@@ -105,8 +105,8 @@ static cl::opt<bool> PrintRangeChecks("irce-print-range-checks", cl::Hidden,
105
105
static cl::opt<bool > SkipProfitabilityChecks (" irce-skip-profitability-checks" ,
106
106
cl::Hidden, cl::init(false ));
107
107
108
- static cl::opt<unsigned > MinRuntimeIterations (" irce-min-runtime-iterations " ,
109
- cl::Hidden, cl::init(10 ));
108
+ static cl::opt<unsigned > MinEliminatedChecks (" irce-min-eliminated-checks " ,
109
+ cl::Hidden, cl::init(10 ));
110
110
111
111
static cl::opt<bool > AllowUnsignedLatchCondition (" irce-allow-unsigned-latch" ,
112
112
cl::Hidden, cl::init(true ));
@@ -130,15 +130,9 @@ static cl::opt<bool>
130
130
131
131
namespace {
132
132
133
- // / An inductive range check is conditional branch in a loop with
134
- // /
135
- // / 1. a very cold successor (i.e. the branch jumps to that successor very
136
- // / rarely)
137
- // /
138
- // / and
139
- // /
140
- // / 2. a condition that is provably true for some contiguous range of values
141
- // / taken by the containing loop's induction variable.
133
+ // / An inductive range check is conditional branch in a loop with a condition
134
+ // / that is provably true for some contiguous range of values taken by the
135
+ // / containing loop's induction variable.
142
136
// /
143
137
class InductiveRangeCheck {
144
138
@@ -233,6 +227,7 @@ class InductiveRangeCheck {
233
227
// / checks, and hence don't end up in \p Checks.
234
228
static void extractRangeChecksFromBranch (
235
229
BranchInst *BI, Loop *L, ScalarEvolution &SE, BranchProbabilityInfo *BPI,
230
+ std::optional<uint64_t > EstimatedTripCount,
236
231
SmallVectorImpl<InductiveRangeCheck> &Checks, bool &Changed);
237
232
};
238
233
@@ -246,9 +241,10 @@ class InductiveRangeCheckElimination {
246
241
std::optional<llvm::function_ref<llvm::BlockFrequencyInfo &()>>;
247
242
GetBFIFunc GetBFI;
248
243
249
- // Returns true if it is profitable to do a transform basing on estimation of
250
- // number of iterations.
251
- bool isProfitableToTransform (const Loop &L);
244
+ // Returns the estimated number of iterations based on block frequency info if
245
+ // available, or on branch probability info. Nullopt is returned if the number
246
+ // of iterations cannot be estimated.
247
+ std::optional<uint64_t > estimatedTripCount (const Loop &L);
252
248
253
249
public:
254
250
InductiveRangeCheckElimination (ScalarEvolution &SE,
@@ -522,18 +518,40 @@ void InductiveRangeCheck::extractRangeChecksFromCond(
522
518
523
519
void InductiveRangeCheck::extractRangeChecksFromBranch (
524
520
BranchInst *BI, Loop *L, ScalarEvolution &SE, BranchProbabilityInfo *BPI,
521
+ std::optional<uint64_t > EstimatedTripCount,
525
522
SmallVectorImpl<InductiveRangeCheck> &Checks, bool &Changed) {
526
523
if (BI->isUnconditional () || BI->getParent () == L->getLoopLatch ())
527
524
return ;
528
525
529
526
unsigned IndexLoopSucc = L->contains (BI->getSuccessor (0 )) ? 0 : 1 ;
530
527
assert (L->contains (BI->getSuccessor (IndexLoopSucc)) &&
531
528
" No edges coming to loop?" );
532
- BranchProbability LikelyTaken (15 , 16 );
533
529
534
- if (!SkipProfitabilityChecks && BPI &&
535
- BPI->getEdgeProbability (BI->getParent (), IndexLoopSucc) < LikelyTaken)
536
- return ;
530
+ if (!SkipProfitabilityChecks && BPI) {
531
+ auto SuccessProbability =
532
+ BPI->getEdgeProbability (BI->getParent (), IndexLoopSucc);
533
+ if (EstimatedTripCount) {
534
+ auto EstimatedEliminatedChecks =
535
+ SuccessProbability.scale (*EstimatedTripCount);
536
+ if (EstimatedEliminatedChecks < MinEliminatedChecks) {
537
+ LLVM_DEBUG (dbgs () << " irce: could not prove profitability for branch "
538
+ << *BI << " : "
539
+ << " estimated eliminated checks too low "
540
+ << EstimatedEliminatedChecks << " \n " ;);
541
+ return ;
542
+ }
543
+ } else {
544
+ BranchProbability LikelyTaken (15 , 16 );
545
+ if (SuccessProbability < LikelyTaken) {
546
+ LLVM_DEBUG (dbgs () << " irce: could not prove profitability for branch "
547
+ << *BI << " : "
548
+ << " could not estimate trip count "
549
+ << " and branch success probability too low "
550
+ << SuccessProbability << " \n " ;);
551
+ return ;
552
+ }
553
+ }
554
+ }
537
555
538
556
// IRCE expects branch's true edge comes to loop. Invert branch for opposite
539
557
// case.
@@ -938,42 +956,34 @@ PreservedAnalyses IRCEPass::run(Function &F, FunctionAnalysisManager &AM) {
938
956
return getLoopPassPreservedAnalyses ();
939
957
}
940
958
941
- bool InductiveRangeCheckElimination::isProfitableToTransform (const Loop &L) {
942
- if (SkipProfitabilityChecks)
943
- return true ;
959
+ std::optional<uint64_t >
960
+ InductiveRangeCheckElimination::estimatedTripCount (const Loop &L) {
944
961
if (GetBFI) {
945
962
BlockFrequencyInfo &BFI = (*GetBFI)();
946
963
uint64_t hFreq = BFI.getBlockFreq (L.getHeader ()).getFrequency ();
947
964
uint64_t phFreq = BFI.getBlockFreq (L.getLoopPreheader ()).getFrequency ();
948
- if (phFreq != 0 && hFreq != 0 && (hFreq / phFreq < MinRuntimeIterations)) {
949
- LLVM_DEBUG (dbgs () << " irce: could not prove profitability: "
950
- << " the estimated number of iterations basing on "
951
- " frequency info is " << (hFreq / phFreq) << " \n " ;);
952
- return false ;
953
- }
954
- return true ;
965
+ if (phFreq == 0 || hFreq == 0 )
966
+ return std::nullopt;
967
+ return {hFreq / phFreq};
955
968
}
956
969
957
970
if (!BPI)
958
- return true ;
971
+ return std::nullopt ;
959
972
960
973
auto *Latch = L.getLoopLatch ();
961
974
if (!Latch)
962
- return true ;
975
+ return std::nullopt ;
963
976
auto *LatchBr = dyn_cast<BranchInst>(Latch->getTerminator ());
964
977
if (!LatchBr)
965
- return true ;
966
- auto LatchBrExitIdx = LatchBr->getSuccessor (0 ) == L.getHeader () ? 1 : 0 ;
978
+ return std::nullopt;
967
979
980
+ auto LatchBrExitIdx = LatchBr->getSuccessor (0 ) == L.getHeader () ? 1 : 0 ;
968
981
BranchProbability ExitProbability =
969
982
BPI->getEdgeProbability (Latch, LatchBrExitIdx);
970
- if (ExitProbability > BranchProbability (1 , MinRuntimeIterations)) {
971
- LLVM_DEBUG (dbgs () << " irce: could not prove profitability: "
972
- << " the exit probability is too big " << ExitProbability
973
- << " \n " ;);
974
- return false ;
975
- }
976
- return true ;
983
+ if (ExitProbability.isUnknown () || ExitProbability.isZero ())
984
+ return std::nullopt;
985
+
986
+ return {ExitProbability.scaleByInverse (1 )};
977
987
}
978
988
979
989
bool InductiveRangeCheckElimination::run (
@@ -989,17 +999,23 @@ bool InductiveRangeCheckElimination::run(
989
999
return false ;
990
1000
}
991
1001
992
- if (!isProfitableToTransform (*L))
1002
+ auto EstimatedTripCount = estimatedTripCount (*L);
1003
+ if (!SkipProfitabilityChecks && EstimatedTripCount &&
1004
+ *EstimatedTripCount < MinEliminatedChecks) {
1005
+ LLVM_DEBUG (dbgs () << " irce: could not prove profitability: "
1006
+ << " the estimated number of iterations is "
1007
+ << *EstimatedTripCount << " \n " );
993
1008
return false ;
1009
+ }
994
1010
995
1011
LLVMContext &Context = Preheader->getContext ();
996
1012
SmallVector<InductiveRangeCheck, 16 > RangeChecks;
997
1013
bool Changed = false ;
998
1014
999
1015
for (auto *BBI : L->getBlocks ())
1000
1016
if (BranchInst *TBI = dyn_cast<BranchInst>(BBI->getTerminator ()))
1001
- InductiveRangeCheck::extractRangeChecksFromBranch (TBI, L, SE, BPI,
1002
- RangeChecks, Changed);
1017
+ InductiveRangeCheck::extractRangeChecksFromBranch (
1018
+ TBI, L, SE, BPI, EstimatedTripCount, RangeChecks, Changed);
1003
1019
1004
1020
if (RangeChecks.empty ())
1005
1021
return Changed;
0 commit comments