Right now the algorithm does not exit on unpredictable values. It waits until all the paths have been enumerated to see if any of those paths have that value. Waiting this late leads to a lot of wasteful computation and higher compile time. In this patch I have added a heuristic that checks if the value comes from the same inner loops as the switch, if so, then it is likely that the value will also be seen on a threadable path and the code in `getStateDefMap()` return an empty map. I tested this on the llvm test suite and the only change in the number of threaded switches was in 7zip (before 23, after 18). In all of those cases the current algorithm was partially threading the loop because it was hitting a limit on the number of paths to be explored. On increasing this limit even the current algorithm finds paths where the unpredictable value is seen. Compile time(with pass enabled by default and this patch): https://llvm-compile-time-tracker.com/compare.php?from=8c5e9cf737138aba22a4a8f64ef2c5efc80dd7f9&to=42c75d888058b35c6d15901b34e36251d8f766b9&stat=instructions:u
372 lines
17 KiB
LLVM
372 lines
17 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; RUN: opt -S -passes=dfa-jump-threading -dfa-early-exit-heuristic=false %s | FileCheck %s
|
|
|
|
; These tests check if selects are unfolded properly for jump threading
|
|
; opportunities. There are three different patterns to consider:
|
|
; 1) Both operands are constant and the false branch is unfolded by default
|
|
; 2) One operand is constant and the other is another select to be unfolded. In
|
|
; this case a single select is sunk to a new block to unfold.
|
|
; 3) Both operands are a select, and both should be sunk to new blocks.
|
|
define i32 @test1(i32 %num) {
|
|
; CHECK-LABEL: @test1(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: [[COUNT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ]
|
|
; CHECK-NEXT: [[STATE:%.*]] = phi i32 [ 1, [[ENTRY]] ], [ poison, [[FOR_INC]] ]
|
|
; CHECK-NEXT: switch i32 [[STATE]], label [[FOR_INC_JT1:%.*]] [
|
|
; CHECK-NEXT: i32 1, label [[CASE1:%.*]]
|
|
; CHECK-NEXT: i32 2, label [[CASE2:%.*]]
|
|
; CHECK-NEXT: ]
|
|
; CHECK: for.body.jt2:
|
|
; CHECK-NEXT: [[COUNT_JT2:%.*]] = phi i32 [ [[INC_JT2:%.*]], [[FOR_INC_JT2:%.*]] ]
|
|
; CHECK-NEXT: [[STATE_JT2:%.*]] = phi i32 [ [[STATE_NEXT_JT2:%.*]], [[FOR_INC_JT2]] ]
|
|
; CHECK-NEXT: br label [[CASE2]]
|
|
; CHECK: for.body.jt1:
|
|
; CHECK-NEXT: [[COUNT_JT1:%.*]] = phi i32 [ [[INC_JT1:%.*]], [[FOR_INC_JT1]] ]
|
|
; CHECK-NEXT: [[STATE_JT1:%.*]] = phi i32 [ [[STATE_NEXT_JT1:%.*]], [[FOR_INC_JT1]] ]
|
|
; CHECK-NEXT: br label [[CASE1]]
|
|
; CHECK: case1:
|
|
; CHECK-NEXT: [[COUNT2:%.*]] = phi i32 [ [[COUNT_JT1]], [[FOR_BODY_JT1:%.*]] ], [ [[COUNT]], [[FOR_BODY]] ]
|
|
; CHECK-NEXT: br label [[FOR_INC_JT2]]
|
|
; CHECK: case2:
|
|
; CHECK-NEXT: [[COUNT1:%.*]] = phi i32 [ [[COUNT_JT2]], [[FOR_BODY_JT2:%.*]] ], [ [[COUNT]], [[FOR_BODY]] ]
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[COUNT1]], 50
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_INC_JT1]], label [[SI_UNFOLD_FALSE:%.*]]
|
|
; CHECK: si.unfold.false:
|
|
; CHECK-NEXT: br label [[FOR_INC_JT2]]
|
|
; CHECK: for.inc:
|
|
; CHECK-NEXT: [[INC]] = add nsw i32 undef, 1
|
|
; CHECK-NEXT: [[CMP_EXIT:%.*]] = icmp slt i32 [[INC]], [[NUM:%.*]]
|
|
; CHECK-NEXT: br i1 [[CMP_EXIT]], label [[FOR_BODY]], label [[FOR_END:%.*]]
|
|
; CHECK: for.inc.jt2:
|
|
; CHECK-NEXT: [[COUNT4:%.*]] = phi i32 [ [[COUNT1]], [[SI_UNFOLD_FALSE]] ], [ [[COUNT2]], [[CASE1]] ]
|
|
; CHECK-NEXT: [[STATE_NEXT_JT2]] = phi i32 [ 2, [[CASE1]] ], [ 2, [[SI_UNFOLD_FALSE]] ]
|
|
; CHECK-NEXT: [[INC_JT2]] = add nsw i32 [[COUNT4]], 1
|
|
; CHECK-NEXT: [[CMP_EXIT_JT2:%.*]] = icmp slt i32 [[INC_JT2]], [[NUM]]
|
|
; CHECK-NEXT: br i1 [[CMP_EXIT_JT2]], label [[FOR_BODY_JT2]], label [[FOR_END]]
|
|
; CHECK: for.inc.jt1:
|
|
; CHECK-NEXT: [[COUNT3:%.*]] = phi i32 [ [[COUNT1]], [[CASE2]] ], [ [[COUNT]], [[FOR_BODY]] ]
|
|
; CHECK-NEXT: [[STATE_NEXT_JT1]] = phi i32 [ 1, [[CASE2]] ], [ 1, [[FOR_BODY]] ]
|
|
; CHECK-NEXT: [[INC_JT1]] = add nsw i32 [[COUNT3]], 1
|
|
; CHECK-NEXT: [[CMP_EXIT_JT1:%.*]] = icmp slt i32 [[INC_JT1]], [[NUM]]
|
|
; CHECK-NEXT: br i1 [[CMP_EXIT_JT1]], label [[FOR_BODY_JT1]], label [[FOR_END]]
|
|
; CHECK: for.end:
|
|
; CHECK-NEXT: ret i32 0
|
|
;
|
|
entry:
|
|
br label %for.body
|
|
|
|
for.body:
|
|
%count = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
|
|
%state = phi i32 [ 1, %entry ], [ %state.next, %for.inc ]
|
|
switch i32 %state, label %for.inc [
|
|
i32 1, label %case1
|
|
i32 2, label %case2
|
|
]
|
|
|
|
case1:
|
|
br label %for.inc
|
|
|
|
case2:
|
|
%cmp = icmp slt i32 %count, 50
|
|
%sel = select i1 %cmp, i32 1, i32 2
|
|
br label %for.inc
|
|
|
|
for.inc:
|
|
%state.next = phi i32 [ %sel, %case2 ], [ 1, %for.body ], [ 2, %case1 ]
|
|
%inc = add nsw i32 %count, 1
|
|
%cmp.exit = icmp slt i32 %inc, %num
|
|
br i1 %cmp.exit, label %for.body, label %for.end
|
|
|
|
for.end:
|
|
ret i32 0
|
|
}
|
|
|
|
define i32 @test2(i32 %num) {
|
|
; CHECK-LABEL: @test2(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: [[COUNT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ]
|
|
; CHECK-NEXT: [[STATE:%.*]] = phi i32 [ 1, [[ENTRY]] ], [ poison, [[FOR_INC]] ]
|
|
; CHECK-NEXT: switch i32 [[STATE]], label [[FOR_INC_JT1:%.*]] [
|
|
; CHECK-NEXT: i32 1, label [[CASE1:%.*]]
|
|
; CHECK-NEXT: i32 2, label [[CASE2:%.*]]
|
|
; CHECK-NEXT: ]
|
|
; CHECK: for.body.jt3:
|
|
; CHECK-NEXT: [[COUNT_JT3:%.*]] = phi i32 [ [[INC_JT3:%.*]], [[FOR_INC_JT3:%.*]] ]
|
|
; CHECK-NEXT: [[STATE_JT3:%.*]] = phi i32 [ [[STATE_NEXT_JT3:%.*]], [[FOR_INC_JT3]] ]
|
|
; CHECK-NEXT: br label [[FOR_INC_JT1]]
|
|
; CHECK: for.body.jt2:
|
|
; CHECK-NEXT: [[COUNT_JT2:%.*]] = phi i32 [ [[INC_JT2:%.*]], [[FOR_INC_JT2:%.*]] ]
|
|
; CHECK-NEXT: [[STATE_JT2:%.*]] = phi i32 [ [[STATE_NEXT_JT2:%.*]], [[FOR_INC_JT2]] ]
|
|
; CHECK-NEXT: br label [[CASE2]]
|
|
; CHECK: for.body.jt1:
|
|
; CHECK-NEXT: [[COUNT_JT1:%.*]] = phi i32 [ [[INC_JT1:%.*]], [[FOR_INC_JT1]] ]
|
|
; CHECK-NEXT: [[STATE_JT1:%.*]] = phi i32 [ [[STATE_NEXT_JT1:%.*]], [[FOR_INC_JT1]] ]
|
|
; CHECK-NEXT: br label [[CASE1]]
|
|
; CHECK: case1:
|
|
; CHECK-NEXT: [[COUNT5:%.*]] = phi i32 [ [[COUNT_JT1]], [[FOR_BODY_JT1:%.*]] ], [ [[COUNT]], [[FOR_BODY]] ]
|
|
; CHECK-NEXT: [[CMP_C1:%.*]] = icmp slt i32 [[COUNT5]], 50
|
|
; CHECK-NEXT: [[CMP2_C1:%.*]] = icmp slt i32 [[COUNT5]], 100
|
|
; CHECK-NEXT: br i1 [[CMP2_C1]], label [[SI_UNFOLD_TRUE:%.*]], label [[FOR_INC_JT3]]
|
|
; CHECK: case2:
|
|
; CHECK-NEXT: [[COUNT3:%.*]] = phi i32 [ [[COUNT_JT2]], [[FOR_BODY_JT2:%.*]] ], [ [[COUNT]], [[FOR_BODY]] ]
|
|
; CHECK-NEXT: [[CMP_C2:%.*]] = icmp slt i32 [[COUNT3]], 50
|
|
; CHECK-NEXT: [[CMP2_C2:%.*]] = icmp sgt i32 [[COUNT3]], 100
|
|
; CHECK-NEXT: br i1 [[CMP2_C2]], label [[FOR_INC_JT3]], label [[SI_UNFOLD_FALSE:%.*]]
|
|
; CHECK: si.unfold.false:
|
|
; CHECK-NEXT: br i1 [[CMP_C2]], label [[FOR_INC_JT1]], label [[SI_UNFOLD_FALSE1:%.*]]
|
|
; CHECK: si.unfold.false1:
|
|
; CHECK-NEXT: br label [[FOR_INC_JT2]]
|
|
; CHECK: si.unfold.true:
|
|
; CHECK-NEXT: br i1 [[CMP_C1]], label [[FOR_INC_JT1]], label [[SI_UNFOLD_FALSE2:%.*]]
|
|
; CHECK: si.unfold.false2:
|
|
; CHECK-NEXT: br label [[FOR_INC_JT2]]
|
|
; CHECK: for.inc:
|
|
; CHECK-NEXT: [[INC]] = add nsw i32 undef, 1
|
|
; CHECK-NEXT: [[CMP_EXIT:%.*]] = icmp slt i32 [[INC]], [[NUM:%.*]]
|
|
; CHECK-NEXT: br i1 [[CMP_EXIT]], label [[FOR_BODY]], label [[FOR_END:%.*]]
|
|
; CHECK: for.inc.jt3:
|
|
; CHECK-NEXT: [[COUNT6:%.*]] = phi i32 [ [[COUNT3]], [[CASE2]] ], [ [[COUNT5]], [[CASE1]] ]
|
|
; CHECK-NEXT: [[STATE_NEXT_JT3]] = phi i32 [ 3, [[CASE1]] ], [ 3, [[CASE2]] ]
|
|
; CHECK-NEXT: [[INC_JT3]] = add nsw i32 [[COUNT6]], 1
|
|
; CHECK-NEXT: [[CMP_EXIT_JT3:%.*]] = icmp slt i32 [[INC_JT3]], [[NUM]]
|
|
; CHECK-NEXT: br i1 [[CMP_EXIT_JT3]], label [[FOR_BODY_JT3:%.*]], label [[FOR_END]]
|
|
; CHECK: for.inc.jt2:
|
|
; CHECK-NEXT: [[COUNT7:%.*]] = phi i32 [ [[COUNT3]], [[SI_UNFOLD_FALSE1]] ], [ [[COUNT5]], [[SI_UNFOLD_FALSE2]] ]
|
|
; CHECK-NEXT: [[STATE_NEXT_JT2]] = phi i32 [ 2, [[SI_UNFOLD_FALSE1]] ], [ 2, [[SI_UNFOLD_FALSE2]] ]
|
|
; CHECK-NEXT: [[INC_JT2]] = add nsw i32 [[COUNT7]], 1
|
|
; CHECK-NEXT: [[CMP_EXIT_JT2:%.*]] = icmp slt i32 [[INC_JT2]], [[NUM]]
|
|
; CHECK-NEXT: br i1 [[CMP_EXIT_JT2]], label [[FOR_BODY_JT2]], label [[FOR_END]]
|
|
; CHECK: for.inc.jt1:
|
|
; CHECK-NEXT: [[COUNT4:%.*]] = phi i32 [ [[COUNT_JT3]], [[FOR_BODY_JT3]] ], [ [[COUNT3]], [[SI_UNFOLD_FALSE]] ], [ [[COUNT5]], [[SI_UNFOLD_TRUE]] ], [ [[COUNT]], [[FOR_BODY]] ]
|
|
; CHECK-NEXT: [[STATE_NEXT_JT1]] = phi i32 [ 1, [[FOR_BODY]] ], [ 1, [[SI_UNFOLD_FALSE]] ], [ 1, [[SI_UNFOLD_TRUE]] ], [ 1, [[FOR_BODY_JT3]] ]
|
|
; CHECK-NEXT: [[INC_JT1]] = add nsw i32 [[COUNT4]], 1
|
|
; CHECK-NEXT: [[CMP_EXIT_JT1:%.*]] = icmp slt i32 [[INC_JT1]], [[NUM]]
|
|
; CHECK-NEXT: br i1 [[CMP_EXIT_JT1]], label [[FOR_BODY_JT1]], label [[FOR_END]]
|
|
; CHECK: for.end:
|
|
; CHECK-NEXT: ret i32 0
|
|
;
|
|
entry:
|
|
br label %for.body
|
|
|
|
for.body:
|
|
%count = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
|
|
%state = phi i32 [ 1, %entry ], [ %state.next, %for.inc ]
|
|
switch i32 %state, label %for.inc [
|
|
i32 1, label %case1
|
|
i32 2, label %case2
|
|
]
|
|
|
|
case1:
|
|
%cmp.c1 = icmp slt i32 %count, 50
|
|
%cmp2.c1 = icmp slt i32 %count, 100
|
|
%state1.1 = select i1 %cmp.c1, i32 1, i32 2
|
|
%state1.2 = select i1 %cmp2.c1, i32 %state1.1, i32 3
|
|
br label %for.inc
|
|
|
|
case2:
|
|
%cmp.c2 = icmp slt i32 %count, 50
|
|
%cmp2.c2 = icmp sgt i32 %count, 100
|
|
%state2.1 = select i1 %cmp.c2, i32 1, i32 2
|
|
%state2.2 = select i1 %cmp2.c2, i32 3, i32 %state2.1
|
|
br label %for.inc
|
|
|
|
for.inc:
|
|
%state.next = phi i32 [ %state1.2, %case1 ], [ %state2.2, %case2 ], [ 1, %for.body ]
|
|
%inc = add nsw i32 %count, 1
|
|
%cmp.exit = icmp slt i32 %inc, %num
|
|
br i1 %cmp.exit, label %for.body, label %for.end
|
|
|
|
for.end:
|
|
ret i32 0
|
|
}
|
|
|
|
define i32 @test3(i32 %num) {
|
|
; CHECK-LABEL: @test3(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: [[COUNT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ]
|
|
; CHECK-NEXT: [[STATE:%.*]] = phi i32 [ 1, [[ENTRY]] ], [ poison, [[FOR_INC]] ]
|
|
; CHECK-NEXT: switch i32 [[STATE]], label [[FOR_INC_JT1:%.*]] [
|
|
; CHECK-NEXT: i32 1, label [[CASE1:%.*]]
|
|
; CHECK-NEXT: i32 2, label [[CASE2:%.*]]
|
|
; CHECK-NEXT: ]
|
|
; CHECK: for.body.jt4:
|
|
; CHECK-NEXT: [[COUNT_JT4:%.*]] = phi i32 [ [[INC_JT4:%.*]], [[FOR_INC_JT4:%.*]] ]
|
|
; CHECK-NEXT: [[STATE_JT4:%.*]] = phi i32 [ [[STATE_NEXT_JT4:%.*]], [[FOR_INC_JT4]] ]
|
|
; CHECK-NEXT: br label [[FOR_INC_JT1]]
|
|
; CHECK: for.body.jt3:
|
|
; CHECK-NEXT: [[COUNT_JT3:%.*]] = phi i32 [ [[INC_JT3:%.*]], [[FOR_INC_JT3:%.*]] ]
|
|
; CHECK-NEXT: [[STATE_JT3:%.*]] = phi i32 [ [[STATE_NEXT_JT3:%.*]], [[FOR_INC_JT3]] ]
|
|
; CHECK-NEXT: br label [[FOR_INC_JT1]]
|
|
; CHECK: for.body.jt2:
|
|
; CHECK-NEXT: [[COUNT_JT2:%.*]] = phi i32 [ [[INC_JT2:%.*]], [[FOR_INC_JT2:%.*]] ]
|
|
; CHECK-NEXT: [[STATE_JT2:%.*]] = phi i32 [ [[STATE_NEXT_JT2:%.*]], [[FOR_INC_JT2]] ]
|
|
; CHECK-NEXT: br label [[CASE2]]
|
|
; CHECK: for.body.jt1:
|
|
; CHECK-NEXT: [[COUNT_JT1:%.*]] = phi i32 [ [[INC_JT1:%.*]], [[FOR_INC_JT1]] ]
|
|
; CHECK-NEXT: [[STATE_JT1:%.*]] = phi i32 [ [[STATE_NEXT_JT1:%.*]], [[FOR_INC_JT1]] ]
|
|
; CHECK-NEXT: br label [[CASE1]]
|
|
; CHECK: case1:
|
|
; CHECK-NEXT: [[COUNT5:%.*]] = phi i32 [ [[COUNT_JT1]], [[FOR_BODY_JT1:%.*]] ], [ [[COUNT]], [[FOR_BODY]] ]
|
|
; CHECK-NEXT: br label [[FOR_INC_JT2]]
|
|
; CHECK: case2:
|
|
; CHECK-NEXT: [[COUNT4:%.*]] = phi i32 [ [[COUNT_JT2]], [[FOR_BODY_JT2:%.*]] ], [ [[COUNT]], [[FOR_BODY]] ]
|
|
; CHECK-NEXT: [[CMP_1:%.*]] = icmp slt i32 [[COUNT4]], 50
|
|
; CHECK-NEXT: [[CMP_2:%.*]] = icmp slt i32 [[COUNT4]], 100
|
|
; CHECK-NEXT: [[TMP0:%.*]] = and i32 [[COUNT4]], 1
|
|
; CHECK-NEXT: [[CMP_3:%.*]] = icmp eq i32 [[TMP0]], 0
|
|
; CHECK-NEXT: br i1 [[CMP_3]], label [[SI_UNFOLD_TRUE:%.*]], label [[SI_UNFOLD_FALSE:%.*]]
|
|
; CHECK: si.unfold.true:
|
|
; CHECK-NEXT: br i1 [[CMP_1]], label [[FOR_INC_JT1]], label [[SI_UNFOLD_FALSE2:%.*]]
|
|
; CHECK: si.unfold.false:
|
|
; CHECK-NEXT: br i1 [[CMP_2]], label [[FOR_INC_JT3]], label [[SI_UNFOLD_FALSE1:%.*]]
|
|
; CHECK: si.unfold.false1:
|
|
; CHECK-NEXT: br label [[FOR_INC_JT4]]
|
|
; CHECK: si.unfold.false2:
|
|
; CHECK-NEXT: br label [[FOR_INC_JT2]]
|
|
; CHECK: for.inc:
|
|
; CHECK-NEXT: [[INC]] = add nsw i32 undef, 1
|
|
; CHECK-NEXT: [[CMP_EXIT:%.*]] = icmp slt i32 [[INC]], [[NUM:%.*]]
|
|
; CHECK-NEXT: br i1 [[CMP_EXIT]], label [[FOR_BODY]], label [[FOR_END:%.*]]
|
|
; CHECK: for.inc.jt4:
|
|
; CHECK-NEXT: [[STATE_NEXT_JT4]] = phi i32 [ 4, [[SI_UNFOLD_FALSE1]] ]
|
|
; CHECK-NEXT: [[INC_JT4]] = add nsw i32 [[COUNT4]], 1
|
|
; CHECK-NEXT: [[CMP_EXIT_JT4:%.*]] = icmp slt i32 [[INC_JT4]], [[NUM]]
|
|
; CHECK-NEXT: br i1 [[CMP_EXIT_JT4]], label [[FOR_BODY_JT4:%.*]], label [[FOR_END]]
|
|
; CHECK: for.inc.jt3:
|
|
; CHECK-NEXT: [[STATE_NEXT_JT3]] = phi i32 [ 3, [[SI_UNFOLD_FALSE]] ]
|
|
; CHECK-NEXT: [[INC_JT3]] = add nsw i32 [[COUNT4]], 1
|
|
; CHECK-NEXT: [[CMP_EXIT_JT3:%.*]] = icmp slt i32 [[INC_JT3]], [[NUM]]
|
|
; CHECK-NEXT: br i1 [[CMP_EXIT_JT3]], label [[FOR_BODY_JT3:%.*]], label [[FOR_END]]
|
|
; CHECK: for.inc.jt2:
|
|
; CHECK-NEXT: [[COUNT6:%.*]] = phi i32 [ [[COUNT4]], [[SI_UNFOLD_FALSE2]] ], [ [[COUNT5]], [[CASE1]] ]
|
|
; CHECK-NEXT: [[STATE_NEXT_JT2]] = phi i32 [ 2, [[CASE1]] ], [ 2, [[SI_UNFOLD_FALSE2]] ]
|
|
; CHECK-NEXT: [[INC_JT2]] = add nsw i32 [[COUNT6]], 1
|
|
; CHECK-NEXT: [[CMP_EXIT_JT2:%.*]] = icmp slt i32 [[INC_JT2]], [[NUM]]
|
|
; CHECK-NEXT: br i1 [[CMP_EXIT_JT2]], label [[FOR_BODY_JT2]], label [[FOR_END]]
|
|
; CHECK: for.inc.jt1:
|
|
; CHECK-NEXT: [[COUNT3:%.*]] = phi i32 [ [[COUNT_JT4]], [[FOR_BODY_JT4]] ], [ [[COUNT_JT3]], [[FOR_BODY_JT3]] ], [ [[COUNT4]], [[SI_UNFOLD_TRUE]] ], [ [[COUNT]], [[FOR_BODY]] ]
|
|
; CHECK-NEXT: [[STATE_NEXT_JT1]] = phi i32 [ 1, [[FOR_BODY]] ], [ 1, [[SI_UNFOLD_TRUE]] ], [ 1, [[FOR_BODY_JT3]] ], [ 1, [[FOR_BODY_JT4]] ]
|
|
; CHECK-NEXT: [[INC_JT1]] = add nsw i32 [[COUNT3]], 1
|
|
; CHECK-NEXT: [[CMP_EXIT_JT1:%.*]] = icmp slt i32 [[INC_JT1]], [[NUM]]
|
|
; CHECK-NEXT: br i1 [[CMP_EXIT_JT1]], label [[FOR_BODY_JT1]], label [[FOR_END]]
|
|
; CHECK: for.end:
|
|
; CHECK-NEXT: ret i32 0
|
|
;
|
|
entry:
|
|
br label %for.body
|
|
|
|
for.body:
|
|
%count = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
|
|
%state = phi i32 [ 1, %entry ], [ %state.next, %for.inc ]
|
|
switch i32 %state, label %for.inc [
|
|
i32 1, label %case1
|
|
i32 2, label %case2
|
|
]
|
|
|
|
case1:
|
|
br label %for.inc
|
|
|
|
case2:
|
|
%cmp.1 = icmp slt i32 %count, 50
|
|
%cmp.2 = icmp slt i32 %count, 100
|
|
%0 = and i32 %count, 1
|
|
%cmp.3 = icmp eq i32 %0, 0
|
|
%sel.1 = select i1 %cmp.1, i32 1, i32 2
|
|
%sel.2 = select i1 %cmp.2, i32 3, i32 4
|
|
%sel.3 = select i1 %cmp.3, i32 %sel.1, i32 %sel.2
|
|
br label %for.inc
|
|
|
|
for.inc:
|
|
%state.next = phi i32 [ %sel.3, %case2 ], [ 1, %for.body ], [ 2, %case1 ]
|
|
%inc = add nsw i32 %count, 1
|
|
%cmp.exit = icmp slt i32 %inc, %num
|
|
br i1 %cmp.exit, label %for.body, label %for.end
|
|
|
|
for.end:
|
|
ret i32 0
|
|
}
|
|
|
|
define void @select_coming_elsewhere(i1 %cond, i16 %a, i16 %b) {
|
|
; CHECK-LABEL: @select_coming_elsewhere(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[DIV:%.*]] = select i1 [[COND:%.*]], i16 [[A:%.*]], i16 [[B:%.*]]
|
|
; CHECK-NEXT: br label [[FOR_COND:%.*]]
|
|
; CHECK: for.cond:
|
|
; CHECK-NEXT: [[E_ADDR_0:%.*]] = phi i16 [ 0, [[ENTRY:%.*]] ], [ [[DIV]], [[LOR_END:%.*]] ]
|
|
; CHECK-NEXT: switch i16 [[E_ADDR_0]], label [[LOR_END]] [
|
|
; CHECK-NEXT: ]
|
|
; CHECK: lor.end:
|
|
; CHECK-NEXT: br label [[FOR_COND]]
|
|
;
|
|
entry:
|
|
%div = select i1 %cond, i16 %a, i16 %b
|
|
br label %for.cond
|
|
|
|
for.cond: ; preds = %lor.end, %entry
|
|
%e.addr.0 = phi i16 [ 0, %entry ], [ %div, %lor.end ]
|
|
switch i16 %e.addr.0, label %lor.end [
|
|
]
|
|
|
|
lor.end: ; preds = %for.cond
|
|
br label %for.cond
|
|
}
|
|
|
|
define void @pr65222(i32 %flags, i1 %cmp, i1 %tobool.not) {
|
|
; CHECK-LABEL: @pr65222(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[WHILE_COND:%.*]]
|
|
; CHECK: while.cond:
|
|
; CHECK-NEXT: br i1 [[CMP:%.*]], label [[THEN:%.*]], label [[IF_END:%.*]]
|
|
; CHECK: then:
|
|
; CHECK-NEXT: br i1 [[TOBOOL_NOT:%.*]], label [[SI_UNFOLD_TRUE:%.*]], label [[SI_UNFOLD_FALSE:%.*]]
|
|
; CHECK: si.unfold.true:
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[IF_END]], label [[SI_UNFOLD_FALSE2:%.*]]
|
|
; CHECK: si.unfold.false:
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[IF_END]], label [[SI_UNFOLD_FALSE1:%.*]]
|
|
; CHECK: si.unfold.false1:
|
|
; CHECK-NEXT: br label [[IF_END]]
|
|
; CHECK: si.unfold.false2:
|
|
; CHECK-NEXT: br label [[IF_END]]
|
|
; CHECK: if.end:
|
|
; CHECK-NEXT: [[UNFOLDED:%.*]] = phi i32 [ [[FLAGS:%.*]], [[WHILE_COND]] ], [ 3, [[SI_UNFOLD_TRUE]] ], [ 2, [[SI_UNFOLD_FALSE]] ], [ 0, [[SI_UNFOLD_FALSE1]] ], [ 1, [[SI_UNFOLD_FALSE2]] ]
|
|
; CHECK-NEXT: [[OTHER:%.*]] = phi i32 [ [[FLAGS]], [[WHILE_COND]] ], [ 0, [[SI_UNFOLD_TRUE]] ], [ 0, [[SI_UNFOLD_FALSE]] ], [ 0, [[SI_UNFOLD_FALSE1]] ], [ 0, [[SI_UNFOLD_FALSE2]] ]
|
|
; CHECK-NEXT: switch i32 [[UNFOLDED]], label [[UNREACHABLE:%.*]] [
|
|
; CHECK-NEXT: i32 0, label [[SW_BB:%.*]]
|
|
; CHECK-NEXT: ]
|
|
; CHECK: unreachable:
|
|
; CHECK-NEXT: unreachable
|
|
; CHECK: sw.bb:
|
|
; CHECK-NEXT: br label [[WHILE_COND]]
|
|
;
|
|
entry:
|
|
br label %while.cond
|
|
|
|
while.cond: ; preds = %sw.bb147, %if.end, %entry
|
|
br i1 %cmp, label %then, label %if.end
|
|
|
|
then: ; preds = %while.cond
|
|
%cond = select i1 %cmp, i32 2, i32 0
|
|
%cond1 = select i1 %cmp, i32 3, i32 1
|
|
%tounfold = select i1 %tobool.not, i32 %cond1, i32 %cond
|
|
br label %if.end
|
|
|
|
if.end: ; preds = %then, %while.cond
|
|
%unfolded = phi i32 [ %tounfold, %then ], [ %flags, %while.cond ]
|
|
%other = phi i32 [ 0, %then ], [ %flags, %while.cond ]
|
|
switch i32 %unfolded, label %unreachable [
|
|
i32 0, label %sw.bb
|
|
]
|
|
|
|
unreachable:
|
|
unreachable
|
|
|
|
sw.bb: ; preds = %if.end
|
|
br label %while.cond
|
|
}
|