@@ -1292,16 +1292,21 @@ bool IndVarSimplify::sinkUnusedInvariants(Loop *L) {
1292
1292
1293
1293
enum ExitCondAnalysisResult {
1294
1294
CanBeRemoved,
1295
+ CanBeReplacedWithInvariant,
1295
1296
CannotOptimize
1296
1297
};
1297
1298
1298
1299
// / If the condition of BI is trivially true during at least first MaxIter
1299
1300
// / 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.
1300
1304
// / 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) {
1305
1310
ICmpInst::Predicate Pred;
1306
1311
Value *LHS, *RHS;
1307
1312
using namespace PatternMatch ;
@@ -1330,9 +1335,6 @@ static ExitCondAnalysisResult analyzeCond(const Loop *L, BranchInst *BI,
1330
1335
if (ProvingLoopExit)
1331
1336
return CannotOptimize;
1332
1337
1333
- ICmpInst::Predicate InvariantPred;
1334
- const SCEV *InvariantLHS, *InvariantRHS;
1335
-
1336
1338
// Check if there is a loop-invariant predicate equivalent to our check.
1337
1339
if (!SE->isLoopInvariantExitCondDuringFirstIterations (
1338
1340
Pred, LHSS, RHSS, L, BI, MaxIter, InvariantPred, InvariantLHS,
@@ -1342,7 +1344,7 @@ static ExitCondAnalysisResult analyzeCond(const Loop *L, BranchInst *BI,
1342
1344
// Can we prove it to be trivially true?
1343
1345
if (SE->isKnownPredicateAt (InvariantPred, InvariantLHS, InvariantRHS, BI))
1344
1346
return CanBeRemoved;
1345
- return CannotOptimize ;
1347
+ return CanBeReplacedWithInvariant ;
1346
1348
}
1347
1349
1348
1350
bool IndVarSimplify::optimizeLoopExits (Loop *L, SCEVExpander &Rewriter) {
@@ -1420,6 +1422,19 @@ bool IndVarSimplify::optimizeLoopExits(Loop *L, SCEVExpander &Rewriter) {
1420
1422
ReplaceExitCond (BI, NewCond);
1421
1423
};
1422
1424
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
+
1423
1438
bool Changed = false ;
1424
1439
bool SkipLastIter = false ;
1425
1440
SmallSet<const SCEV*, 8 > DominatingExitCounts;
@@ -1429,17 +1444,26 @@ bool IndVarSimplify::optimizeLoopExits(Loop *L, SCEVExpander &Rewriter) {
1429
1444
// Okay, we do not know the exit count here. Can we at least prove that it
1430
1445
// will remain the same within iteration space?
1431
1446
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) {
1434
1450
const SCEV *MaxIter = MaxExitCount;
1435
1451
if (SkipLastIter) {
1436
1452
const SCEV *One = SE->getOne (MaxIter->getType ());
1437
1453
MaxIter = SE->getMinusSCEV (MaxIter, One);
1438
1454
}
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)) {
1440
1459
case CanBeRemoved:
1441
1460
FoldExit (ExitingBB, Inverted);
1442
1461
return true ;
1462
+ case CanBeReplacedWithInvariant: {
1463
+ ReplaceWithInvariantCond (ExitingBB, InvariantPred, InvariantLHS,
1464
+ InvariantRHS);
1465
+ return true ;
1466
+ }
1443
1467
case CannotOptimize:
1444
1468
return false ;
1445
1469
}
0 commit comments