Skip to content

Commit

Permalink
[GuardWidening] Choose right point for generating wide condition for …
Browse files Browse the repository at this point in the history
…branches. PR60234

When guards are represented as widenable branches, there is a tricky
situation when the branch stays in loop but widenable condition doesn't.
It means that the widenable condition is loop-invariant, and some other
optimizations could have done changes using this fact.

If widening is allowed to create widened condition inside this loop,
and join the loop-invariant wc with some non-invariant facts, it can
cause miscompile. See example of this at #60234.

The solution is to adjust the point of generationg the wide condition,
and therefore of hoisting all related parts there. It should not be before
the branch, but before the widenable_condition call. The fact that `wc()`
and the wide condition are in the same block guarantees that they will
not violate the invariance property for any loop.

Differential Revision: https://reviews.llvm.org/D142693
Reviewed By: apilipenko
  • Loading branch information
xortator committed Jan 31, 2023
1 parent ff96267 commit 5cb568a
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 37 deletions.
24 changes: 21 additions & 3 deletions llvm/lib/Transforms/Scalar/GuardWidening.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,23 @@ static void eliminateGuard(Instruction *GuardInst, MemorySSAUpdater *MSSAU) {
++GuardsEliminated;
}

/// Find a point at which the widened condition of \p Guard should be inserted.
/// When it is represented as intrinsic call, we can do it right before the call
/// instruction. However, when we are dealing with widenable branch, we must
/// account for the following situation: widening should not turn a
/// loop-invariant condition into a loop-variant. It means that if
/// widenable.condition() call is invariant (w.r.t. any loop), the new wide
/// condition should stay invariant. Otherwise there can be a miscompile, like
/// the one described at https://github.com/llvm/llvm-project/issues/60234. The
/// safest way to do it is to expand the new condition at WC's block.
static Instruction *findInsertionPointForWideCondition(Instruction *Guard) {
Value *Condition, *WC;
BasicBlock *IfTrue, *IfFalse;
if (parseWidenableBranch(Guard, Condition, WC, IfTrue, IfFalse))
return cast<Instruction>(WC);
return Guard;
}

class GuardWideningImpl {
DominatorTree &DT;
PostDominatorTree *PDT;
Expand Down Expand Up @@ -263,8 +280,8 @@ class GuardWideningImpl {
void widenGuard(Instruction *ToWiden, Value *NewCondition,
bool InvertCondition) {
Value *Result;

widenCondCommon(getCondition(ToWiden), NewCondition, ToWiden, Result,
Instruction *InsertPt = findInsertionPointForWideCondition(ToWiden);
widenCondCommon(getCondition(ToWiden), NewCondition, InsertPt, Result,
InvertCondition);
if (isGuardAsWidenableBranch(ToWiden)) {
setWidenableBranchCond(cast<BranchInst>(ToWiden), Result);
Expand Down Expand Up @@ -422,7 +439,8 @@ GuardWideningImpl::computeWideningScore(Instruction *DominatedInstr,
HoistingOutOfLoop = true;
}

if (!isAvailableAt(getCondition(DominatedInstr), DominatingGuard))
auto *WideningPoint = findInsertionPointForWideCondition(DominatingGuard);
if (!isAvailableAt(getCondition(DominatedInstr), WideningPoint))
return WS_IllegalOrNegative;

// If the guard was conditional executed, it may never be reached
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
define void @f_0(i1 %cond_0, i1 %cond_1) {
; CHECK-LABEL: @f_0(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1:%.*]]
; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]
; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0:![0-9]+]]
; CHECK: deopt:
Expand Down Expand Up @@ -50,8 +50,8 @@ guarded1: ; preds = %guarded
define void @f_1(i1 %cond_0, i1 %cond_1) {
; CHECK-LABEL: @f_1(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1:%.*]]
; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]
; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]]
; CHECK: deopt:
Expand Down Expand Up @@ -110,9 +110,9 @@ define void @f_2(i32 %a, i32 %b) {
; CHECK-LABEL: @f_2(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[COND_0:%.*]] = icmp ult i32 [[A:%.*]], 10
; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
; CHECK-NEXT: [[COND_1:%.*]] = icmp ult i32 [[B:%.*]], 10
; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_0]], [[COND_1]]
; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]
; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]]
; CHECK: deopt:
Expand Down Expand Up @@ -231,9 +231,9 @@ define void @f_4(i32 %a, i32 %b) {
; CHECK-LABEL: @f_4(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[COND_0:%.*]] = icmp ult i32 [[A:%.*]], 10
; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
; CHECK-NEXT: [[COND_1:%.*]] = icmp ult i32 [[B:%.*]], 10
; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_0]], [[COND_1]]
; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]
; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]]
; CHECK: deopt:
Expand Down Expand Up @@ -289,8 +289,8 @@ define void @f_5(i32 %a) {
; CHECK-LABEL: @f_5(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[COND_0:%.*]] = icmp ugt i32 [[A:%.*]], 7
; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
; CHECK-NEXT: [[WIDE_CHK:%.*]] = icmp uge i32 [[A]], 11
; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]
; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]]
; CHECK: deopt:
Expand Down Expand Up @@ -397,9 +397,9 @@ define void @f_7(i32 %a, ptr %cond_buf) {
; CHECK-LABEL: @f_7(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[COND_1:%.*]] = load volatile i1, ptr [[COND_BUF:%.*]], align 1
; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
; CHECK-NEXT: [[COND_3:%.*]] = icmp ult i32 [[A:%.*]], 7
; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_1]], [[COND_3]]
; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]
; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]]
; CHECK: deopt:
Expand Down Expand Up @@ -484,9 +484,9 @@ define void @f_8(i32 %a, i1 %cond_1, i1 %cond_2) {
; CHECK: guarded:
; CHECK-NEXT: br i1 undef, label [[LOOP]], label [[LEAVE:%.*]]
; CHECK: leave:
; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
; CHECK-NEXT: [[COND_3:%.*]] = icmp ult i32 [[A:%.*]], 7
; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_2:%.*]], [[COND_3]]
; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND3]]
; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND4]], label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]]
; CHECK: deopt2:
Expand Down Expand Up @@ -663,8 +663,8 @@ define void @f_11(i32 %a, i1 %cond_0, i1 %cond_1) {
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[OUTER_HEADER:%.*]]
; CHECK: outer_header:
; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1:%.*]]
; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]
; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]]
; CHECK: deopt:
Expand Down Expand Up @@ -725,7 +725,6 @@ exit: ; preds = %outer_latch
define void @f_12(i32 %a0) {
; CHECK-LABEL: @f_12(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
; CHECK-NEXT: [[A1:%.*]] = mul i32 [[A0:%.*]], [[A0]]
; CHECK-NEXT: [[A2:%.*]] = mul i32 [[A1]], [[A1]]
; CHECK-NEXT: [[A3:%.*]] = mul i32 [[A2]], [[A2]]
Expand Down Expand Up @@ -758,6 +757,7 @@ define void @f_12(i32 %a0) {
; CHECK-NEXT: [[A30:%.*]] = mul i32 [[A29]], [[A29]]
; CHECK-NEXT: [[COND:%.*]] = trunc i32 [[A30]] to i1
; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 true, [[COND]]
; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]
; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]]
; CHECK: deopt:
Expand Down Expand Up @@ -830,8 +830,8 @@ define void @f_13(i32 %a) {
; CHECK-LABEL: @f_13(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[COND_0:%.*]] = icmp ult i32 [[A:%.*]], 14
; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
; CHECK-NEXT: [[WIDE_CHK:%.*]] = icmp ult i32 [[A]], 10
; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]
; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]]
; CHECK: deopt:
Expand Down Expand Up @@ -1025,8 +1025,8 @@ guarded1: ; preds = %guarded
define void @swapped_wb(i1 %cond_0, i1 %cond_1) {
; CHECK-LABEL: @swapped_wb(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1:%.*]]
; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDENABLE_COND]], [[WIDE_CHK]]
; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]]
; CHECK: deopt:
Expand Down Expand Up @@ -1067,8 +1067,8 @@ guarded1: ; preds = %guarded
define void @trivial_wb(i1 %cond_0) {
; CHECK-LABEL: @trivial_wb(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 true, [[COND_0:%.*]]
; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
; CHECK-NEXT: [[TMP0:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]
; CHECK-NEXT: br i1 [[TMP0]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]]
; CHECK: deopt:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@

declare i32 @llvm.experimental.deoptimize.i32(...)

; FIXME: Make sure the two loop-invariant conditions can be widened together,
; and the widening point is outside the loop.
; Make sure the two loop-invariant conditions can be widened together,
; and the widening point is outside the loop.
define i32 @test_01(i32 %start, i32 %x) {
; CHECK-LABEL: @test_01(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[START:%.*]], [[X:%.*]]
; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 true, [[COND]]
; CHECK-NEXT: [[WC1:%.*]] = call i1 @llvm.experimental.widenable.condition()
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 true, [[COND]]
; CHECK-NEXT: [[TMP0:%.*]] = and i1 [[WIDE_CHK]], [[WC1]]
; CHECK-NEXT: br i1 [[TMP0]], label [[GUARD_BLOCK:%.*]], label [[EXIT_BY_WC:%.*]]
; CHECK: exit_by_wc:
Expand Down Expand Up @@ -65,25 +65,23 @@ failure:
}


; FIXME: Make sure the loop-variant condition is not widened into loop-invariant.
; Make sure the loop-variant condition is not widened into loop-invariant.
define i32 @test_02(i32 %start, i32 %x) {
; CHECK-LABEL: @test_02(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[WC1:%.*]] = call i1 @llvm.experimental.widenable.condition()
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[IV]], [[X:%.*]]
; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 true, [[COND]]
; CHECK-NEXT: [[TMP0:%.*]] = and i1 [[WIDE_CHK]], [[WC1]]
; CHECK-NEXT: br i1 [[TMP0]], label [[GUARD_BLOCK:%.*]], label [[EXIT_BY_WC:%.*]]
; CHECK-NEXT: br i1 [[WC1]], label [[GUARD_BLOCK:%.*]], label [[EXIT_BY_WC:%.*]]
; CHECK: exit_by_wc:
; CHECK-NEXT: [[RVAL1:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 [[IV]]) ]
; CHECK-NEXT: ret i32 [[RVAL1]]
; CHECK: guard_block:
; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[IV]], [[X:%.*]]
; CHECK-NEXT: [[WC2:%.*]] = call i1 @llvm.experimental.widenable.condition()
; CHECK-NEXT: [[GUARD:%.*]] = and i1 [[COND]], [[WC2]]
; CHECK-NEXT: br i1 true, label [[BACKEDGE]], label [[FAILURE:%.*]]
; CHECK-NEXT: br i1 [[GUARD]], label [[BACKEDGE]], label [[FAILURE:%.*]]
; CHECK: backedge:
; CHECK-NEXT: call void @side_effect()
; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
Expand Down Expand Up @@ -125,16 +123,16 @@ failure:
ret i32 %rval2
}

; FIXME: Same as test_01, but the initial condition is not immediately WC.
; Same as test_01, but the initial condition is not immediately WC.
define i32 @test_03(i32 %start, i32 %x, i1 %c) {
; CHECK-LABEL: @test_03(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[START:%.*]], [[X:%.*]]
; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[C:%.*]], [[COND]]
; CHECK-NEXT: [[WC1:%.*]] = call i1 @llvm.experimental.widenable.condition()
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[C:%.*]], [[COND]]
; CHECK-NEXT: [[INVARIANT:%.*]] = and i1 [[WIDE_CHK]], [[WC1]]
; CHECK-NEXT: br i1 [[INVARIANT]], label [[GUARD_BLOCK:%.*]], label [[EXIT_BY_WC:%.*]]
; CHECK: exit_by_wc:
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/Transforms/GuardWidening/mixed_guards.ll
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ guarded1: ; preds = %guarded
define void @test_02(i1 %cond_0, i1 %cond_1) {
; CHECK-LABEL: @test_02(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1:%.*]]
; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]
; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]]
; CHECK: deopt:
Expand Down
18 changes: 8 additions & 10 deletions llvm/test/Transforms/GuardWidening/pr60234.ll
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,28 @@

declare i32 @llvm.experimental.deoptimize.i32(...)

; FIXME: Make sure that guard widening does not turn loop-invariant condition
; (that then gets optimized basing on this fact) into non-invariant.
; https://github.com/llvm/llvm-project/issues/60234 explains how it causes
; a miscompile.
; Make sure that guard widening does not turn loop-invariant condition
; (that then gets optimized basing on this fact) into non-invariant.
; https://github.com/llvm/llvm-project/issues/60234 explains how it causes
; a miscompile.
define i32 @test(i32 %start) {
; CHECK-LABEL: @test(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[WC1:%.*]] = call i1 @llvm.experimental.widenable.condition()
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
; CHECK-NEXT: [[START_PLUS_1:%.*]] = add i32 [[START]], 1
; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[START_PLUS_1]], [[IV]]
; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 true, [[COND]]
; CHECK-NEXT: [[TMP0:%.*]] = and i1 [[WIDE_CHK]], [[WC1]]
; CHECK-NEXT: br i1 [[TMP0]], label [[GUARD_BLOCK:%.*]], label [[EXIT_BY_WC:%.*]]
; CHECK-NEXT: br i1 [[WC1]], label [[GUARD_BLOCK:%.*]], label [[EXIT_BY_WC:%.*]]
; CHECK: exit_by_wc:
; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i32 [ [[START]], [[LOOP]] ]
; CHECK-NEXT: [[RVAL1:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 [[IV_LCSSA]]) ]
; CHECK-NEXT: ret i32 [[RVAL1]]
; CHECK: guard_block:
; CHECK-NEXT: [[START_PLUS_1:%.*]] = add i32 [[START]], 1
; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[START_PLUS_1]], [[IV]]
; CHECK-NEXT: [[WC2:%.*]] = call i1 @llvm.experimental.widenable.condition()
; CHECK-NEXT: [[GUARD:%.*]] = and i1 [[COND]], [[WC2]]
; CHECK-NEXT: br i1 true, label [[BACKEDGE]], label [[FAILURE:%.*]]
; CHECK-NEXT: br i1 [[GUARD]], label [[BACKEDGE]], label [[FAILURE:%.*]]
; CHECK: backedge:
; CHECK-NEXT: call void @side_effect()
; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
Expand Down

0 comments on commit 5cb568a

Please sign in to comment.