llvm.org GIT mirror llvm / 3c0efb7
[InstSimplify] fold select with implied condition This is an almost direct move of the functionality from InstCombine to InstSimplify. There's no reason not to do this in InstSimplify because we never create a new value with this transform. (There's a question of whether any dominance-based transform belongs in either of these passes, but that's a separate issue.) I've changed 1 of the conditions for the fold (1 of the blocks for the branch must be the block we started with) into an assert because I'm not sure how that could ever be false. We need 1 extra check to make sure that the instruction itself is in a basic block because passes other than InstCombine may be using InstSimplify as an analysis on values that are not wired up yet. The 3-way compare changes show that InstCombine has some kind of phase-ordering hole. Otherwise, we would have already gotten the intended final result that we now show here. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@347896 91177308-0d34-0410-b5e6-96231b3b80d8 Sanjay Patel 10 months ago
5 changed file(s) with 317 addition(s) and 306 deletion(s). Raw diff Collapse all Expand all
39233923 return nullptr;
39243924 }
39253925
3926 /// Try to determine the result of a select based on a dominating condition.
3927 static Value *foldSelectWithDominatingCond(Value *Cond, Value *TV, Value *FV,
3928 const SimplifyQuery &Q) {
3929 // First, make sure that we have a select in a basic block.
3930 // We don't know if we are called from some incomplete state.
3931 if (!Q.CxtI || !Q.CxtI->getParent())
3932 return nullptr;
3933
3934 // TODO: This is a poor/cheap way to determine dominance. Should we use the
3935 // dominator tree in the SimplifyQuery instead?
3936 const BasicBlock *SelectBB = Q.CxtI->getParent();
3937 const BasicBlock *PredBB = SelectBB->getSinglePredecessor();
3938 if (!PredBB)
3939 return nullptr;
3940
3941 // We need a conditional branch in the predecessor.
3942 Value *PredCond;
3943 BasicBlock *TrueBB, *FalseBB;
3944 if (!match(PredBB->getTerminator(), m_Br(m_Value(PredCond), TrueBB, FalseBB)))
3945 return nullptr;
3946
3947 // The branch should get simplified. Don't bother simplifying the select.
3948 if (TrueBB == FalseBB)
3949 return nullptr;
3950
3951 assert((TrueBB == SelectBB || FalseBB == SelectBB) &&
3952 "Predecessor block does not point to successor?");
3953
3954 // Is the select condition implied by the predecessor condition?
3955 bool CondIsTrue = TrueBB == SelectBB;
3956 Optional Implied = isImpliedCondition(PredCond, Cond, Q.DL, CondIsTrue);
3957 if (!Implied)
3958 return nullptr;
3959 return *Implied ? TV : FV;
3960 }
3961
39263962 /// Given operands for a SelectInst, see if we can fold the result.
39273963 /// If not, this returns null.
39283964 static Value *SimplifySelectInst(Value *Cond, Value *TrueVal, Value *FalseVal,
39633999 return V;
39644000
39654001 if (Value *V = foldSelectWithBinaryOp(Cond, TrueVal, FalseVal))
4002 return V;
4003
4004 if (Value *V = foldSelectWithDominatingCond(Cond, TrueVal, FalseVal, Q))
39664005 return V;
39674006
39684007 return nullptr;
20202020 }
20212021 }
20222022
2023 // See if we can determine the result of this select based on a dominating
2024 // condition.
2025 BasicBlock *Parent = SI.getParent();
2026 if (BasicBlock *Dom = Parent->getSinglePredecessor()) {
2027 auto *PBI = dyn_cast_or_null(Dom->getTerminator());
2028 if (PBI && PBI->isConditional() &&
2029 PBI->getSuccessor(0) != PBI->getSuccessor(1) &&
2030 (PBI->getSuccessor(0) == Parent || PBI->getSuccessor(1) == Parent)) {
2031 bool CondIsTrue = PBI->getSuccessor(0) == Parent;
2032 Optional Implication = isImpliedCondition(
2033 PBI->getCondition(), SI.getCondition(), DL, CondIsTrue);
2034 if (Implication) {
2035 Value *V = *Implication ? TrueVal : FalseVal;
2036 return replaceInstUsesWith(SI, V);
2037 }
2038 }
2039 }
2040
20412023 // If we can compute the condition, there's no need for a select.
20422024 // Like the above fold, we are attempting to reduce compile-time cost by
20432025 // putting this fold here with limitations rather than in InstSimplify.
+0
-274
test/Transforms/InstCombine/select-implied.ll less more
None ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
1 ; RUN: opt < %s -instcombine -S | FileCheck %s
2
3 ; A == B implies A >u B is false.
4
5 define void @test1(i32 %a, i32 %b) {
6 ; CHECK-LABEL: @test1(
7 ; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
8 ; CHECK-NEXT: br i1 [[CMP1]], label [[TAKEN:%.*]], label [[END:%.*]]
9 ; CHECK: taken:
10 ; CHECK-NEXT: call void @foo(i32 10)
11 ; CHECK-NEXT: br label [[END]]
12 ; CHECK: end:
13 ; CHECK-NEXT: ret void
14 ;
15 %cmp1 = icmp eq i32 %a, %b
16 br i1 %cmp1, label %taken, label %end
17
18 taken:
19 %cmp2 = icmp ugt i32 %a, %b
20 %c = select i1 %cmp2, i32 0, i32 10
21 call void @foo(i32 %c)
22 br label %end
23
24 end:
25 ret void
26 }
27
28 ; If A == B is false then A != B is true.
29
30 define void @test2(i32 %a, i32 %b) {
31 ; CHECK-LABEL: @test2(
32 ; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
33 ; CHECK-NEXT: br i1 [[CMP1]], label [[END:%.*]], label [[TAKEN:%.*]]
34 ; CHECK: taken:
35 ; CHECK-NEXT: call void @foo(i32 20)
36 ; CHECK-NEXT: br label [[END]]
37 ; CHECK: end:
38 ; CHECK-NEXT: ret void
39 ;
40 %cmp1 = icmp eq i32 %a, %b
41 br i1 %cmp1, label %end, label %taken
42
43 taken:
44 %cmp2 = icmp ne i32 %a, %b
45 %c = select i1 %cmp2, i32 20, i32 0
46 call void @foo(i32 %c)
47 br label %end
48
49 end:
50 ret void
51 }
52
53 ; A >u 10 implies A >u 10 is true.
54
55 define void @test3(i32 %a) {
56 ; CHECK-LABEL: @test3(
57 ; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt i32 [[A:%.*]], 10
58 ; CHECK-NEXT: br i1 [[CMP1]], label [[TAKEN:%.*]], label [[END:%.*]]
59 ; CHECK: taken:
60 ; CHECK-NEXT: call void @foo(i32 30)
61 ; CHECK-NEXT: br label [[END]]
62 ; CHECK: end:
63 ; CHECK-NEXT: ret void
64 ;
65 %cmp1 = icmp ugt i32 %a, 10
66 br i1 %cmp1, label %taken, label %end
67
68 taken:
69 %cmp2 = icmp ugt i32 %a, 10
70 %c = select i1 %cmp2, i32 30, i32 0
71 call void @foo(i32 %c)
72 br label %end
73
74 end:
75 ret void
76 }
77
78 define i8 @PR23333(i8 addrspace(1)* %ptr) {
79 ; CHECK-LABEL: @PR23333(
80 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 addrspace(1)* [[PTR:%.*]], null
81 ; CHECK-NEXT: br i1 [[CMP]], label [[TAKEN:%.*]], label [[END:%.*]]
82 ; CHECK: taken:
83 ; CHECK-NEXT: ret i8 1
84 ; CHECK: end:
85 ; CHECK-NEXT: ret i8 0
86 ;
87 %cmp = icmp eq i8 addrspace(1)* %ptr, null
88 br i1 %cmp, label %taken, label %end
89
90 taken:
91 %cmp2 = icmp ne i8 addrspace(1)* %ptr, null
92 %res = select i1 %cmp2, i8 2, i8 1
93 ret i8 %res
94
95 end:
96 ret i8 0
97 }
98
99 ; We know the condition of the select is true based on a dominating condition.
100 ; Therefore, we can replace %cond with %len. However, now the inner icmp is
101 ; always false and can be elided.
102
103 define void @test4(i32 %len) {
104 ; CHECK-LABEL: @test4(
105 ; CHECK-NEXT: entry:
106 ; CHECK-NEXT: [[TMP0:%.*]] = call i32 @bar(i32 [[LEN:%.*]])
107 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[LEN]], 4
108 ; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[B1:%.*]]
109 ; CHECK: bb:
110 ; CHECK-NEXT: br i1 false, label [[B0:%.*]], label [[B1]]
111 ; CHECK: b0:
112 ; CHECK-NEXT: br label [[B1]]
113 ; CHECK: b1:
114 ; CHECK-NEXT: [[TMP1:%.*]] = phi i32 [ [[LEN]], [[BB]] ], [ undef, [[B0]] ], [ [[TMP0]], [[ENTRY:%.*]] ]
115 ; CHECK-NEXT: br label [[RET:%.*]]
116 ; CHECK: ret:
117 ; CHECK-NEXT: call void @foo(i32 [[TMP1]])
118 ; CHECK-NEXT: ret void
119 ;
120 entry:
121 %0 = call i32 @bar(i32 %len);
122 %cmp = icmp ult i32 %len, 4
123 br i1 %cmp, label %bb, label %b1
124 bb:
125 %cond = select i1 %cmp, i32 %len, i32 8
126 %cmp11 = icmp eq i32 %cond, 8
127 br i1 %cmp11, label %b0, label %b1
128
129 b0:
130 call void @foo(i32 %len)
131 br label %b1
132
133 b1:
134 %1 = phi i32 [ %cond, %bb ], [ undef, %b0 ], [ %0, %entry ]
135 br label %ret
136
137 ret:
138 call void @foo(i32 %1)
139 ret void
140 }
141
142 ; A >u 10 implies A >u 9 is true.
143
144 define void @test5(i32 %a) {
145 ; CHECK-LABEL: @test5(
146 ; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt i32 [[A:%.*]], 10
147 ; CHECK-NEXT: br i1 [[CMP1]], label [[TAKEN:%.*]], label [[END:%.*]]
148 ; CHECK: taken:
149 ; CHECK-NEXT: call void @foo(i32 30)
150 ; CHECK-NEXT: br label [[END]]
151 ; CHECK: end:
152 ; CHECK-NEXT: ret void
153 ;
154 %cmp1 = icmp ugt i32 %a, 10
155 br i1 %cmp1, label %taken, label %end
156
157 taken:
158 %cmp2 = icmp ugt i32 %a, 9
159 %c = select i1 %cmp2, i32 30, i32 0
160 call void @foo(i32 %c)
161 br label %end
162
163 end:
164 ret void
165 }
166
167 declare void @foo(i32)
168 declare i32 @bar(i32)
169
170 define i32 @test_and(i32 %a, i32 %b) {
171 ; CHECK-LABEL: @test_and(
172 ; CHECK-NEXT: entry:
173 ; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i32 [[A:%.*]], 0
174 ; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i32 [[B:%.*]], 0
175 ; CHECK-NEXT: [[AND:%.*]] = and i1 [[CMP1]], [[CMP2]]
176 ; CHECK-NEXT: br i1 [[AND]], label [[TPATH:%.*]], label [[END:%.*]]
177 ; CHECK: tpath:
178 ; CHECK-NEXT: ret i32 313
179 ; CHECK: end:
180 ; CHECK-NEXT: ret i32 0
181 ;
182 entry:
183 %cmp1 = icmp ne i32 %a, 0
184 %cmp2 = icmp ne i32 %b, 0
185 %and = and i1 %cmp1, %cmp2
186 br i1 %and, label %tpath, label %end
187
188 tpath:
189 %cmp3 = icmp eq i32 %a, 0 ;; <-- implied false
190 %c = select i1 %cmp3, i32 0, i32 313
191 ret i32 %c
192
193 end:
194 ret i32 0
195 }
196
197 ; cmp1 and cmp2 are false on the 'fpath' path and thus cmp3 is true.
198
199 define i32 @test_or1(i32 %a, i32 %b) {
200 ; CHECK-LABEL: @test_or1(
201 ; CHECK-NEXT: entry:
202 ; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], 0
203 ; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32 [[B:%.*]], 0
204 ; CHECK-NEXT: [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
205 ; CHECK-NEXT: br i1 [[OR]], label [[END:%.*]], label [[FPATH:%.*]]
206 ; CHECK: fpath:
207 ; CHECK-NEXT: ret i32 37
208 ; CHECK: end:
209 ; CHECK-NEXT: ret i32 0
210 ;
211 entry:
212 %cmp1 = icmp eq i32 %a, 0
213 %cmp2 = icmp eq i32 %b, 0
214 %or = or i1 %cmp1, %cmp2
215 br i1 %or, label %end, label %fpath
216
217 fpath:
218 %cmp3 = icmp ne i32 %a, 0 ;; <-- implied true
219 %c = select i1 %cmp3, i32 37, i32 0
220 ret i32 %c
221
222 end:
223 ret i32 0
224 }
225
226 ; LHS ==> RHS by definition (true -> true)
227
228 define void @test6(i32 %a, i32 %b) {
229 ; CHECK-LABEL: @test6(
230 ; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
231 ; CHECK-NEXT: br i1 [[CMP1]], label [[TAKEN:%.*]], label [[END:%.*]]
232 ; CHECK: taken:
233 ; CHECK-NEXT: call void @foo(i32 10)
234 ; CHECK-NEXT: br label [[END]]
235 ; CHECK: end:
236 ; CHECK-NEXT: ret void
237 ;
238 %cmp1 = icmp eq i32 %a, %b
239 br i1 %cmp1, label %taken, label %end
240
241 taken:
242 %c = select i1 %cmp1, i32 10, i32 0
243 call void @foo(i32 %c)
244 br label %end
245
246 end:
247 ret void
248 }
249
250 ; LHS ==> RHS by definition (false -> false)
251
252 define void @test7(i32 %a, i32 %b) {
253 ; CHECK-LABEL: @test7(
254 ; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
255 ; CHECK-NEXT: br i1 [[CMP1]], label [[END:%.*]], label [[TAKEN:%.*]]
256 ; CHECK: taken:
257 ; CHECK-NEXT: call void @foo(i32 11)
258 ; CHECK-NEXT: br label [[END]]
259 ; CHECK: end:
260 ; CHECK-NEXT: ret void
261 ;
262 %cmp1 = icmp eq i32 %a, %b
263 br i1 %cmp1, label %end, label %taken
264
265 taken:
266 %c = select i1 %cmp1, i32 0, i32 11
267 call void @foo(i32 %c)
268 br label %end
269
270 end:
271 ret void
272 }
273
0 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
1 ; Various patterns of three-ways comparison that are not currently recognized.
2
31 ; RUN: opt < %s -instcombine -S | FileCheck %s
42
53 target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
75 declare void @foo(i32 %x)
86
97 define i32 @compare_against_arbitrary_value(i32 %x, i32 %c) {
10 ; TODO: We can prove that if %x s> %c then %x != c, so there should be no actual
11 ; calculations in callfoo block. @foo can be invoked with 1. We only do it
12 ; for constants that are not 0 currently while it could be generalized.
138 ; CHECK-LABEL: @compare_against_arbitrary_value(
149 ; CHECK-NEXT: entry:
1510 ; CHECK-NEXT: [[TMP0:%.*]] = icmp sgt i32 [[X:%.*]], [[C:%.*]]
1611 ; CHECK-NEXT: br i1 [[TMP0]], label [[CALLFOO:%.*]], label [[EXIT:%.*]]
1712 ; CHECK: callfoo:
18 ; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i32 [[X]], [[C]]
19 ; CHECK-NEXT: [[SELECT2:%.*]] = zext i1 [[CMP1]] to i32
20 ; CHECK-NEXT: call void @foo(i32 [[SELECT2]])
13 ; CHECK-NEXT: call void @foo(i32 1)
2114 ; CHECK-NEXT: br label [[EXIT]]
2215 ; CHECK: exit:
2316 ; CHECK-NEXT: ret i32 42
352345 }
353346
354347 define i32 @compare_against_arbitrary_value_type_mismatch(i64 %x, i64 %c) {
355 ; TODO: We can prove that if %x s> %c then %x != c, so there should be no actual
356 ; calculations in callfoo block. @foo can be invoked with 1. We only do it
357 ; for constants that are not 0 currently while it could be generalized.
358348 ; CHECK-LABEL: @compare_against_arbitrary_value_type_mismatch(
359349 ; CHECK-NEXT: entry:
360350 ; CHECK-NEXT: [[TMP0:%.*]] = icmp sgt i64 [[X:%.*]], [[C:%.*]]
361351 ; CHECK-NEXT: br i1 [[TMP0]], label [[CALLFOO:%.*]], label [[EXIT:%.*]]
362352 ; CHECK: callfoo:
363 ; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i64 [[X]], [[C]]
364 ; CHECK-NEXT: [[SELECT2:%.*]] = zext i1 [[CMP1]] to i32
365 ; CHECK-NEXT: call void @foo(i32 [[SELECT2]])
353 ; CHECK-NEXT: call void @foo(i32 1)
366354 ; CHECK-NEXT: br label [[EXIT]]
367355 ; CHECK: exit:
368356 ; CHECK-NEXT: ret i32 42
0 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
1 ; RUN: opt < %s -instsimplify -S | FileCheck %s
2
3 ; A == B implies A >u B is false.
4
5 define void @test1(i32 %a, i32 %b) {
6 ; CHECK-LABEL: @test1(
7 ; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
8 ; CHECK-NEXT: br i1 [[CMP1]], label [[TAKEN:%.*]], label [[END:%.*]]
9 ; CHECK: taken:
10 ; CHECK-NEXT: call void @foo(i32 10)
11 ; CHECK-NEXT: br label [[END]]
12 ; CHECK: end:
13 ; CHECK-NEXT: ret void
14 ;
15 %cmp1 = icmp eq i32 %a, %b
16 br i1 %cmp1, label %taken, label %end
17
18 taken:
19 %cmp2 = icmp ugt i32 %a, %b
20 %c = select i1 %cmp2, i32 0, i32 10
21 call void @foo(i32 %c)
22 br label %end
23
24 end:
25 ret void
26 }
27
28 ; If A == B is false then A != B is true.
29
30 define void @test2(i32 %a, i32 %b) {
31 ; CHECK-LABEL: @test2(
32 ; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
33 ; CHECK-NEXT: br i1 [[CMP1]], label [[END:%.*]], label [[TAKEN:%.*]]
34 ; CHECK: taken:
35 ; CHECK-NEXT: call void @foo(i32 20)
36 ; CHECK-NEXT: br label [[END]]
37 ; CHECK: end:
38 ; CHECK-NEXT: ret void
39 ;
40 %cmp1 = icmp eq i32 %a, %b
41 br i1 %cmp1, label %end, label %taken
42
43 taken:
44 %cmp2 = icmp ne i32 %a, %b
45 %c = select i1 %cmp2, i32 20, i32 0
46 call void @foo(i32 %c)
47 br label %end
48
49 end:
50 ret void
51 }
52
53 ; A >u 10 implies A >u 10 is true.
54
55 define void @test3(i32 %a) {
56 ; CHECK-LABEL: @test3(
57 ; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt i32 [[A:%.*]], 10
58 ; CHECK-NEXT: br i1 [[CMP1]], label [[TAKEN:%.*]], label [[END:%.*]]
59 ; CHECK: taken:
60 ; CHECK-NEXT: call void @foo(i32 30)
61 ; CHECK-NEXT: br label [[END]]
62 ; CHECK: end:
63 ; CHECK-NEXT: ret void
64 ;
65 %cmp1 = icmp ugt i32 %a, 10
66 br i1 %cmp1, label %taken, label %end
67
68 taken:
69 %cmp2 = icmp ugt i32 %a, 10
70 %c = select i1 %cmp2, i32 30, i32 0
71 call void @foo(i32 %c)
72 br label %end
73
74 end:
75 ret void
76 }
77
78 define i8 @PR23333(i8 addrspace(1)* %ptr) {
79 ; CHECK-LABEL: @PR23333(
80 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 addrspace(1)* [[PTR:%.*]], null
81 ; CHECK-NEXT: br i1 [[CMP]], label [[TAKEN:%.*]], label [[END:%.*]]
82 ; CHECK: taken:
83 ; CHECK-NEXT: ret i8 1
84 ; CHECK: end:
85 ; CHECK-NEXT: ret i8 0
86 ;
87 %cmp = icmp eq i8 addrspace(1)* %ptr, null
88 br i1 %cmp, label %taken, label %end
89
90 taken:
91 %cmp2 = icmp ne i8 addrspace(1)* %ptr, null
92 %res = select i1 %cmp2, i8 2, i8 1
93 ret i8 %res
94
95 end:
96 ret i8 0
97 }
98
99 ; We know the condition of the select is true based on a dominating condition.
100 ; Therefore, we can replace %cond with %len.
101 ; TODO: len == 8 is known false in bb. This is handled by other passes, but should it be handled here?
102
103 define void @test4(i32 %len) {
104 ; CHECK-LABEL: @test4(
105 ; CHECK-NEXT: entry:
106 ; CHECK-NEXT: [[TMP0:%.*]] = call i32 @bar(i32 [[LEN:%.*]])
107 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[LEN]], 4
108 ; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[B1:%.*]]
109 ; CHECK: bb:
110 ; CHECK-NEXT: [[CMP11:%.*]] = icmp eq i32 [[LEN]], 8
111 ; CHECK-NEXT: br i1 [[CMP11]], label [[B0:%.*]], label [[B1]]
112 ; CHECK: b0:
113 ; CHECK-NEXT: call void @foo(i32 [[LEN]])
114 ; CHECK-NEXT: br label [[B1]]
115 ; CHECK: b1:
116 ; CHECK-NEXT: [[TMP1:%.*]] = phi i32 [ [[LEN]], [[BB]] ], [ undef, [[B0]] ], [ [[TMP0]], [[ENTRY:%.*]] ]
117 ; CHECK-NEXT: br label [[RET:%.*]]
118 ; CHECK: ret:
119 ; CHECK-NEXT: call void @foo(i32 [[TMP1]])
120 ; CHECK-NEXT: ret void
121 ;
122 entry:
123 %0 = call i32 @bar(i32 %len);
124 %cmp = icmp ult i32 %len, 4
125 br i1 %cmp, label %bb, label %b1
126 bb:
127 %cond = select i1 %cmp, i32 %len, i32 8
128 %cmp11 = icmp eq i32 %cond, 8
129 br i1 %cmp11, label %b0, label %b1
130
131 b0:
132 call void @foo(i32 %len)
133 br label %b1
134
135 b1:
136 %1 = phi i32 [ %cond, %bb ], [ undef, %b0 ], [ %0, %entry ]
137 br label %ret
138
139 ret:
140 call void @foo(i32 %1)
141 ret void
142 }
143
144 ; A >u 10 implies A >u 9 is true.
145
146 define void @test5(i32 %a) {
147 ; CHECK-LABEL: @test5(
148 ; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt i32 [[A:%.*]], 10
149 ; CHECK-NEXT: br i1 [[CMP1]], label [[TAKEN:%.*]], label [[END:%.*]]
150 ; CHECK: taken:
151 ; CHECK-NEXT: call void @foo(i32 30)
152 ; CHECK-NEXT: br label [[END]]
153 ; CHECK: end:
154 ; CHECK-NEXT: ret void
155 ;
156 %cmp1 = icmp ugt i32 %a, 10
157 br i1 %cmp1, label %taken, label %end
158
159 taken:
160 %cmp2 = icmp ugt i32 %a, 9
161 %c = select i1 %cmp2, i32 30, i32 0
162 call void @foo(i32 %c)
163 br label %end
164
165 end:
166 ret void
167 }
168
169 declare void @foo(i32)
170 declare i32 @bar(i32)
171
172 define i32 @test_and(i32 %a, i32 %b) {
173 ; CHECK-LABEL: @test_and(
174 ; CHECK-NEXT: entry:
175 ; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i32 [[A:%.*]], 0
176 ; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i32 [[B:%.*]], 0
177 ; CHECK-NEXT: [[AND:%.*]] = and i1 [[CMP1]], [[CMP2]]
178 ; CHECK-NEXT: br i1 [[AND]], label [[TPATH:%.*]], label [[END:%.*]]
179 ; CHECK: tpath:
180 ; CHECK-NEXT: ret i32 313
181 ; CHECK: end:
182 ; CHECK-NEXT: ret i32 0
183 ;
184 entry:
185 %cmp1 = icmp ne i32 %a, 0
186 %cmp2 = icmp ne i32 %b, 0
187 %and = and i1 %cmp1, %cmp2
188 br i1 %and, label %tpath, label %end
189
190 tpath:
191 %cmp3 = icmp eq i32 %a, 0 ;; <-- implied false
192 %c = select i1 %cmp3, i32 0, i32 313
193 ret i32 %c
194
195 end:
196 ret i32 0
197 }
198
199 ; cmp1 and cmp2 are false on the 'fpath' path and thus cmp3 is true.
200
201 define i32 @test_or1(i32 %a, i32 %b) {
202 ; CHECK-LABEL: @test_or1(
203 ; CHECK-NEXT: entry:
204 ; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], 0
205 ; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32 [[B:%.*]], 0
206 ; CHECK-NEXT: [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
207 ; CHECK-NEXT: br i1 [[OR]], label [[END:%.*]], label [[FPATH:%.*]]
208 ; CHECK: fpath:
209 ; CHECK-NEXT: ret i32 37
210 ; CHECK: end:
211 ; CHECK-NEXT: ret i32 0
212 ;
213 entry:
214 %cmp1 = icmp eq i32 %a, 0
215 %cmp2 = icmp eq i32 %b, 0
216 %or = or i1 %cmp1, %cmp2
217 br i1 %or, label %end, label %fpath
218
219 fpath:
220 %cmp3 = icmp ne i32 %a, 0 ;; <-- implied true
221 %c = select i1 %cmp3, i32 37, i32 0
222 ret i32 %c
223
224 end:
225 ret i32 0
226 }
227
228 ; LHS ==> RHS by definition (true -> true)
229
230 define void @test6(i32 %a, i32 %b) {
231 ; CHECK-LABEL: @test6(
232 ; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
233 ; CHECK-NEXT: br i1 [[CMP1]], label [[TAKEN:%.*]], label [[END:%.*]]
234 ; CHECK: taken:
235 ; CHECK-NEXT: call void @foo(i32 10)
236 ; CHECK-NEXT: br label [[END]]
237 ; CHECK: end:
238 ; CHECK-NEXT: ret void
239 ;
240 %cmp1 = icmp eq i32 %a, %b
241 br i1 %cmp1, label %taken, label %end
242
243 taken:
244 %c = select i1 %cmp1, i32 10, i32 0
245 call void @foo(i32 %c)
246 br label %end
247
248 end:
249 ret void
250 }
251
252 ; LHS ==> RHS by definition (false -> false)
253
254 define void @test7(i32 %a, i32 %b) {
255 ; CHECK-LABEL: @test7(
256 ; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
257 ; CHECK-NEXT: br i1 [[CMP1]], label [[END:%.*]], label [[TAKEN:%.*]]
258 ; CHECK: taken:
259 ; CHECK-NEXT: call void @foo(i32 11)
260 ; CHECK-NEXT: br label [[END]]
261 ; CHECK: end:
262 ; CHECK-NEXT: ret void
263 ;
264 %cmp1 = icmp eq i32 %a, %b
265 br i1 %cmp1, label %end, label %taken
266
267 taken:
268 %c = select i1 %cmp1, i32 0, i32 11
269 call void @foo(i32 %c)
270 br label %end
271
272 end:
273 ret void
274 }
275