Skip to content

Commit be27399

Browse files
committed
Remove value cache in SCEV comparator.
The cache triggers almost never. When it does, it is likely to cause the comparator to become inconsistent due to a bad interaction of the depth limit and cache hits. This leads to crashes in debug builds.
1 parent 6f83a03 commit be27399

File tree

2 files changed

+46
-17
lines changed

2 files changed

+46
-17
lines changed

llvm/lib/Analysis/ScalarEvolution.cpp

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -597,11 +597,9 @@ void SCEVUnknown::allUsesReplacedWith(Value *New) {
597597
///
598598
/// Since we do not continue running this routine on expression trees once we
599599
/// have seen unequal values, there is no need to track them in the cache.
600-
static int
601-
CompareValueComplexity(EquivalenceClasses<const Value *> &EqCacheValue,
602-
const LoopInfo *const LI, Value *LV, Value *RV,
603-
unsigned Depth) {
604-
if (Depth > MaxValueCompareDepth || EqCacheValue.isEquivalent(LV, RV))
600+
static int CompareValueComplexity(const LoopInfo *const LI, Value *LV,
601+
Value *RV, unsigned Depth) {
602+
if (Depth > MaxValueCompareDepth)
605603
return 0;
606604

607605
// Order pointer values after integer values. This helps SCEVExpander form
@@ -660,15 +658,13 @@ CompareValueComplexity(EquivalenceClasses<const Value *> &EqCacheValue,
660658
return (int)LNumOps - (int)RNumOps;
661659

662660
for (unsigned Idx : seq(LNumOps)) {
663-
int Result =
664-
CompareValueComplexity(EqCacheValue, LI, LInst->getOperand(Idx),
665-
RInst->getOperand(Idx), Depth + 1);
661+
int Result = CompareValueComplexity(LI, LInst->getOperand(Idx),
662+
RInst->getOperand(Idx), Depth + 1);
666663
if (Result != 0)
667664
return Result;
668665
}
669666
}
670667

671-
EqCacheValue.unionSets(LV, RV);
672668
return 0;
673669
}
674670

@@ -679,7 +675,6 @@ CompareValueComplexity(EquivalenceClasses<const Value *> &EqCacheValue,
679675
// not know if they are equivalent for sure.
680676
static std::optional<int>
681677
CompareSCEVComplexity(EquivalenceClasses<const SCEV *> &EqCacheSCEV,
682-
EquivalenceClasses<const Value *> &EqCacheValue,
683678
const LoopInfo *const LI, const SCEV *LHS,
684679
const SCEV *RHS, DominatorTree &DT, unsigned Depth = 0) {
685680
// Fast-path: SCEVs are uniqued so we can do a quick equality check.
@@ -705,8 +700,8 @@ CompareSCEVComplexity(EquivalenceClasses<const SCEV *> &EqCacheSCEV,
705700
const SCEVUnknown *LU = cast<SCEVUnknown>(LHS);
706701
const SCEVUnknown *RU = cast<SCEVUnknown>(RHS);
707702

708-
int X = CompareValueComplexity(EqCacheValue, LI, LU->getValue(),
709-
RU->getValue(), Depth + 1);
703+
int X =
704+
CompareValueComplexity(LI, LU->getValue(), RU->getValue(), Depth + 1);
710705
if (X == 0)
711706
EqCacheSCEV.unionSets(LHS, RHS);
712707
return X;
@@ -773,8 +768,8 @@ CompareSCEVComplexity(EquivalenceClasses<const SCEV *> &EqCacheSCEV,
773768
return (int)LNumOps - (int)RNumOps;
774769

775770
for (unsigned i = 0; i != LNumOps; ++i) {
776-
auto X = CompareSCEVComplexity(EqCacheSCEV, EqCacheValue, LI, LOps[i],
777-
ROps[i], DT, Depth + 1);
771+
auto X = CompareSCEVComplexity(EqCacheSCEV, LI, LOps[i], ROps[i], DT,
772+
Depth + 1);
778773
if (X != 0)
779774
return X;
780775
}
@@ -802,12 +797,10 @@ static void GroupByComplexity(SmallVectorImpl<const SCEV *> &Ops,
802797
if (Ops.size() < 2) return; // Noop
803798

804799
EquivalenceClasses<const SCEV *> EqCacheSCEV;
805-
EquivalenceClasses<const Value *> EqCacheValue;
806800

807801
// Whether LHS has provably less complexity than RHS.
808802
auto IsLessComplex = [&](const SCEV *LHS, const SCEV *RHS) {
809-
auto Complexity =
810-
CompareSCEVComplexity(EqCacheSCEV, EqCacheValue, LI, LHS, RHS, DT);
803+
auto Complexity = CompareSCEVComplexity(EqCacheSCEV, LI, LHS, RHS, DT);
811804
return Complexity && *Complexity < 0;
812805
};
813806
if (Ops.size() == 2) {

llvm/unittests/Analysis/ScalarEvolutionTest.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1625,4 +1625,40 @@ TEST_F(ScalarEvolutionsTest, ForgetValueWithOverflowInst) {
16251625
});
16261626
}
16271627

1628+
EST_F(ScalarEvolutionsTest, ComplexityComparatorIsStrictWeakOrdering) {
1629+
// Regression test for a case where caching of equivalent values caused the
1630+
// comparator to get inconsistent.
1631+
LLVMContext C;
1632+
SMDiagnostic Err;
1633+
std::unique_ptr<Module> M = parseAssemblyString(R"(
1634+
define i32 @foo(i32 %arg0) {
1635+
%1 = add i32 %arg0, 1
1636+
%2 = add i32 %arg0, 1
1637+
%3 = xor i32 %2, %1
1638+
%4 = add i32 %3, %2
1639+
%5 = add i32 %arg0, 1
1640+
%6 = xor i32 %5, %arg0
1641+
%7 = add i32 %arg0, %6
1642+
%8 = add i32 %5, %7
1643+
%9 = xor i32 %8, %7
1644+
%10 = add i32 %9, %8
1645+
%11 = xor i32 %10, %9
1646+
%12 = add i32 %11, %10
1647+
%13 = xor i32 %12, %11
1648+
%14 = add i32 %12, %13
1649+
%15 = add i32 %14, %4
1650+
ret i32 %15
1651+
})",
1652+
Err, C);
1653+
1654+
ASSERT_TRUE(M && "Could not parse module?");
1655+
ASSERT_TRUE(!verifyModule(*M) && "Must have been well formed!");
1656+
1657+
runWithSE(*M, "foo", [](Function &F, LoopInfo &LI, ScalarEvolution &SE) {
1658+
// When _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_DEBUG, this will
1659+
// crash if the comparator has the specific caching bug.
1660+
SE.getSCEV(F.getEntryBlock().getTerminator()->getOperand(0));
1661+
});
1662+
}
1663+
16281664
} // end namespace llvm

0 commit comments

Comments
 (0)