• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -reassociate -S | FileCheck %s
3
4; Basic pattern where two contiguous i8 loads form a wider i16 load
5define i16 @p0_i8_i8_i16(i8* %ptr) {
6; CHECK-LABEL: @p0_i8_i8_i16(
7; CHECK-NEXT:    [[I:%.*]] = getelementptr inbounds i8, i8* [[PTR:%.*]], i64 1
8; CHECK-NEXT:    [[I2:%.*]] = load i8, i8* [[I]], align 1
9; CHECK-NEXT:    [[I3:%.*]] = zext i8 [[I2]] to i16
10; CHECK-NEXT:    [[I4:%.*]] = shl i16 [[I3]], 8
11; CHECK-NEXT:    [[I5:%.*]] = load i8, i8* [[PTR]], align 1
12; CHECK-NEXT:    [[I6:%.*]] = zext i8 [[I5]] to i16
13; CHECK-NEXT:    [[I7:%.*]] = or i16 [[I4]], [[I6]]
14; CHECK-NEXT:    [[I8:%.*]] = add i16 [[I7]], 42
15; CHECK-NEXT:    ret i16 [[I8]]
16;
17  %i = getelementptr inbounds i8, i8* %ptr, i64 1
18  %i2 = load i8, i8* %i
19  %i3 = zext i8 %i2 to i16
20  %i4 = shl i16 %i3, 8
21  %i5 = load i8, i8* %ptr
22  %i6 = zext i8 %i5 to i16
23  %i7 = or i16 %i4, %i6
24  %i8 = add i16 %i7, 42
25  ret i16 %i8
26}
27
28; Basic pattern where two contiguous i8 loads form a wider i16 load, with swapped endianness
29define i16 @p1_i8_i8_i16_swapped(i8* %ptr) {
30; CHECK-LABEL: @p1_i8_i8_i16_swapped(
31; CHECK-NEXT:    [[I:%.*]] = load i8, i8* [[PTR:%.*]], align 1
32; CHECK-NEXT:    [[I2:%.*]] = zext i8 [[I]] to i16
33; CHECK-NEXT:    [[I3:%.*]] = shl i16 [[I2]], 8
34; CHECK-NEXT:    [[I4:%.*]] = getelementptr inbounds i8, i8* [[PTR]], i64 1
35; CHECK-NEXT:    [[I5:%.*]] = load i8, i8* [[I4]], align 1
36; CHECK-NEXT:    [[I6:%.*]] = zext i8 [[I5]] to i16
37; CHECK-NEXT:    [[I7:%.*]] = or i16 [[I3]], [[I6]]
38; CHECK-NEXT:    [[I8:%.*]] = add i16 [[I7]], 42
39; CHECK-NEXT:    ret i16 [[I8]]
40;
41  %i = load i8, i8* %ptr
42  %i2 = zext i8 %i to i16
43  %i3 = shl i16 %i2, 8
44  %i4 = getelementptr inbounds i8, i8* %ptr, i64 1
45  %i5 = load i8, i8* %i4
46  %i6 = zext i8 %i5 to i16
47  %i7 = or i16 %i3, %i6
48  %i8 = add i16 %i7, 42
49  ret i16 %i8
50}
51
52; Loads are spaced out by a bit, but we don't check for that.
53define i16 @p2(i8* %ptr) {
54; CHECK-LABEL: @p2(
55; CHECK-NEXT:    [[I:%.*]] = getelementptr inbounds i8, i8* [[PTR:%.*]], i64 1
56; CHECK-NEXT:    [[I2:%.*]] = load i8, i8* [[I]], align 1
57; CHECK-NEXT:    [[I3:%.*]] = zext i8 [[I2]] to i16
58; CHECK-NEXT:    [[I4:%.*]] = shl i16 [[I3]], 9
59; CHECK-NEXT:    [[I5:%.*]] = load i8, i8* [[PTR]], align 1
60; CHECK-NEXT:    [[I6:%.*]] = zext i8 [[I5]] to i16
61; CHECK-NEXT:    [[I7:%.*]] = or i16 [[I4]], [[I6]]
62; CHECK-NEXT:    [[I8:%.*]] = add i16 [[I7]], 42
63; CHECK-NEXT:    ret i16 [[I8]]
64;
65  %i = getelementptr inbounds i8, i8* %ptr, i64 1
66  %i2 = load i8, i8* %i
67  %i3 = zext i8 %i2 to i16
68  %i4 = shl i16 %i3, 9 ; wrong shift amount
69  %i5 = load i8, i8* %ptr
70  %i6 = zext i8 %i5 to i16
71  %i7 = or i16 %i4, %i6
72  %i8 = add i16 %i7, 42
73  ret i16 %i8
74}
75
76; Both bytes are the same, but we don't check for that.
77define i16 @p3(i8* %ptr) {
78; CHECK-LABEL: @p3(
79; CHECK-NEXT:    [[I:%.*]] = load i8, i8* [[PTR:%.*]], align 1
80; CHECK-NEXT:    [[I2:%.*]] = zext i8 [[I]] to i16
81; CHECK-NEXT:    [[I3:%.*]] = shl i16 [[I2]], 8
82; CHECK-NEXT:    [[I4:%.*]] = or i16 [[I3]], [[I2]]
83; CHECK-NEXT:    [[I5:%.*]] = add i16 [[I4]], 42
84; CHECK-NEXT:    ret i16 [[I5]]
85;
86  %i = load i8, i8* %ptr
87  %i2 = zext i8 %i to i16
88  %i3 = shl i16 %i2, 8
89  %i4 = or i16 %i3, %i2
90  %i5 = add i16 %i4, 42
91  ret i16 %i5
92}
93
94; ---------------------------------------------------------------------------- ;
95; Negative tests, should be transformed.
96
97; Low bits are not a load
98define i16 @n4(i8* %ptr) {
99; CHECK-LABEL: @n4(
100; CHECK-NEXT:    [[I:%.*]] = load i8, i8* [[PTR:%.*]], align 1
101; CHECK-NEXT:    [[I2:%.*]] = zext i8 [[I]] to i16
102; CHECK-NEXT:    [[I3:%.*]] = shl i16 [[I2]], 8
103; CHECK-NEXT:    [[I5:%.*]] = add i16 [[I3]], 84
104; CHECK-NEXT:    ret i16 [[I5]]
105;
106  %i = load i8, i8* %ptr
107  %i2 = zext i8 %i to i16
108  %i3 = shl i16 %i2, 8
109  %i4 = or i16 %i3, 42 ; Second operand is bad
110  %i5 = add i16 %i4, 42
111  ret i16 %i5
112}
113
114; Low bits are not a load
115define i16 @n5(i8* %ptr, i8 %lowbits) {
116; CHECK-LABEL: @n5(
117; CHECK-NEXT:    [[I:%.*]] = load i8, i8* [[PTR:%.*]], align 1
118; CHECK-NEXT:    [[I2:%.*]] = zext i8 [[I]] to i16
119; CHECK-NEXT:    [[I3:%.*]] = shl i16 [[I2]], 8
120; CHECK-NEXT:    [[I4:%.*]] = zext i8 [[LOWBITS:%.*]] to i16
121; CHECK-NEXT:    [[I5:%.*]] = add i16 [[I4]], 42
122; CHECK-NEXT:    [[I6:%.*]] = add i16 [[I5]], [[I3]]
123; CHECK-NEXT:    ret i16 [[I6]]
124;
125  %i = load i8, i8* %ptr
126  %i2 = zext i8 %i to i16
127  %i3 = shl i16 %i2, 8
128  %i4 = zext i8 %lowbits to i16 ; base operand is bad
129  %i5 = or i16 %i3, %i4
130  %i6 = add i16 %i5, 42
131  ret i16 %i6
132}
133
134; High bits are not a load
135define i16 @n6(i8* %ptr, i8 %highbits) {
136; CHECK-LABEL: @n6(
137; CHECK-NEXT:    [[I:%.*]] = getelementptr inbounds i8, i8* [[PTR:%.*]], i64 1
138; CHECK-NEXT:    [[I4:%.*]] = shl i16 42, 8
139; CHECK-NEXT:    [[I5:%.*]] = load i8, i8* [[PTR]], align 1
140; CHECK-NEXT:    [[I6:%.*]] = zext i8 [[I5]] to i16
141; CHECK-NEXT:    [[I7:%.*]] = add i16 [[I4]], 42
142; CHECK-NEXT:    [[I8:%.*]] = add i16 [[I7]], [[I6]]
143; CHECK-NEXT:    ret i16 [[I8]]
144;
145  %i = getelementptr inbounds i8, i8* %ptr, i64 1
146  %i2 = load i8, i8* %i
147  %i4 = shl i16 42, 8 ; base operand is bad
148  %i5 = load i8, i8* %ptr
149  %i6 = zext i8 %i5 to i16
150  %i7 = or i16 %i4, %i6
151  %i8 = add i16 %i7, 42
152  ret i16 %i8
153}
154