Skip to content

Commit

Permalink
hacks over hacks over hacks
Browse files Browse the repository at this point in the history
  • Loading branch information
nikic committed Jan 18, 2024
1 parent f204886 commit e484a38
Show file tree
Hide file tree
Showing 8 changed files with 157 additions and 82 deletions.
17 changes: 15 additions & 2 deletions llvm/include/llvm/Analysis/ValueLattice.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ class ValueLatticeElement {
/// We can not precisely model the dynamic values this value might take.
/// No transitions are allowed after reaching overdefined.
overdefined,

/// TODO
speculative,
};

ValueLatticeElementTy Tag : 8;
Expand All @@ -98,6 +101,7 @@ class ValueLatticeElement {
case undef:
case constant:
case notconstant:
case speculative:
break;
case constantrange_including_undef:
case constantrange:
Expand Down Expand Up @@ -164,6 +168,7 @@ class ValueLatticeElement {
case overdefined:
case unknown:
case undef:
case speculative:
break;
}
}
Expand All @@ -183,6 +188,7 @@ class ValueLatticeElement {
case overdefined:
case unknown:
case undef:
case speculative:
break;
}
Other.Tag = unknown;
Expand Down Expand Up @@ -234,6 +240,12 @@ class ValueLatticeElement {
return Res;
}

static ValueLatticeElement getSpeculative() {
ValueLatticeElement Res;
Res.Tag = speculative;
return Res;
}

bool isUndef() const { return Tag == undef; }
bool isUnknown() const { return Tag == unknown; }
bool isUnknownOrUndef() const { return Tag == unknown || Tag == undef; }
Expand All @@ -251,6 +263,7 @@ class ValueLatticeElement {
(UndefAllowed || Range.isSingleElement()));
}
bool isOverdefined() const { return Tag == overdefined; }
bool isSpeculative() const { return Tag == speculative; }

Constant *getConstant() const {
assert(isConstant() && "Cannot get the constant of a non-constant!");
Expand Down Expand Up @@ -384,9 +397,9 @@ class ValueLatticeElement {
/// true if this object has been changed.
bool mergeIn(const ValueLatticeElement &RHS,
MergeOptions Opts = MergeOptions()) {
if (RHS.isUnknown() || isOverdefined())
if (RHS.isUnknown() || isOverdefined() || isSpeculative())
return false;
if (RHS.isOverdefined()) {
if (RHS.isOverdefined() || RHS.isSpeculative()) {
markOverdefined();
return true;
}
Expand Down
83 changes: 60 additions & 23 deletions llvm/lib/Analysis/LazyValueInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -372,18 +372,29 @@ class LazyValueInfoImpl {
SmallVector<std::pair<BasicBlock*, Value*>, 8> BlockValueStack;

/// Keeps track of which block-value pairs are in BlockValueStack.
DenseSet<std::pair<BasicBlock*, Value*> > BlockValueSet;

/// Push BV onto BlockValueStack unless it's already in there.
/// Returns true on success.
bool pushBlockValue(const std::pair<BasicBlock *, Value *> &BV) {
if (!BlockValueSet.insert(BV).second)
return false; // It's already in the stack.
DenseMap<std::pair<BasicBlock*, Value*>, bool> BlockValueSet;

bool isSameValueCycle(BasicBlock *BB, Value *Val) const {
for (auto [StackBB, StackVal] : reverse(BlockValueStack)) {
if (StackBB == BB && StackVal == Val)
return true;
if (StackVal != Val)
return false;
}
llvm_unreachable("Not a cycle?");
}

LLVM_DEBUG(dbgs() << "PUSH: " << *BV.second << " in "
<< BV.first->getName() << "\n");
BlockValueStack.push_back(BV);
return true;
std::optional<ValueLatticeElement> getCachedValueInfo(Value *Val,
BasicBlock *BB) const {
if (std::optional<ValueLatticeElement> Res =
TheCache.getCachedValueInfo(Val, BB)) {
if (!Res->isSpeculative())
return Res;
auto It = BlockValueSet.find({BB, Val});
if (It == BlockValueSet.end() || It->second)
return Res;
}
return std::nullopt;
}

AssumptionCache *AC; ///< A pointer to the cache of @llvm.assume calls.
Expand Down Expand Up @@ -573,16 +584,34 @@ LazyValueInfoImpl::getBlockValue(Value *Val, BasicBlock *BB,
return ValueLatticeElement::get(VC);

if (std::optional<ValueLatticeElement> OptLatticeVal =
TheCache.getCachedValueInfo(Val, BB)) {
getCachedValueInfo(Val, BB)) {
intersectAssumeOrGuardBlockValueConstantRange(Val, *OptLatticeVal, CxtI);
return OptLatticeVal;
}

// We have hit a cycle, assume overdefined.
if (!pushBlockValue({ BB, Val }))
// We have hit a cycle.
auto Res = BlockValueSet.try_emplace({BB, Val}, false);
if (!Res.second) {
// TODO
if (isSameValueCycle(BB, Val)) {
for (auto &Pair : reverse(BlockValueStack)) {
if (Pair.first == BB && Pair.second == Val)
break;
// Mark as speculative.
BlockValueSet.find({BB, Val})->second = true;
}
LLVM_DEBUG(dbgs() << "SPECULATE: " << *Val << " in " << BB->getName()
<< "\n");
return ValueLatticeElement::getSpeculative();
}

// In all other cases, assume overdefined.
return ValueLatticeElement::getOverdefined();
}

// Yet to be resolved.
LLVM_DEBUG(dbgs() << "PUSH: " << *Val << " in " << BB->getName() << "\n");
BlockValueStack.push_back({BB, Val});
return std::nullopt;
}

Expand All @@ -605,8 +634,7 @@ static ValueLatticeElement getFromRangeMetadata(Instruction *BBI) {

bool LazyValueInfoImpl::solveBlockValue(Value *Val, BasicBlock *BB) {
assert(!isa<Constant>(Val) && "Value should not be constant");
assert(!TheCache.getCachedValueInfo(Val, BB) &&
"Value should not be in cache");
assert(!getCachedValueInfo(Val, BB) && "Value should not be in cache");

// Hold off inserting this value into the Cache in case we have to return
// false and come back later.
Expand Down Expand Up @@ -728,7 +756,14 @@ LazyValueInfoImpl::solveBlockValueNonLocal(Value *Val, BasicBlock *BB) {
// Explore that input, then return here
return std::nullopt;

Result.mergeIn(*EdgeResult);
if (Result.isSpeculative()) {
Result = *EdgeResult;
} else if (EdgeResult->isSpeculative()) {
if (Result.isUnknown())
Result = *EdgeResult;
} else {
Result.mergeIn(*EdgeResult);
}

// If we hit overdefined, exit early. The BlockVals entry is already set
// to overdefined.
Expand Down Expand Up @@ -1489,6 +1524,14 @@ LazyValueInfoImpl::getEdgeValue(Value *Val, BasicBlock *BBFrom,
if (Constant *VC = dyn_cast<Constant>(Val))
return ValueLatticeElement::get(VC);

std::optional<ValueLatticeElement> OptInBlock =
getBlockValue(Val, BBFrom, BBFrom->getTerminator());
if (!OptInBlock)
return std::nullopt;
ValueLatticeElement &InBlock = *OptInBlock;
if (InBlock.isSpeculative())
return InBlock;

std::optional<ValueLatticeElement> LocalResult =
getEdgeValueLocal(Val, BBFrom, BBTo, /*UseBlockValue*/ true);
if (!LocalResult)
Expand All @@ -1498,12 +1541,6 @@ LazyValueInfoImpl::getEdgeValue(Value *Val, BasicBlock *BBFrom,
// Can't get any more precise here
return LocalResult;

std::optional<ValueLatticeElement> OptInBlock =
getBlockValue(Val, BBFrom, BBFrom->getTerminator());
if (!OptInBlock)
return std::nullopt;
ValueLatticeElement &InBlock = *OptInBlock;

// We can use the context instruction (generically the ultimate instruction
// the calling pass is trying to simplify) here, even though the result of
// this function is generally cached when called from the solve* functions
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Analysis/ValueLattice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ raw_ostream &operator<<(raw_ostream &OS, const ValueLatticeElement &Val) {
return OS << "undef";
if (Val.isOverdefined())
return OS << "overdefined";
if (Val.isSpeculative())
return OS << "speculative";

if (Val.isNotConstant())
return OS << "notconstant<" << *Val.getNotConstant() << ">";
Expand Down
22 changes: 9 additions & 13 deletions llvm/test/Transforms/JumpThreading/ddt-crash.ll
Original file line number Diff line number Diff line change
Expand Up @@ -118,31 +118,27 @@ define void @spam(ptr %arg) {
; CHECK-NEXT: br i1 [[TMP24]], label [[BB37:%.*]], label [[BB25:%.*]]
; CHECK: bb25:
; CHECK-NEXT: [[TMP26:%.*]] = icmp eq ptr [[TMP15]], null
; CHECK-NEXT: br i1 [[TMP26]], label [[BB41_THREAD:%.*]], label [[BB27:%.*]]
; CHECK-NEXT: br i1 [[TMP26]], label [[BB41_THREAD11:%.*]], label [[BB27:%.*]]
; CHECK: bb27:
; CHECK-NEXT: [[TMP28:%.*]] = load ptr, ptr undef, align 8
; CHECK-NEXT: [[TMP29:%.*]] = icmp eq ptr [[TMP28]], [[TMP21]]
; CHECK-NEXT: br i1 [[TMP29]], label [[BB41_THREAD]], label [[BB30:%.*]]
; CHECK-NEXT: br i1 [[TMP29]], label [[BB41_THREAD11]], label [[BB30:%.*]]
; CHECK: bb30:
; CHECK-NEXT: [[TMP32_PR:%.*]] = load i8, ptr undef, align 8
; CHECK-NEXT: br label [[BB31:%.*]]
; CHECK: bb31:
; CHECK-NEXT: [[TMP32:%.*]] = phi i8 [ [[TMP32]], [[BB31]] ], [ [[TMP32_PR]], [[BB30]] ]
; CHECK-NEXT: [[TMP33:%.*]] = icmp eq i8 [[TMP32]], 0
; CHECK-NEXT: br i1 [[TMP33]], label [[BB31]], label [[BB37]]
; CHECK-NEXT: br i1 [[TMP33]], label [[BB31]], label [[BB41_THREAD11]]
; CHECK: bb37:
; CHECK-NEXT: [[TMP36:%.*]] = phi i1 [ false, [[BB23]] ], [ true, [[BB31]] ]
; CHECK-NEXT: [[TMP36:%.*]] = phi i1 [ false, [[BB23]] ]
; CHECK-NEXT: [[TMP38:%.*]] = icmp eq ptr [[TMP15]], null
; CHECK-NEXT: br i1 [[TMP38]], label [[BB39:%.*]], label [[BB41:%.*]]
; CHECK: bb39:
; CHECK-NEXT: [[TMP364:%.*]] = phi i1 [ [[TMP36]], [[BB37]] ]
; CHECK-NEXT: [[TMP40:%.*]] = load ptr, ptr @global, align 8
; CHECK-NEXT: br i1 [[TMP364]], label [[BB41_THREAD]], label [[BB41_THREAD]]
; CHECK-NEXT: br i1 [[TMP38]], label [[BB41:%.*]], label [[BB41_THREAD11]]
; CHECK: bb41:
; CHECK-NEXT: [[TMP363:%.*]] = phi i1 [ [[TMP36]], [[BB37]] ]
; CHECK-NEXT: br i1 [[TMP363]], label [[BB41_THREAD]], label [[BB41_THREAD]]
; CHECK: bb41.thread:
; CHECK-NEXT: [[TMP0:%.*]] = phi ptr [ undef, [[BB41]] ], [ undef, [[BB39]] ], [ undef, [[BB39]] ], [ undef, [[BB41]] ], [ undef, [[BB27]] ], [ undef, [[BB25]] ]
; CHECK-NEXT: [[TMP40:%.*]] = load ptr, ptr @global, align 8
; CHECK-NEXT: br label [[BB41_THREAD11]]
; CHECK: bb41.thread11:
; CHECK-NEXT: [[TMP0:%.*]] = phi ptr [ undef, [[BB41]] ], [ undef, [[BB25]] ], [ undef, [[BB31]] ], [ undef, [[BB27]] ], [ undef, [[BB37]] ]
; CHECK-NEXT: ret void
;
bb:
Expand Down
21 changes: 8 additions & 13 deletions llvm/test/Transforms/JumpThreading/loop-phi.ll
Original file line number Diff line number Diff line change
Expand Up @@ -9,29 +9,24 @@ define i32 @test(i1 %ARG1, i1 %ARG2, i32 %n) {
; CHECK-SAME: i1 [[ARG1:%.*]], i1 [[ARG2:%.*]], i32 [[N:%.*]]) {
; CHECK-NEXT: head1:
; CHECK-NEXT: br i1 [[ARG1]], label [[EXIT:%.*]], label [[BODY2:%.*]]
; CHECK: head1.thread:
; CHECK-NEXT: br i1 [[ARG1]], label [[EXIT]], label [[BODY2_THREAD9:%.*]]
; CHECK: body2.thread9:
; CHECK-NEXT: [[TMP1612:%.*]] = add i32 [[TMP165:%.*]], 1
; CHECK-NEXT: br label [[LATCH1:%.*]]
; CHECK: body1:
; CHECK-NEXT: [[TMP12:%.*]] = icmp sgt i32 [[TMP165]], 1
; CHECK-NEXT: br i1 [[TMP12]], label [[BODY2_THREAD:%.*]], label [[HEAD1_THREAD:%.*]]
; CHECK-NEXT: [[TMP12:%.*]] = icmp sgt i32 [[TMP168:%.*]], 1
; CHECK-NEXT: br i1 [[TMP12]], label [[BODY2_THREAD:%.*]], label [[BODY2_THREAD]]
; CHECK: body2.thread:
; CHECK-NEXT: [[TMP163:%.*]] = add i32 [[TMP165]], 1
; CHECK-NEXT: br label [[LATCH1]]
; CHECK-NEXT: [[TMP166:%.*]] = add i32 [[TMP168]], 1
; CHECK-NEXT: br label [[LATCH1:%.*]]
; CHECK: body2:
; CHECK-NEXT: [[TMP14:%.*]] = phi i32 [ 0, [[HEAD1:%.*]] ]
; CHECK-NEXT: [[TMP15:%.*]] = phi i32 [ 0, [[HEAD1]] ]
; CHECK-NEXT: [[TMP16:%.*]] = add i32 [[TMP14]], 1
; CHECK-NEXT: br i1 [[ARG2]], label [[EXIT]], label [[LATCH1]]
; CHECK: latch1:
; CHECK-NEXT: [[TMP165]] = phi i32 [ [[TMP163]], [[BODY2_THREAD]] ], [ [[TMP16]], [[BODY2]] ], [ [[TMP1612]], [[BODY2_THREAD9]] ]
; CHECK-NEXT: [[TMP154:%.*]] = phi i32 [ [[TMP165]], [[BODY2_THREAD]] ], [ [[TMP15]], [[BODY2]] ], [ [[TMP165]], [[BODY2_THREAD9]] ]
; CHECK-NEXT: [[TMP18:%.*]] = icmp sgt i32 [[TMP165]], [[N]]
; CHECK-NEXT: [[TMP168]] = phi i32 [ [[TMP166]], [[BODY2_THREAD]] ], [ [[TMP16]], [[BODY2]] ]
; CHECK-NEXT: [[TMP157:%.*]] = phi i32 [ [[TMP168]], [[BODY2_THREAD]] ], [ [[TMP15]], [[BODY2]] ]
; CHECK-NEXT: [[TMP18:%.*]] = icmp sgt i32 [[TMP168]], [[N]]
; CHECK-NEXT: br i1 [[TMP18]], label [[EXIT]], label [[BODY1:%.*]]
; CHECK: exit:
; CHECK-NEXT: [[RC:%.*]] = phi i32 [ [[TMP15]], [[BODY2]] ], [ [[TMP154]], [[LATCH1]] ], [ -1, [[HEAD1]] ], [ -1, [[HEAD1_THREAD]] ]
; CHECK-NEXT: [[RC:%.*]] = phi i32 [ [[TMP15]], [[BODY2]] ], [ [[TMP157]], [[LATCH1]] ], [ -1, [[HEAD1]] ]
; CHECK-NEXT: ret i32 [[RC]]
;
entry:
Expand Down
50 changes: 41 additions & 9 deletions llvm/test/Transforms/JumpThreading/pr63013.ll
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,52 @@ define void @test(i16 %arg) {
; CHECK-LABEL: define void @test
; CHECK-SAME: (i16 [[ARG:%.*]]) {
; CHECK-NEXT: start:
; CHECK-NEXT: br label [[BB8THREAD_PRE_SPLIT1:%.*]]
; CHECK: bb8thread-pre-split1:
; CHECK-NEXT: [[LOAD_PR_PR:%.*]] = load i16, ptr null, align 2
; CHECK-NEXT: br label [[BB8:%.*]]
; CHECK-NEXT: br label [[BB5:%.*]]
; CHECK: bb20:
; CHECK-NEXT: ret void
; CHECK: bb5:
; CHECK-NEXT: [[_11_0:%.*]] = phi ptr [ [[_11_5:%.*]], [[BB16:%.*]] ], [ null, [[BB10:%.*]] ], [ null, [[BB8:%.*]] ], [ null, [[BB10]] ], [ null, [[START:%.*]] ]
; CHECK-NEXT: br label [[BB8]]
; CHECK: bb8:
; CHECK-NEXT: [[LOAD_PR:%.*]] = phi i16 [ [[LOAD_PR_PR]], [[BB8THREAD_PRE_SPLIT1]] ], [ [[LOAD_PR]], [[BB8]] ]
; CHECK-NEXT: [[LOAD_PR:%.*]] = load i16, ptr null, align 2
; CHECK-NEXT: [[I:%.*]] = icmp eq i16 [[LOAD_PR]], 0
; CHECK-NEXT: br i1 [[I]], label [[BB10:%.*]], label [[BB8]]
; CHECK-NEXT: br i1 [[I]], label [[BB9:%.*]], label [[BB5]]
; CHECK: bb9:
; CHECK-NEXT: br label [[BB13:%.*]]
; CHECK: bb10:
; CHECK-NEXT: [[I1:%.*]] = getelementptr { i128, i8 }, ptr null, i64 0, i32 1
; CHECK-NEXT: [[_2_7:%.*]] = phi ptr [ [[_11_0]], [[BB14:%.*]] ], [ [[_11_0]], [[BB13]] ]
; CHECK-NEXT: [[I1:%.*]] = getelementptr { i128, i8 }, ptr [[_11_0]], i64 0, i32 1
; CHECK-NEXT: store i8 0, ptr [[I1]], align 8
; CHECK-NEXT: [[I2:%.*]] = load i128, ptr null, align 8
; CHECK-NEXT: [[I2:%.*]] = load i128, ptr [[_2_7]], align 8
; CHECK-NEXT: [[I3:%.*]] = icmp eq i128 [[I2]], 0
; CHECK-NEXT: br i1 [[I3]], label [[BB8THREAD_PRE_SPLIT1]], label [[BB8THREAD_PRE_SPLIT1]]
; CHECK-NEXT: br i1 [[I3]], label [[BB5]], label [[BB5]]
; CHECK: bb13:
; CHECK-NEXT: br label [[BB10]]
; CHECK: bb14:
; CHECK-NEXT: switch i16 [[ARG]], label [[BB20:%.*]] [
; CHECK-NEXT: i16 0, label [[BB13]]
; CHECK-NEXT: i16 2, label [[BB10]]
; CHECK-NEXT: i16 1, label [[BB15:%.*]]
; CHECK-NEXT: ]
; CHECK: bb15:
; CHECK-NEXT: switch i16 [[ARG]], label [[BB16]] [
; CHECK-NEXT: i16 1, label [[BB8]]
; CHECK-NEXT: i16 0, label [[BB17:%.*]]
; CHECK-NEXT: ]
; CHECK: bb16:
; CHECK-NEXT: [[_11_5]] = phi ptr [ null, [[BB15]] ], [ null, [[BB19:%.*]] ]
; CHECK-NEXT: br label [[BB5]]
; CHECK: bb17:
; CHECK-NEXT: switch i16 [[ARG]], label [[BB20]] [
; CHECK-NEXT: i16 0, label [[BB20]]
; CHECK-NEXT: i16 1, label [[BB19]]
; CHECK-NEXT: ]
; CHECK: bb19:
; CHECK-NEXT: switch i16 [[ARG]], label [[BB16]] [
; CHECK-NEXT: i16 0, label [[BB14]]
; CHECK-NEXT: i16 1, label [[BB20]]
; CHECK-NEXT: i16 6570, label [[BB17]]
; CHECK-NEXT: ]
;
start:
br label %bb5
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,32 +10,32 @@ define i1 @test_order_1(ptr %this, ptr noalias %other, i1 %tobool9.not, i32 %cal
; CHECK-NEXT: entry:
; CHECK-NEXT: br i1 [[TOBOOL9_NOT]], label [[EXIT:%.*]], label [[FOR_COND_PREHEADER:%.*]]
; CHECK: for.cond.preheader:
; CHECK-NEXT: [[CMP40_NOT3:%.*]] = icmp slt i32 [[CALL]], 1
; CHECK-NEXT: br i1 [[CMP40_NOT3]], label [[FOR_COND41_PREHEADER_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]]
; CHECK-NEXT: [[CMP40_NOT3:%.*]] = icmp sgt i32 [[CALL]], 0
; CHECK-NEXT: br i1 [[CMP40_NOT3]], label [[CLEANUP59:%.*]], label [[FOR_COND41_PREHEADER_PREHEADER:%.*]]
; CHECK: for.cond41.preheader.preheader:
; CHECK-NEXT: [[TMP0:%.*]] = sext i32 [[CALL]] to i64
; CHECK-NEXT: br label [[FOR_COND41_PREHEADER:%.*]]
; CHECK: for.cond:
; CHECK-NEXT: [[INDVARS_IV_NEXT:%.*]] = add nsw i64 [[INDVARS_IV:%.*]], 1
; CHECK-NEXT: [[TMP1:%.*]] = and i64 [[INDVARS_IV_NEXT]], 4294967295
; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[TMP1]], 1
; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_COND_CLEANUP]], label [[FOR_COND41_PREHEADER]]
; CHECK: for.cond41.preheader:
; CHECK-NEXT: [[INDVARS_IV]] = phi i64 [ [[TMP0]], [[FOR_COND41_PREHEADER_PREHEADER]] ], [ [[INDVARS_IV_NEXT]], [[FOR_COND:%.*]] ]
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[TMP0]], [[FOR_COND41_PREHEADER_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_INC57:%.*]] ]
; CHECK-NEXT: [[CALL431:%.*]] = load volatile i32, ptr [[OTHER]], align 4
; CHECK-NEXT: [[CMP442:%.*]] = icmp sgt i32 [[CALL431]], 0
; CHECK-NEXT: br i1 [[CMP442]], label [[FOR_BODY45_LR_PH:%.*]], label [[FOR_COND]]
; CHECK-NEXT: br i1 [[CMP442]], label [[FOR_BODY45_LR_PH:%.*]], label [[FOR_INC57]]
; CHECK: for.body45.lr.ph:
; CHECK-NEXT: [[ARRAYIDX_I_I:%.*]] = getelementptr ptr, ptr [[OTHER]], i64 [[INDVARS_IV]]
; CHECK-NEXT: br label [[FOR_BODY45:%.*]]
; CHECK: for.cond.cleanup:
; CHECK-NEXT: store i32 0, ptr [[THIS]], align 4
; CHECK-NEXT: br label [[EXIT]]
; CHECK: for.body45:
; CHECK-NEXT: [[CALL49:%.*]] = load volatile i1, ptr [[ARRAYIDX_I_I]], align 1
; CHECK-NEXT: [[CALL43:%.*]] = load volatile i32, ptr [[OTHER]], align 4
; CHECK-NEXT: [[CMP44:%.*]] = icmp sgt i32 [[CALL43]], 0
; CHECK-NEXT: br i1 [[CMP44]], label [[FOR_BODY45]], label [[FOR_COND]]
; CHECK-NEXT: br i1 [[CMP44]], label [[FOR_BODY45]], label [[FOR_INC57]]
; CHECK: for.inc57:
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
; CHECK-NEXT: [[TMP1:%.*]] = and i64 [[INDVARS_IV_NEXT]], 4294967295
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[TMP1]], 1
; CHECK-NEXT: br i1 [[EXITCOND]], label [[CLEANUP59]], label [[FOR_COND41_PREHEADER]]
; CHECK: cleanup59:
; CHECK-NEXT: store i32 0, ptr [[THIS]], align 4
; CHECK-NEXT: br label [[EXIT]]
; CHECK: exit:
; CHECK-NEXT: ret i1 false
;
Expand Down
Loading

0 comments on commit e484a38

Please sign in to comment.