1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
2; RUN: opt -passes=loop-vectorize -force-vector-width=2 -force-vector-interleave=1 -S %s | FileCheck %s
3
4
5define i64 @pr62565_incoming_value_known_undef(i64 %a, ptr %src) {
6; CHECK-LABEL: define i64 @pr62565_incoming_value_known_undef
7; CHECK-SAME: (i64 [[A:%.*]], ptr [[SRC:%.*]]) {
8; CHECK-NEXT:  entry:
9; CHECK-NEXT:    br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]]
10; CHECK:       vector.ph:
11; CHECK-NEXT:    br label [[VECTOR_BODY:%.*]]
12; CHECK:       vector.body:
13; CHECK-NEXT:    [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
14; CHECK-NEXT:    [[VEC_PHI:%.*]] = phi <2 x i1> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP5:%.*]], [[VECTOR_BODY]] ]
15; CHECK-NEXT:    [[OFFSET_IDX:%.*]] = add i32 1, [[INDEX]]
16; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[OFFSET_IDX]], 0
17; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i32 [[TMP0]]
18; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i32 0
19; CHECK-NEXT:    [[WIDE_LOAD:%.*]] = load <2 x i32>, ptr [[TMP2]], align 4
20; CHECK-NEXT:    [[TMP3:%.*]] = icmp eq <2 x i32> [[WIDE_LOAD]], splat (i32 1)
21; CHECK-NEXT:    [[TMP4:%.*]] = xor <2 x i1> [[TMP3]], splat (i1 true)
22; CHECK-NEXT:    [[TMP5]] = or <2 x i1> [[VEC_PHI]], [[TMP4]]
23; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i32 [[INDEX]], 2
24; CHECK-NEXT:    [[TMP6:%.*]] = icmp eq i32 [[INDEX_NEXT]], 32
25; CHECK-NEXT:    br i1 [[TMP6]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]]
26; CHECK:       middle.block:
27; CHECK-NEXT:    [[TMP7:%.*]] = call i1 @llvm.vector.reduce.or.v2i1(<2 x i1> [[TMP5]])
28; CHECK-NEXT:    [[TMP8:%.*]] = freeze i1 [[TMP7]]
29; CHECK-NEXT:    [[RDX_SELECT:%.*]] = select i1 [[TMP8]], i64 [[A]], i64 undef
30; CHECK-NEXT:    br i1 true, label [[EXIT:%.*]], label [[SCALAR_PH]]
31; CHECK:       scalar.ph:
32; CHECK-NEXT:    [[BC_RESUME_VAL:%.*]] = phi i32 [ 33, [[MIDDLE_BLOCK]] ], [ 1, [[ENTRY:%.*]] ]
33; CHECK-NEXT:    [[BC_MERGE_RDX:%.*]] = phi i64 [ [[RDX_SELECT]], [[MIDDLE_BLOCK]] ], [ undef, [[ENTRY]] ]
34; CHECK-NEXT:    br label [[LOOP:%.*]]
35; CHECK:       loop:
36; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[ADD:%.*]], [[LOOP]] ]
37; CHECK-NEXT:    [[RED:%.*]] = phi i64 [ [[BC_MERGE_RDX]], [[SCALAR_PH]] ], [ [[SELECT:%.*]], [[LOOP]] ]
38; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i32 [[IV]]
39; CHECK-NEXT:    [[L:%.*]] = load i32, ptr [[GEP]], align 4
40; CHECK-NEXT:    [[C:%.*]] = icmp eq i32 [[L]], 1
41; CHECK-NEXT:    [[SELECT]] = select i1 [[C]], i64 [[RED]], i64 [[A]]
42; CHECK-NEXT:    [[ADD]] = add nuw i32 [[IV]], 1
43; CHECK-NEXT:    [[EC:%.*]] = icmp eq i32 [[IV]], 32
44; CHECK-NEXT:    br i1 [[EC]], label [[EXIT]], label [[LOOP]], !llvm.loop [[LOOP3:![0-9]+]]
45; CHECK:       exit:
46; CHECK-NEXT:    [[PHI:%.*]] = phi i64 [ [[SELECT]], [[LOOP]] ], [ [[RDX_SELECT]], [[MIDDLE_BLOCK]] ]
47; CHECK-NEXT:    ret i64 [[PHI]]
48;
49entry:
50  br label %loop
51
52loop:
53  %iv = phi i32 [ 1, %entry ], [ %add, %loop ]
54  %red = phi i64 [ undef, %entry ], [ %select, %loop ]
55  %gep = getelementptr inbounds i32, ptr %src, i32 %iv
56  %l = load i32, ptr %gep
57  %c = icmp eq i32 %l, 1
58  %select = select i1 %c, i64 %red, i64 %a
59  %add = add nuw i32 %iv, 1
60  %ec = icmp eq i32 %iv, 32
61  br i1 %ec, label %exit, label %loop
62
63exit:
64  %phi = phi i64 [ %select, %loop ]
65  ret i64 %phi
66}
67
68define i64 @pr62565_incoming_value_known_poison(i64 %a, ptr %src) {
69; CHECK-LABEL: define i64 @pr62565_incoming_value_known_poison
70; CHECK-SAME: (i64 [[A:%.*]], ptr [[SRC:%.*]]) {
71; CHECK-NEXT:  entry:
72; CHECK-NEXT:    br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]]
73; CHECK:       vector.ph:
74; CHECK-NEXT:    br label [[VECTOR_BODY:%.*]]
75; CHECK:       vector.body:
76; CHECK-NEXT:    [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
77; CHECK-NEXT:    [[VEC_PHI:%.*]] = phi <2 x i1> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP5:%.*]], [[VECTOR_BODY]] ]
78; CHECK-NEXT:    [[OFFSET_IDX:%.*]] = add i32 1, [[INDEX]]
79; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[OFFSET_IDX]], 0
80; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i32 [[TMP0]]
81; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i32 0
82; CHECK-NEXT:    [[WIDE_LOAD:%.*]] = load <2 x i32>, ptr [[TMP2]], align 4
83; CHECK-NEXT:    [[TMP3:%.*]] = icmp eq <2 x i32> [[WIDE_LOAD]], splat (i32 1)
84; CHECK-NEXT:    [[TMP4:%.*]] = xor <2 x i1> [[TMP3]], splat (i1 true)
85; CHECK-NEXT:    [[TMP5]] = or <2 x i1> [[VEC_PHI]], [[TMP4]]
86; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i32 [[INDEX]], 2
87; CHECK-NEXT:    [[TMP6:%.*]] = icmp eq i32 [[INDEX_NEXT]], 32
88; CHECK-NEXT:    br i1 [[TMP6]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP4:![0-9]+]]
89; CHECK:       middle.block:
90; CHECK-NEXT:    [[TMP7:%.*]] = call i1 @llvm.vector.reduce.or.v2i1(<2 x i1> [[TMP5]])
91; CHECK-NEXT:    [[TMP8:%.*]] = freeze i1 [[TMP7]]
92; CHECK-NEXT:    [[RDX_SELECT:%.*]] = select i1 [[TMP8]], i64 [[A]], i64 poison
93; CHECK-NEXT:    br i1 true, label [[EXIT:%.*]], label [[SCALAR_PH]]
94; CHECK:       scalar.ph:
95; CHECK-NEXT:    [[BC_RESUME_VAL:%.*]] = phi i32 [ 33, [[MIDDLE_BLOCK]] ], [ 1, [[ENTRY:%.*]] ]
96; CHECK-NEXT:    [[BC_MERGE_RDX:%.*]] = phi i64 [ [[RDX_SELECT]], [[MIDDLE_BLOCK]] ], [ poison, [[ENTRY]] ]
97; CHECK-NEXT:    br label [[LOOP:%.*]]
98; CHECK:       loop:
99; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[ADD:%.*]], [[LOOP]] ]
100; CHECK-NEXT:    [[RED:%.*]] = phi i64 [ [[BC_MERGE_RDX]], [[SCALAR_PH]] ], [ [[SELECT:%.*]], [[LOOP]] ]
101; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i32 [[IV]]
102; CHECK-NEXT:    [[L:%.*]] = load i32, ptr [[GEP]], align 4
103; CHECK-NEXT:    [[C:%.*]] = icmp eq i32 [[L]], 1
104; CHECK-NEXT:    [[SELECT]] = select i1 [[C]], i64 [[RED]], i64 [[A]]
105; CHECK-NEXT:    [[ADD]] = add nuw i32 [[IV]], 1
106; CHECK-NEXT:    [[EC:%.*]] = icmp eq i32 [[IV]], 32
107; CHECK-NEXT:    br i1 [[EC]], label [[EXIT]], label [[LOOP]], !llvm.loop [[LOOP5:![0-9]+]]
108; CHECK:       exit:
109; CHECK-NEXT:    [[PHI:%.*]] = phi i64 [ [[SELECT]], [[LOOP]] ], [ [[RDX_SELECT]], [[MIDDLE_BLOCK]] ]
110; CHECK-NEXT:    ret i64 [[PHI]]
111;
112entry:
113  br label %loop
114
115loop:
116  %iv = phi i32 [ 1, %entry ], [ %add, %loop ]
117  %red = phi i64 [ poison, %entry ], [ %select, %loop ]
118  %gep = getelementptr inbounds i32, ptr %src, i32 %iv
119  %l = load i32, ptr %gep
120  %c = icmp eq i32 %l, 1
121  %select = select i1 %c, i64 %red, i64 %a
122  %add = add nuw i32 %iv, 1
123  %ec = icmp eq i32 %iv, 32
124  br i1 %ec, label %exit, label %loop
125
126exit:
127  %phi = phi i64 [ %select, %loop ]
128  ret i64 %phi
129}
130
131define i64 @pr62565_incoming_value_may_be_poison(i64 %a, ptr %src, i64 %start) {
132; CHECK-LABEL: define i64 @pr62565_incoming_value_may_be_poison
133; CHECK-SAME: (i64 [[A:%.*]], ptr [[SRC:%.*]], i64 [[START:%.*]]) {
134; CHECK-NEXT:  entry:
135; CHECK-NEXT:    br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]]
136; CHECK:       vector.ph:
137; CHECK-NEXT:    br label [[VECTOR_BODY:%.*]]
138; CHECK:       vector.body:
139; CHECK-NEXT:    [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
140; CHECK-NEXT:    [[VEC_PHI:%.*]] = phi <2 x i1> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP5:%.*]], [[VECTOR_BODY]] ]
141; CHECK-NEXT:    [[OFFSET_IDX:%.*]] = add i32 1, [[INDEX]]
142; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[OFFSET_IDX]], 0
143; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i32 [[TMP0]]
144; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i32 0
145; CHECK-NEXT:    [[WIDE_LOAD:%.*]] = load <2 x i32>, ptr [[TMP2]], align 4
146; CHECK-NEXT:    [[TMP3:%.*]] = icmp eq <2 x i32> [[WIDE_LOAD]], splat (i32 1)
147; CHECK-NEXT:    [[TMP4:%.*]] = xor <2 x i1> [[TMP3]], splat (i1 true)
148; CHECK-NEXT:    [[TMP5]] = or <2 x i1> [[VEC_PHI]], [[TMP4]]
149; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i32 [[INDEX]], 2
150; CHECK-NEXT:    [[TMP6:%.*]] = icmp eq i32 [[INDEX_NEXT]], 32
151; CHECK-NEXT:    br i1 [[TMP6]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP6:![0-9]+]]
152; CHECK:       middle.block:
153; CHECK-NEXT:    [[TMP7:%.*]] = call i1 @llvm.vector.reduce.or.v2i1(<2 x i1> [[TMP5]])
154; CHECK-NEXT:    [[TMP8:%.*]] = freeze i1 [[TMP7]]
155; CHECK-NEXT:    [[RDX_SELECT:%.*]] = select i1 [[TMP8]], i64 [[A]], i64 [[START]]
156; CHECK-NEXT:    br i1 true, label [[EXIT:%.*]], label [[SCALAR_PH]]
157; CHECK:       scalar.ph:
158; CHECK-NEXT:    [[BC_RESUME_VAL:%.*]] = phi i32 [ 33, [[MIDDLE_BLOCK]] ], [ 1, [[ENTRY:%.*]] ]
159; CHECK-NEXT:    [[BC_MERGE_RDX:%.*]] = phi i64 [ [[RDX_SELECT]], [[MIDDLE_BLOCK]] ], [ [[START]], [[ENTRY]] ]
160; CHECK-NEXT:    br label [[LOOP:%.*]]
161; CHECK:       loop:
162; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[ADD:%.*]], [[LOOP]] ]
163; CHECK-NEXT:    [[RED:%.*]] = phi i64 [ [[BC_MERGE_RDX]], [[SCALAR_PH]] ], [ [[SELECT:%.*]], [[LOOP]] ]
164; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i32 [[IV]]
165; CHECK-NEXT:    [[L:%.*]] = load i32, ptr [[GEP]], align 4
166; CHECK-NEXT:    [[C:%.*]] = icmp eq i32 [[L]], 1
167; CHECK-NEXT:    [[SELECT]] = select i1 [[C]], i64 [[RED]], i64 [[A]]
168; CHECK-NEXT:    [[ADD]] = add nuw i32 [[IV]], 1
169; CHECK-NEXT:    [[EC:%.*]] = icmp eq i32 [[IV]], 32
170; CHECK-NEXT:    br i1 [[EC]], label [[EXIT]], label [[LOOP]], !llvm.loop [[LOOP7:![0-9]+]]
171; CHECK:       exit:
172; CHECK-NEXT:    [[PHI:%.*]] = phi i64 [ [[SELECT]], [[LOOP]] ], [ [[RDX_SELECT]], [[MIDDLE_BLOCK]] ]
173; CHECK-NEXT:    ret i64 [[PHI]]
174;
175entry:
176  br label %loop
177
178loop:
179  %iv = phi i32 [ 1, %entry ], [ %add, %loop ]
180  %red = phi i64 [ %start, %entry ], [ %select, %loop ]
181  %gep = getelementptr inbounds i32, ptr %src, i32 %iv
182  %l = load i32, ptr %gep
183  %c = icmp eq i32 %l, 1
184  %select = select i1 %c, i64 %red, i64 %a
185  %add = add nuw i32 %iv, 1
186  %ec = icmp eq i32 %iv, 32
187  br i1 %ec, label %exit, label %loop
188
189exit:
190  %phi = phi i64 [ %select, %loop ]
191  ret i64 %phi
192}
193