Skip to content

Commit 77efb73

Browse files
committed
[IndVars] Replace checks with invariants if we cannot remove them
If we cannot prove that the check is trivially true, but can prove that it either fails on the 1st iteration or never fails, we can replace it with first iteration check. Differential Revision: https://reviews.llvm.org/D88527 Reviewed By: skatkov
1 parent 7602ef7 commit 77efb73

File tree

2 files changed

+38
-13
lines changed

2 files changed

+38
-13
lines changed

llvm/lib/Transforms/Scalar/IndVarSimplify.cpp

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1292,16 +1292,21 @@ bool IndVarSimplify::sinkUnusedInvariants(Loop *L) {
12921292

12931293
enum ExitCondAnalysisResult {
12941294
CanBeRemoved,
1295+
CanBeReplacedWithInvariant,
12951296
CannotOptimize
12961297
};
12971298

12981299
/// If the condition of BI is trivially true during at least first MaxIter
12991300
/// iterations, return CanBeRemoved.
1301+
/// If the condition is equivalent to loop-invariant condition expressed as
1302+
/// 'InvariantLHS `InvariantPred` InvariantRHS', fill them into respective
1303+
/// output parameters and return CanBeReplacedWithInvariant.
13001304
/// Otherwise, return CannotOptimize.
1301-
static ExitCondAnalysisResult analyzeCond(const Loop *L, BranchInst *BI,
1302-
ScalarEvolution *SE,
1303-
bool ProvingLoopExit,
1304-
const SCEV *MaxIter) {
1305+
static ExitCondAnalysisResult
1306+
analyzeCond(const Loop *L, BranchInst *BI, ScalarEvolution *SE,
1307+
bool ProvingLoopExit, const SCEV *MaxIter,
1308+
ICmpInst::Predicate &InvariantPred, const SCEV *&InvariantLHS,
1309+
const SCEV *&InvariantRHS) {
13051310
ICmpInst::Predicate Pred;
13061311
Value *LHS, *RHS;
13071312
using namespace PatternMatch;
@@ -1330,9 +1335,6 @@ static ExitCondAnalysisResult analyzeCond(const Loop *L, BranchInst *BI,
13301335
if (ProvingLoopExit)
13311336
return CannotOptimize;
13321337

1333-
ICmpInst::Predicate InvariantPred;
1334-
const SCEV *InvariantLHS, *InvariantRHS;
1335-
13361338
// Check if there is a loop-invariant predicate equivalent to our check.
13371339
if (!SE->isLoopInvariantExitCondDuringFirstIterations(
13381340
Pred, LHSS, RHSS, L, BI, MaxIter, InvariantPred, InvariantLHS,
@@ -1342,7 +1344,7 @@ static ExitCondAnalysisResult analyzeCond(const Loop *L, BranchInst *BI,
13421344
// Can we prove it to be trivially true?
13431345
if (SE->isKnownPredicateAt(InvariantPred, InvariantLHS, InvariantRHS, BI))
13441346
return CanBeRemoved;
1345-
return CannotOptimize;
1347+
return CanBeReplacedWithInvariant;
13461348
}
13471349

13481350
bool IndVarSimplify::optimizeLoopExits(Loop *L, SCEVExpander &Rewriter) {
@@ -1420,6 +1422,19 @@ bool IndVarSimplify::optimizeLoopExits(Loop *L, SCEVExpander &Rewriter) {
14201422
ReplaceExitCond(BI, NewCond);
14211423
};
14221424

1425+
auto ReplaceWithInvariantCond = [&](
1426+
BasicBlock *ExitingBB, ICmpInst::Predicate InvariantPred,
1427+
const SCEV *InvariantLHS, const SCEV *InvariantRHS) {
1428+
BranchInst *BI = cast<BranchInst>(ExitingBB->getTerminator());
1429+
Rewriter.setInsertPoint(BI);
1430+
auto *LHSV = Rewriter.expandCodeFor(InvariantLHS);
1431+
auto *RHSV = Rewriter.expandCodeFor(InvariantRHS);
1432+
IRBuilder<> Builder(BI);
1433+
auto *NewCond = Builder.CreateICmp(InvariantPred, LHSV, RHSV,
1434+
BI->getCondition()->getName());
1435+
ReplaceExitCond(BI, NewCond);
1436+
};
1437+
14231438
bool Changed = false;
14241439
bool SkipLastIter = false;
14251440
SmallSet<const SCEV*, 8> DominatingExitCounts;
@@ -1429,17 +1444,26 @@ bool IndVarSimplify::optimizeLoopExits(Loop *L, SCEVExpander &Rewriter) {
14291444
// Okay, we do not know the exit count here. Can we at least prove that it
14301445
// will remain the same within iteration space?
14311446
auto *BI = cast<BranchInst>(ExitingBB->getTerminator());
1432-
auto OptimizeCond = [this, L, BI, ExitingBB, MaxExitCount, &FoldExit](
1433-
bool Inverted, bool SkipLastIter) {
1447+
auto OptimizeCond = [this, L, BI, ExitingBB, MaxExitCount, &FoldExit,
1448+
&ReplaceWithInvariantCond](bool Inverted,
1449+
bool SkipLastIter) {
14341450
const SCEV *MaxIter = MaxExitCount;
14351451
if (SkipLastIter) {
14361452
const SCEV *One = SE->getOne(MaxIter->getType());
14371453
MaxIter = SE->getMinusSCEV(MaxIter, One);
14381454
}
1439-
switch (analyzeCond(L, BI, SE, Inverted, MaxIter)) {
1455+
ICmpInst::Predicate InvariantPred;
1456+
const SCEV *InvariantLHS, *InvariantRHS;
1457+
switch (analyzeCond(L, BI, SE, Inverted, MaxIter, InvariantPred,
1458+
InvariantLHS, InvariantRHS)) {
14401459
case CanBeRemoved:
14411460
FoldExit(ExitingBB, Inverted);
14421461
return true;
1462+
case CanBeReplacedWithInvariant: {
1463+
ReplaceWithInvariantCond(ExitingBB, InvariantPred, InvariantLHS,
1464+
InvariantRHS);
1465+
return true;
1466+
}
14431467
case CannotOptimize:
14441468
return false;
14451469
}

llvm/test/Transforms/IndVarSimplify/predicated_ranges.ll

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -470,15 +470,16 @@ define void @test_can_predicate_simple_unsigned(i32* %p, i32* %arr) {
470470
; CHECK-LABEL: @test_can_predicate_simple_unsigned(
471471
; CHECK-NEXT: preheader:
472472
; CHECK-NEXT: [[LEN:%.*]] = load i32, i32* [[P:%.*]], align 4
473+
; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[LEN]], -1
473474
; CHECK-NEXT: br label [[LOOP:%.*]]
474475
; CHECK: loop:
475476
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[LEN]], [[PREHEADER:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
476477
; CHECK-NEXT: [[ZERO_COND:%.*]] = icmp eq i32 [[IV]], 0
477478
; CHECK-NEXT: br i1 [[ZERO_COND]], label [[EXIT:%.*]], label [[RANGE_CHECK_BLOCK:%.*]]
478479
; CHECK: range_check_block:
479480
; CHECK-NEXT: [[IV_NEXT]] = sub i32 [[IV]], 1
480-
; CHECK-NEXT: [[RANGE_CHECK:%.*]] = icmp ult i32 [[IV_NEXT]], [[LEN]]
481-
; CHECK-NEXT: br i1 [[RANGE_CHECK]], label [[BACKEDGE]], label [[FAIL:%.*]]
481+
; CHECK-NEXT: [[RANGE_CHECK1:%.*]] = icmp ult i32 [[TMP0]], [[LEN]]
482+
; CHECK-NEXT: br i1 [[RANGE_CHECK1]], label [[BACKEDGE]], label [[FAIL:%.*]]
482483
; CHECK: backedge:
483484
; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, i32* [[P]], i32 [[IV]]
484485
; CHECK-NEXT: [[EL:%.*]] = load i32, i32* [[EL_PTR]], align 4

0 commit comments

Comments
 (0)