1 ; RUN: opt -S -jump-threading < %s | FileCheck %s
9 ; Jump threading of branch with select as condition.
10 ; Mostly theoretical since instruction combining simplifies all selects of
11 ; booleans where at least one operand is true/false/undef.
13 ; CHECK-LABEL: @test_br(
15 ; CHECK-NEXT: br i1 %cond, label %L1,
16 define void @test_br(i1 %cond, i1 %value) nounwind {
18 br i1 %cond, label %L0, label %L3
20 %expr = select i1 %cond, i1 true, i1 %value
21 br i1 %expr, label %L1, label %L2
35 ; Jump threading of switch with select as condition.
37 ; CHECK-LABEL: @test_switch(
39 ; CHECK-NEXT: br i1 %cond, label %L1,
40 define void @test_switch(i1 %cond, i8 %value) nounwind {
42 br i1 %cond, label %L0, label %L4
44 %expr = select i1 %cond, i8 1, i8 %value
45 switch i8 %expr, label %L3 [i8 1, label %L1 i8 2, label %L2]
61 ; Make sure the blocks in the indirectbr test aren't trivially removable as
62 ; successors by taking their addresses.
63 @anchor = constant [3 x i8*] [
64 i8* blockaddress(@test_indirectbr, %L1),
65 i8* blockaddress(@test_indirectbr, %L2),
66 i8* blockaddress(@test_indirectbr, %L3)
70 ; Jump threading of indirectbr with select as address.
72 ; CHECK-LABEL: @test_indirectbr(
74 ; CHECK-NEXT: br i1 %cond, label %L1, label %L3
75 define void @test_indirectbr(i1 %cond, i8* %address) nounwind {
77 br i1 %cond, label %L0, label %L3
79 %indirect.goto.dest = select i1 %cond, i8* blockaddress(@test_indirectbr, %L1), i8* %address
80 indirectbr i8* %indirect.goto.dest, [label %L1, label %L2, label %L3]
94 ; Jump threading of indirectbr with select as address. Test increased
95 ; duplication threshold for cases where indirectbr is being threaded
98 ; CHECK-LABEL: @test_indirectbr_thresh(
100 ; CHECK-NEXT: br i1 %cond, label %L1, label %L3
101 ; CHECK-NOT: indirectbr
102 define void @test_indirectbr_thresh(i1 %cond, i8* %address) nounwind {
104 br i1 %cond, label %L0, label %L3
106 %indirect.goto.dest = select i1 %cond, i8* blockaddress(@test_indirectbr_thresh, %L1), i8* %address
110 indirectbr i8* %indirect.goto.dest, [label %L1, label %L2, label %L3]
124 ; A more complicated case: the condition is a select based on a comparison.
126 ; CHECK-LABEL: @test_switch_cmp(
128 ; CHECK-NEXT: br i1 %cond, label %L0, label %[[THREADED:[A-Za-z.0-9]+]]
129 ; CHECK: [[THREADED]]:
130 ; CHECK-NEXT: call void @quux
131 ; CHECK-NEXT: br label %L1
132 define void @test_switch_cmp(i1 %cond, i32 %val, i8 %value) nounwind {
134 br i1 %cond, label %L0, label %L4
136 %val.phi = phi i32 [%val, %entry], [-1, %L4]
137 %cmp = icmp slt i32 %val.phi, 0
138 %expr = select i1 %cmp, i8 1, i8 %value
139 switch i8 %expr, label %L3 [i8 1, label %L1 i8 2, label %L2]
155 ; Make sure the edge value of %0 from entry to L2 includes 0 and L3 is
157 ; CHECK: test_switch_default
161 ; CHECK: [[THREADED:[A-Za-z.0-9]+]]:
165 ; CHECK-SAME: preds = %entry, %entry
166 ; CHECK-NEXT: phi i32
167 define void @test_switch_default(i32* nocapture %status) nounwind {
169 %0 = load i32, i32* %status, align 4
170 switch i32 %0, label %L2 [
176 store i32 10025, i32* %status, align 4
180 %1 = load i32, i32* %status, align 4
181 %cmp57.i = icmp eq i32 %1, 0
182 br i1 %cmp57.i, label %L3, label %L4
185 store i32 10000, i32* %status, align 4
192 define void @unfold1(double %x, double %y) nounwind {
194 %sub = fsub double %x, %y
195 %cmp = fcmp ogt double %sub, 1.000000e+01
196 br i1 %cmp, label %cond.end4, label %cond.false
198 cond.false: ; preds = %entry
199 %add = fadd double %x, %y
200 %cmp1 = fcmp ogt double %add, 1.000000e+01
201 %add. = select i1 %cmp1, double %add, double 0.000000e+00
204 cond.end4: ; preds = %entry, %cond.false
205 %cond5 = phi double [ %add., %cond.false ], [ %sub, %entry ]
206 %cmp6 = fcmp oeq double %cond5, 0.000000e+00
207 br i1 %cmp6, label %if.then, label %if.end
209 if.then: ; preds = %cond.end4
213 if.end: ; preds = %if.then, %cond.end4
216 ; CHECK-LABEL: @unfold1
217 ; CHECK: br i1 %cmp, label %cond.end4, label %cond.false
218 ; CHECK: br i1 %cmp1, label %cond.end4, label %if.then
219 ; CHECK: br i1 %cmp6, label %if.then, label %if.end
220 ; CHECK: br label %if.end
224 define void @unfold2(i32 %x, i32 %y) nounwind {
226 %sub = sub nsw i32 %x, %y
227 %cmp = icmp sgt i32 %sub, 10
228 br i1 %cmp, label %cond.end4, label %cond.false
230 cond.false: ; preds = %entry
231 %add = add nsw i32 %x, %y
232 %cmp1 = icmp sgt i32 %add, 10
233 %add. = select i1 %cmp1, i32 0, i32 %add
236 cond.end4: ; preds = %entry, %cond.false
237 %cond5 = phi i32 [ %add., %cond.false ], [ %sub, %entry ]
238 %cmp6 = icmp eq i32 %cond5, 0
239 br i1 %cmp6, label %if.then, label %if.end
241 if.then: ; preds = %cond.end4
245 if.end: ; preds = %if.then, %cond.end4
248 ; CHECK-LABEL: @unfold2
249 ; CHECK: br i1 %cmp, label %if.end, label %cond.false
250 ; CHECK: br i1 %cmp1, label %if.then, label %cond.end4
251 ; CHECK: br i1 %cmp6, label %if.then, label %if.end
252 ; CHECK: br label %if.end
256 define i32 @unfold3(i32 %u, i32 %v, i32 %w, i32 %x, i32 %y, i32 %z, i32 %j) nounwind {
258 %add3 = add nsw i32 %j, 2
259 %cmp.i = icmp slt i32 %u, %v
260 br i1 %cmp.i, label %.exit, label %cond.false.i
262 cond.false.i: ; preds = %entry
263 %cmp4.i = icmp sgt i32 %u, %v
264 br i1 %cmp4.i, label %.exit, label %cond.false.6.i
266 cond.false.6.i: ; preds = %cond.false.i
267 %cmp8.i = icmp slt i32 %w, %x
268 br i1 %cmp8.i, label %.exit, label %cond.false.10.i
270 cond.false.10.i: ; preds = %cond.false.6.i
271 %cmp13.i = icmp sgt i32 %w, %x
272 br i1 %cmp13.i, label %.exit, label %cond.false.15.i
274 cond.false.15.i: ; preds = %cond.false.10.i
275 %phitmp = icmp sge i32 %y, %z
278 .exit: ; preds = %entry, %cond.false.i, %cond.false.6.i, %cond.false.10.i, %cond.false.15.i
279 %cond23.i = phi i1 [ false, %entry ], [ true, %cond.false.i ], [ false, %cond.false.6.i ], [ %phitmp, %cond.false.15.i ], [ true, %cond.false.10.i ]
280 %j.add3 = select i1 %cond23.i, i32 %j, i32 %add3
283 ; CHECK-LABEL: @unfold3
284 ; CHECK: br i1 %cmp.i, label %.exit.thread3, label %cond.false.i
285 ; CHECK: br i1 %cmp4.i, label %.exit.thread, label %cond.false.6.i
286 ; CHECK: br i1 %cmp8.i, label %.exit.thread3, label %cond.false.10.i
287 ; CHECK: br i1 %cmp13.i, label %.exit.thread, label %.exit
288 ; CHECK: br i1 %phitmp, label %.exit.thread, label %.exit.thread3
289 ; CHECK: br label %.exit.thread3
292 define i32 @unfold4(i32 %u, i32 %v, i32 %w, i32 %x, i32 %y, i32 %z, i32 %j) nounwind {
294 %add3 = add nsw i32 %j, 2
295 %cmp.i = icmp slt i32 %u, %v
296 br i1 %cmp.i, label %.exit, label %cond.false.i
298 cond.false.i: ; preds = %entry
299 %cmp4.i = icmp sgt i32 %u, %v
300 br i1 %cmp4.i, label %.exit, label %cond.false.6.i
302 cond.false.6.i: ; preds = %cond.false.i
303 %cmp8.i = icmp slt i32 %w, %x
304 br i1 %cmp8.i, label %.exit, label %cond.false.10.i
306 cond.false.10.i: ; preds = %cond.false.6.i
307 %cmp13.i = icmp sgt i32 %w, %x
308 br i1 %cmp13.i, label %.exit, label %cond.false.15.i
310 cond.false.15.i: ; preds = %cond.false.10.i
311 %cmp19.i = icmp sge i32 %y, %z
312 %conv = zext i1 %cmp19.i to i32
315 .exit: ; preds = %entry, %cond.false.i, %cond.false.6.i, %cond.false.10.i, %cond.false.15.i
316 %cond23.i = phi i32 [ 1, %entry ], [ 0, %cond.false.i ], [ 1, %cond.false.6.i ], [ %conv, %cond.false.15.i ], [ 0, %cond.false.10.i ]
317 %lnot.i18 = icmp eq i32 %cond23.i, 1
318 %j.add3 = select i1 %lnot.i18, i32 %j, i32 %add3
321 ; CHECK-LABEL: @unfold4
322 ; CHECK: br i1 %cmp.i, label %.exit.thread, label %cond.false.i
323 ; CHECK: br i1 %cmp4.i, label %.exit.thread4, label %cond.false.6.i
324 ; CHECK: br i1 %cmp8.i, label %.exit.thread, label %cond.false.10.i
325 ; CHECK: br i1 %cmp13.i, label %.exit.thread4, label %.exit
326 ; CHECK: br i1 %lnot.i18, label %.exit.thread, label %.exit.thread4
327 ; CHECK: br label %.exit.thread4
330 define i32 @unfold5(i32 %u, i32 %v, i32 %w, i32 %x, i32 %y, i32 %z, i32 %j) nounwind {
332 %add3 = add nsw i32 %j, 2
333 %cmp.i = icmp slt i32 %u, %v
334 br i1 %cmp.i, label %.exit, label %cond.false.i
336 cond.false.i: ; preds = %entry
337 %cmp4.i = icmp sgt i32 %u, %v
338 br i1 %cmp4.i, label %.exit, label %cond.false.6.i
340 cond.false.6.i: ; preds = %cond.false.i
341 %cmp8.i = icmp slt i32 %w, %x
342 br i1 %cmp8.i, label %.exit, label %cond.false.10.i
344 cond.false.10.i: ; preds = %cond.false.6.i
345 %cmp13.i = icmp sgt i32 %w, %x
346 br i1 %cmp13.i, label %.exit, label %cond.false.15.i
348 cond.false.15.i: ; preds = %cond.false.10.i
349 %cmp19.i = icmp sge i32 %y, %z
350 %conv = zext i1 %cmp19.i to i32
353 .exit: ; preds = %entry, %cond.false.i, %cond.false.6.i, %cond.false.10.i, %cond.false.15.i
354 %cond23.i = phi i32 [ 2, %entry ], [ 3, %cond.false.i ], [ 1, %cond.false.6.i ], [ %conv, %cond.false.15.i ], [ 7, %cond.false.10.i ]
355 %lnot.i18 = icmp sgt i32 %cond23.i, 5
356 %j.add3 = select i1 %lnot.i18, i32 %j, i32 %cond23.i
359 ; CHECK-LABEL: @unfold5
360 ; CHECK: br i1 %cmp.i, label %.exit, label %cond.false.i
361 ; CHECK: br i1 %cmp4.i, label %.exit, label %cond.false.6.i
362 ; CHECK: br i1 %cmp8.i, label %.exit, label %cond.false.10.i
363 ; CHECK: br i1 %cmp13.i, label %.exit, label %cond.false.15.i
364 ; CHECK: br label %.exit
367 ; When a select has a constant operand in one branch, and it feeds a phi node
368 ; and the phi node feeds a switch we unfold the select
369 define void @test_func(i32* nocapture readonly %a, i32* nocapture readonly %b, i32* nocapture readonly %c, i32 %n) local_unnamed_addr #0 {
373 for.cond: ; preds = %sw.default, %entry
374 %i.0 = phi i32 [ 0, %entry ], [ %inc, %sw.default ]
375 %cmp = icmp slt i32 %i.0, %n
376 br i1 %cmp, label %for.body, label %for.cond.cleanup
378 for.cond.cleanup: ; preds = %for.cond
381 for.body: ; preds = %for.cond
382 %0 = zext i32 %i.0 to i64
383 %arrayidx = getelementptr inbounds i32, i32* %a, i64 %0
384 %1 = load i32, i32* %arrayidx, align 4
385 %cmp1 = icmp eq i32 %1, 4
386 br i1 %cmp1, label %land.lhs.true, label %if.end
388 land.lhs.true: ; preds = %for.body
389 %arrayidx3 = getelementptr inbounds i32, i32* %b, i64 %0
390 %2 = load i32, i32* %arrayidx3, align 4
391 %arrayidx5 = getelementptr inbounds i32, i32* %c, i64 %0
392 %3 = load i32, i32* %arrayidx5, align 4
393 %cmp6 = icmp eq i32 %2, %3
394 %spec.select = select i1 %cmp6, i32 2, i32 4
397 if.end: ; preds = %land.lhs.true, %for.body
398 %local_var.0 = phi i32 [ %1, %for.body ], [ %spec.select, %land.lhs.true ]
399 switch i32 %local_var.0, label %sw.default [
406 sw.bb: ; preds = %if.end
410 sw.bb7: ; preds = %if.end, %sw.bb
414 sw.bb8: ; preds = %if.end, %sw.bb7
418 sw.bb9: ; preds = %if.end, %sw.bb8
422 sw.default: ; preds = %if.end, %sw.bb9
424 %inc = add nuw nsw i32 %i.0, 1
427 ; CHECK-LABEL: @test_func(
428 ; CHECK: [[REG:%[0-9]+]] = load
432 ; CHECK: br i1 {{.*}}, label [[DEST1:%.*]], label [[DEST2:%.*]]
434 ; The following line checks existence of a phi node, and makes sure
435 ; it only has one incoming value. To do this, we check every '%'. Note
436 ; that REG and REG2 each contain one '%;. There is another one in the
437 ; beginning of the incoming block name. After that there should be no other '%'.
439 ; CHECK: [[REG2:%.*]] = phi i32 {{[^%]*}}[[REG]]{{[^%]*%[^%]*}}
440 ; CHECK: switch i32 [[REG2]]
441 ; CHECK: i32 2, label [[DEST1]]
442 ; CHECK: i32 4, label [[DEST2]]
445 ; FIXME: This is an invalid transform. If %b is false and %x is poison,
446 ; then the select produces poison (the result of the program is poison).
447 ; But with this transform, we may be branching on poison, and that is UB.
449 define i32 @TryToUnfoldSelectInCurrBB(i1 %b, i1 %ui, i32 %s, i1 %x) {
450 ; CHECK-LABEL: @TryToUnfoldSelectInCurrBB(
452 ; CHECK-NEXT: br i1 [[B:%.*]], label [[IF_END_THREAD:%.*]], label [[IF_END:%.*]]
454 ; CHECK-NEXT: br i1 [[X:%.*]], label [[TMP0:%.*]], label [[IF_END_THREAD]]
456 ; CHECK-NEXT: br label [[IF_END_THREAD]]
457 ; CHECK: if.end.thread:
458 ; CHECK-NEXT: [[TMP1:%.*]] = phi i32 [ [[S:%.*]], [[TMP0]] ], [ 42, [[IF_END]] ], [ 42, [[ENTRY:%.*]] ]
459 ; CHECK-NEXT: ret i32 [[TMP1]]
462 br i1 %b, label %if.end, label %if.else
468 %v = phi i1 [ %x, %if.else ], [ false, %entry ]
469 %v1 = select i1 %v, i32 %s, i32 42