xref: /llvm-project/llvm/test/Transforms/CorrelatedValuePropagation/vectors.ll (revision 7a7a426188eea0b181738436205759e13ad6fd7b)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2; RUN: opt -S -passes=correlated-propagation < %s | FileCheck %s
3
4define <2 x i1> @cmp1(<2 x i8> %a) {
5; CHECK-LABEL: define <2 x i1> @cmp1(
6; CHECK-SAME: <2 x i8> [[A:%.*]]) {
7; CHECK-NEXT:    [[ADD:%.*]] = add nuw <2 x i8> [[A]], splat (i8 1)
8; CHECK-NEXT:    ret <2 x i1> splat (i1 true)
9;
10  %add = add nuw <2 x i8> %a, splat (i8 1)
11  %cmp = icmp ne <2 x i8> %add, zeroinitializer
12  ret <2 x i1> %cmp
13}
14
15define <2 x i1> @cmp2(<2 x i8> %a) {
16; CHECK-LABEL: define <2 x i1> @cmp2(
17; CHECK-SAME: <2 x i8> [[A:%.*]]) {
18; CHECK-NEXT:    [[ADD:%.*]] = add nuw <2 x i8> [[A]], splat (i8 5)
19; CHECK-NEXT:    ret <2 x i1> splat (i1 true)
20;
21  %add = add nuw <2 x i8> %a, splat (i8 5)
22  %cmp = icmp ugt <2 x i8> %add, splat (i8 2)
23  ret <2 x i1> %cmp
24}
25
26define <2 x i1> @cmp_nonsplat(<2 x i8> %a) {
27; CHECK-LABEL: define <2 x i1> @cmp_nonsplat(
28; CHECK-SAME: <2 x i8> [[A:%.*]]) {
29; CHECK-NEXT:    [[ADD:%.*]] = add nuw <2 x i8> [[A]], <i8 4, i8 5>
30; CHECK-NEXT:    ret <2 x i1> splat (i1 true)
31;
32  %add = add nuw <2 x i8> %a, <i8 4, i8 5>
33  %cmp = icmp ugt <2 x i8> %add, <i8 2, i8 3>
34  ret <2 x i1> %cmp
35}
36
37; Handling this would require keeping track of ranges on a per-element basis.
38define <2 x i1> @cmp_nonsplat_fail(<2 x i8> %a) {
39; CHECK-LABEL: define <2 x i1> @cmp_nonsplat_fail(
40; CHECK-SAME: <2 x i8> [[A:%.*]]) {
41; CHECK-NEXT:    [[ADD:%.*]] = add nuw <2 x i8> [[A]], <i8 3, i8 4>
42; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt <2 x i8> [[ADD]], <i8 2, i8 3>
43; CHECK-NEXT:    ret <2 x i1> [[CMP]]
44;
45  %add = add nuw <2 x i8> %a, <i8 3, i8 4>
46  %cmp = icmp ugt <2 x i8> %add, <i8 2, i8 3>
47  ret <2 x i1> %cmp
48}
49
50define <2 x i1> @cmp_signedness(<2 x i8> %a) {
51; CHECK-LABEL: define <2 x i1> @cmp_signedness(
52; CHECK-SAME: <2 x i8> [[A:%.*]]) {
53; CHECK-NEXT:    [[ZEXT:%.*]] = zext <2 x i8> [[A]] to <2 x i16>
54; CHECK-NEXT:    [[CMP:%.*]] = icmp samesign ult <2 x i16> [[ZEXT]], splat (i16 5)
55; CHECK-NEXT:    ret <2 x i1> [[CMP]]
56;
57  %zext = zext <2 x i8> %a to <2 x i16>
58  %cmp = icmp slt <2 x i16> %zext, splat (i16 5)
59  ret <2 x i1> %cmp
60}
61
62define <2 x i16> @infer_nowrap(<2 x i8> %a) {
63; CHECK-LABEL: define range(i16 1, 257) <2 x i16> @infer_nowrap(
64; CHECK-SAME: <2 x i8> [[A:%.*]]) {
65; CHECK-NEXT:    [[ZEXT:%.*]] = zext <2 x i8> [[A]] to <2 x i16>
66; CHECK-NEXT:    [[RES:%.*]] = add nuw nsw <2 x i16> [[ZEXT]], splat (i16 1)
67; CHECK-NEXT:    ret <2 x i16> [[RES]]
68;
69  %zext = zext <2 x i8> %a to <2 x i16>
70  %res = add <2 x i16> %zext, splat (i16 1)
71  ret <2 x i16> %res
72}
73
74define <2 x i16> @infer_nowrap_nonsplat(<2 x i8> %a) {
75; CHECK-LABEL: define range(i16 1, 258) <2 x i16> @infer_nowrap_nonsplat(
76; CHECK-SAME: <2 x i8> [[A:%.*]]) {
77; CHECK-NEXT:    [[ZEXT:%.*]] = zext <2 x i8> [[A]] to <2 x i16>
78; CHECK-NEXT:    [[RES:%.*]] = add nuw nsw <2 x i16> [[ZEXT]], <i16 1, i16 2>
79; CHECK-NEXT:    ret <2 x i16> [[RES]]
80;
81  %zext = zext <2 x i8> %a to <2 x i16>
82  %res = add <2 x i16> %zext, <i16 1, i16 2>
83  ret <2 x i16> %res
84}
85
86define <vscale x 2 x i16> @infer_nowrap_scalable(<vscale x 2 x i8> %a) {
87; CHECK-LABEL: define range(i16 1, 257) <vscale x 2 x i16> @infer_nowrap_scalable(
88; CHECK-SAME: <vscale x 2 x i8> [[A:%.*]]) {
89; CHECK-NEXT:    [[ZEXT:%.*]] = zext <vscale x 2 x i8> [[A]] to <vscale x 2 x i16>
90; CHECK-NEXT:    [[RES:%.*]] = add nuw nsw <vscale x 2 x i16> [[ZEXT]], splat (i16 1)
91; CHECK-NEXT:    ret <vscale x 2 x i16> [[RES]]
92;
93  %zext = zext <vscale x 2 x i8> %a to <vscale x 2 x i16>
94  %res = add <vscale x 2 x i16> %zext, splat (i16 1)
95  ret <vscale x 2 x i16> %res
96}
97
98define <2 x i16> @infer_nowrap_poison(<2 x i8> %a) {
99; CHECK-LABEL: define range(i16 1, 257) <2 x i16> @infer_nowrap_poison(
100; CHECK-SAME: <2 x i8> [[A:%.*]]) {
101; CHECK-NEXT:    [[ZEXT:%.*]] = zext <2 x i8> [[A]] to <2 x i16>
102; CHECK-NEXT:    [[RES:%.*]] = add nuw nsw <2 x i16> [[ZEXT]], <i16 1, i16 poison>
103; CHECK-NEXT:    ret <2 x i16> [[RES]]
104;
105  %zext = zext <2 x i8> %a to <2 x i16>
106  %res = add <2 x i16> %zext, <i16 1, i16 poison>
107  ret <2 x i16> %res
108}
109
110define <2 x i16> @infer_nowrap_nonsplat_nsw_only(<2 x i8> %a) {
111; CHECK-LABEL: define range(i16 -1, 257) <2 x i16> @infer_nowrap_nonsplat_nsw_only(
112; CHECK-SAME: <2 x i8> [[A:%.*]]) {
113; CHECK-NEXT:    [[ZEXT:%.*]] = zext <2 x i8> [[A]] to <2 x i16>
114; CHECK-NEXT:    [[RES:%.*]] = add nsw <2 x i16> [[ZEXT]], <i16 1, i16 -1>
115; CHECK-NEXT:    ret <2 x i16> [[RES]]
116;
117  %zext = zext <2 x i8> %a to <2 x i16>
118  %res = add <2 x i16> %zext, <i16 1, i16 -1>
119  ret <2 x i16> %res
120}
121
122define <2 x i16> @abs(<2 x i8> %a) {
123; CHECK-LABEL: define range(i16 0, 256) <2 x i16> @abs(
124; CHECK-SAME: <2 x i8> [[A:%.*]]) {
125; CHECK-NEXT:    [[ZEXT:%.*]] = zext <2 x i8> [[A]] to <2 x i16>
126; CHECK-NEXT:    ret <2 x i16> [[ZEXT]]
127;
128  %zext = zext <2 x i8> %a to <2 x i16>
129  %res = call <2 x i16> @llvm.abs(<2 x i16> %zext, i1 false)
130  ret <2 x i16> %res
131}
132
133define <2 x i16> @saturating(<2 x i8> %a) {
134; CHECK-LABEL: define range(i16 1, 257) <2 x i16> @saturating(
135; CHECK-SAME: <2 x i8> [[A:%.*]]) {
136; CHECK-NEXT:    [[ZEXT:%.*]] = zext <2 x i8> [[A]] to <2 x i16>
137; CHECK-NEXT:    [[RES:%.*]] = add nuw nsw <2 x i16> [[ZEXT]], splat (i16 1)
138; CHECK-NEXT:    ret <2 x i16> [[RES]]
139;
140  %zext = zext <2 x i8> %a to <2 x i16>
141  %res = call <2 x i16> @llvm.uadd.sat(<2 x i16> %zext, <2 x i16> splat (i16 1))
142  ret <2 x i16> %res
143}
144
145define {<2 x i16>, <2 x i1>} @with_overflow(<2 x i8> %a) {
146; CHECK-LABEL: define { <2 x i16>, <2 x i1> } @with_overflow(
147; CHECK-SAME: <2 x i8> [[A:%.*]]) {
148; CHECK-NEXT:    [[ZEXT:%.*]] = zext <2 x i8> [[A]] to <2 x i16>
149; CHECK-NEXT:    [[RES1:%.*]] = add nuw nsw <2 x i16> [[ZEXT]], splat (i16 1)
150; CHECK-NEXT:    [[RES:%.*]] = insertvalue { <2 x i16>, <2 x i1> } { <2 x i16> poison, <2 x i1> zeroinitializer }, <2 x i16> [[RES1]], 0
151; CHECK-NEXT:    ret { <2 x i16>, <2 x i1> } [[RES]]
152;
153  %zext = zext <2 x i8> %a to <2 x i16>
154  %res = call {<2 x i16>, <2 x i1>} @llvm.uadd.with.overflow(<2 x i16> %zext, <2 x i16> splat (i16 1))
155  ret {<2 x i16>, <2 x i1>} %res
156}
157
158define <2 x i16> @srem1(<2 x i8> %a) {
159; CHECK-LABEL: define range(i16 0, 42) <2 x i16> @srem1(
160; CHECK-SAME: <2 x i8> [[A:%.*]]) {
161; CHECK-NEXT:    [[ZEXT:%.*]] = zext <2 x i8> [[A]] to <2 x i16>
162; CHECK-NEXT:    [[RES1_LHS_TRUNC:%.*]] = trunc <2 x i16> [[ZEXT]] to <2 x i8>
163; CHECK-NEXT:    [[RES12:%.*]] = urem <2 x i8> [[RES1_LHS_TRUNC]], splat (i8 42)
164; CHECK-NEXT:    [[RES:%.*]] = zext <2 x i8> [[RES12]] to <2 x i16>
165; CHECK-NEXT:    ret <2 x i16> [[RES]]
166;
167  %zext = zext <2 x i8> %a to <2 x i16>
168  %res = srem <2 x i16> %zext, splat (i16 42)
169  ret <2 x i16> %res
170}
171
172define <2 x i16> @srem2(<2 x i8> %a) {
173; CHECK-LABEL: define range(i16 -41, 42) <2 x i16> @srem2(
174; CHECK-SAME: <2 x i8> [[A:%.*]]) {
175; CHECK-NEXT:    [[ZEXT:%.*]] = sext <2 x i8> [[A]] to <2 x i16>
176; CHECK-NEXT:    [[RES_LHS_TRUNC:%.*]] = trunc <2 x i16> [[ZEXT]] to <2 x i8>
177; CHECK-NEXT:    [[RES1:%.*]] = srem <2 x i8> [[RES_LHS_TRUNC]], splat (i8 42)
178; CHECK-NEXT:    [[RES:%.*]] = sext <2 x i8> [[RES1]] to <2 x i16>
179; CHECK-NEXT:    ret <2 x i16> [[RES]]
180;
181  %zext = sext <2 x i8> %a to <2 x i16>
182  %res = srem <2 x i16> %zext, splat (i16 42)
183  ret <2 x i16> %res
184}
185
186define <2 x i16> @ashr(<2 x i8> %a) {
187; CHECK-LABEL: define range(i16 0, 128) <2 x i16> @ashr(
188; CHECK-SAME: <2 x i8> [[A:%.*]]) {
189; CHECK-NEXT:    [[ZEXT:%.*]] = zext <2 x i8> [[A]] to <2 x i16>
190; CHECK-NEXT:    [[RES:%.*]] = lshr <2 x i16> [[ZEXT]], splat (i16 1)
191; CHECK-NEXT:    ret <2 x i16> [[RES]]
192;
193  %zext = zext <2 x i8> %a to <2 x i16>
194  %res = ashr <2 x i16> %zext, splat (i16 1)
195  ret <2 x i16> %res
196}
197
198define <2 x i32> @sext(<2 x i8> %a) {
199; CHECK-LABEL: define range(i32 0, 256) <2 x i32> @sext(
200; CHECK-SAME: <2 x i8> [[A:%.*]]) {
201; CHECK-NEXT:    [[ZEXT:%.*]] = zext <2 x i8> [[A]] to <2 x i16>
202; CHECK-NEXT:    [[RES:%.*]] = zext nneg <2 x i16> [[ZEXT]] to <2 x i32>
203; CHECK-NEXT:    ret <2 x i32> [[RES]]
204;
205  %zext = zext <2 x i8> %a to <2 x i16>
206  %res = sext <2 x i16> %zext to <2 x i32>
207  ret <2 x i32> %res
208}
209
210define <2 x float> @sitofp(<2 x i8> %a) {
211; CHECK-LABEL: define <2 x float> @sitofp(
212; CHECK-SAME: <2 x i8> [[A:%.*]]) {
213; CHECK-NEXT:    [[ZEXT:%.*]] = zext <2 x i8> [[A]] to <2 x i16>
214; CHECK-NEXT:    [[RES:%.*]] = uitofp nneg <2 x i16> [[ZEXT]] to <2 x float>
215; CHECK-NEXT:    ret <2 x float> [[RES]]
216;
217  %zext = zext <2 x i8> %a to <2 x i16>
218  %res = sitofp <2 x i16> %zext to <2 x float>
219  ret <2 x float> %res
220}
221
222define <2 x i16> @and(<2 x i8> %a) {
223; CHECK-LABEL: define range(i16 0, 256) <2 x i16> @and(
224; CHECK-SAME: <2 x i8> [[A:%.*]]) {
225; CHECK-NEXT:    [[ZEXT:%.*]] = zext <2 x i8> [[A]] to <2 x i16>
226; CHECK-NEXT:    ret <2 x i16> [[ZEXT]]
227;
228  %zext = zext <2 x i8> %a to <2 x i16>
229  %res = and <2 x i16> %zext, splat (i16 u0xff)
230  ret <2 x i16> %res
231}
232
233define <2 x i16> @and_with_poison(<2 x i8> %a) {
234; CHECK-LABEL: define range(i16 0, 256) <2 x i16> @and_with_poison(
235; CHECK-SAME: <2 x i8> [[A:%.*]]) {
236; CHECK-NEXT:    [[ZEXT:%.*]] = zext <2 x i8> [[A]] to <2 x i16>
237; CHECK-NEXT:    ret <2 x i16> [[ZEXT]]
238;
239  %zext = zext <2 x i8> %a to <2 x i16>
240  %res = and <2 x i16> %zext, <i16 u0xff, i16 poison>
241  ret <2 x i16> %res
242}
243
244define <4 x i64> @issue_97674_getConstantOnEdge(i1 %cond) {
245; CHECK-LABEL: define range(i64 0, 2) <4 x i64> @issue_97674_getConstantOnEdge(
246; CHECK-SAME: i1 [[COND:%.*]]) {
247; CHECK-NEXT:  [[ENTRY:.*]]:
248; CHECK-NEXT:    br i1 [[COND]], label %[[IF_THEN:.*]], label %[[IF_END:.*]]
249; CHECK:       [[IF_THEN]]:
250; CHECK-NEXT:    [[FOLDS:%.*]] = add nuw nsw <4 x i64> zeroinitializer, splat (i64 1)
251; CHECK-NEXT:    br label %[[IF_END]]
252; CHECK:       [[IF_END]]:
253; CHECK-NEXT:    [[R:%.*]] = phi <4 x i64> [ splat (i64 1), %[[IF_THEN]] ], [ zeroinitializer, %[[ENTRY]] ]
254; CHECK-NEXT:    ret <4 x i64> [[R]]
255;
256entry:
257  br i1 %cond, label %if.then, label %if.end
258
259if.then:
260  %folds = add <4 x i64> zeroinitializer, <i64 1, i64 1, i64 1, i64 1>
261  br label %if.end
262
263if.end:
264  %r = phi <4 x i64> [ %folds, %if.then ], [ zeroinitializer, %entry ]
265  ret <4 x i64> %r
266}
267
268define <4 x i64> @issue_97674_getConstant() {
269; CHECK-LABEL: define <4 x i64> @issue_97674_getConstant() {
270; CHECK-NEXT:  [[ENTRY:.*:]]
271; CHECK-NEXT:    [[FOLDS:%.*]] = add nuw nsw <4 x i64> zeroinitializer, zeroinitializer
272; CHECK-NEXT:    ret <4 x i64> zeroinitializer
273;
274entry:
275  %folds = add <4 x i64> zeroinitializer, zeroinitializer
276  ret <4 x i64> %folds
277}
278
279define <2 x i16> @phi_merge1(i1 %c, <2 x i8> %a) {
280; CHECK-LABEL: define range(i16 2, 259) <2 x i16> @phi_merge1(
281; CHECK-SAME: i1 [[C:%.*]], <2 x i8> [[A:%.*]]) {
282; CHECK-NEXT:  [[ENTRY:.*]]:
283; CHECK-NEXT:    [[ZEXT:%.*]] = zext <2 x i8> [[A]] to <2 x i16>
284; CHECK-NEXT:    br i1 [[C]], label %[[IF:.*]], label %[[JOIN:.*]]
285; CHECK:       [[IF]]:
286; CHECK-NEXT:    br label %[[JOIN]]
287; CHECK:       [[JOIN]]:
288; CHECK-NEXT:    [[PHI:%.*]] = phi <2 x i16> [ [[ZEXT]], %[[ENTRY]] ], [ <i16 1, i16 2>, %[[IF]] ]
289; CHECK-NEXT:    [[ADD:%.*]] = add nuw nsw <2 x i16> [[PHI]], <i16 2, i16 3>
290; CHECK-NEXT:    ret <2 x i16> [[ADD]]
291;
292entry:
293  %zext = zext <2 x i8> %a to <2 x i16>
294  br i1 %c, label %if, label %join
295
296if:
297  br label %join
298
299join:
300  %phi = phi <2 x i16> [ %zext, %entry ], [ <i16 1, i16 2>, %if ]
301  %add = add <2 x i16> %phi, <i16 2, i16 3>
302  ret <2 x i16> %add
303}
304
305define <2 x i16> @phi_merge2(i1 %c, <2 x i8> %a) {
306; CHECK-LABEL: define range(i16 2, 259) <2 x i16> @phi_merge2(
307; CHECK-SAME: i1 [[C:%.*]], <2 x i8> [[A:%.*]]) {
308; CHECK-NEXT:  [[ENTRY:.*]]:
309; CHECK-NEXT:    [[ZEXT:%.*]] = zext <2 x i8> [[A]] to <2 x i16>
310; CHECK-NEXT:    br i1 [[C]], label %[[IF:.*]], label %[[JOIN:.*]]
311; CHECK:       [[IF]]:
312; CHECK-NEXT:    br label %[[JOIN]]
313; CHECK:       [[JOIN]]:
314; CHECK-NEXT:    [[PHI:%.*]] = phi <2 x i16> [ <i16 1, i16 2>, %[[ENTRY]] ], [ [[ZEXT]], %[[IF]] ]
315; CHECK-NEXT:    [[ADD:%.*]] = add nuw nsw <2 x i16> [[PHI]], <i16 2, i16 3>
316; CHECK-NEXT:    ret <2 x i16> [[ADD]]
317;
318entry:
319  %zext = zext <2 x i8> %a to <2 x i16>
320  br i1 %c, label %if, label %join
321
322if:
323  br label %join
324
325join:
326  %phi = phi <2 x i16> [ <i16 1, i16 2>, %entry ], [ %zext, %if ]
327  %add = add <2 x i16> %phi, <i16 2, i16 3>
328  ret <2 x i16> %add
329}
330
331;; Check if ICMP instruction is constant folded or not.
332define <2 x i1> @insertelement_fold1() {
333; CHECK-LABEL: define <2 x i1> @insertelement_fold1() {
334; CHECK-NEXT:    [[IE1:%.*]] = insertelement <2 x i32> poison, i32 10, i64 0
335; CHECK-NEXT:    [[IE2:%.*]] = insertelement <2 x i32> [[IE1]], i32 20, i64 1
336; CHECK-NEXT:    ret <2 x i1> splat (i1 true)
337;
338  %ie1 = insertelement <2 x i32> poison, i32 10, i64 0
339  %ie2 = insertelement <2 x i32> %ie1, i32 20, i64 1
340  %icmp1 = icmp slt <2 x i32> %ie2, <i32 1024, i32 1024>
341  ret <2 x i1> %icmp1
342}
343
344;; Check if LVI is able to handle constant vector operands
345;; in InsertElementInst and CVP is able to fold ICMP instruction.
346define <2 x i1> @insertelement_fold2() {
347; CHECK-LABEL: define <2 x i1> @insertelement_fold2() {
348; CHECK-NEXT:    [[IE1:%.*]] = insertelement <2 x i32> <i32 poison, i32 20>, i32 10, i64 0
349; CHECK-NEXT:    ret <2 x i1> splat (i1 true)
350;
351  %ie1 = insertelement <2 x i32> <i32 poison, i32 20>, i32 10, i64 0
352  %icmp1 = icmp slt <2 x i32> %ie1, <i32 1024, i32 1024>
353  ret <2 x i1> %icmp1
354}
355
356@g = external global i32
357
358define <2 x i16> @insertelement_constexpr() {
359; CHECK-LABEL: define <2 x i16> @insertelement_constexpr() {
360; CHECK-NEXT:    [[INS:%.*]] = insertelement <2 x i16> poison, i16 ptrtoint (ptr @g to i16), i32 0
361; CHECK-NEXT:    ret <2 x i16> [[INS]]
362;
363  %ins = insertelement <2 x i16> poison, i16 ptrtoint (ptr @g to i16), i32 0
364  ret <2 x i16> %ins
365}
366