Skip to content

Commit 74d6ce5

Browse files
committed
[ScalarEvolution] Make getMinusSCEV() fail for unrelated pointers.
As part of making ScalarEvolution's handling of pointers consistent, we want to forbid multiplying a pointer by -1 (or any other value). This means we can't blindly subtract pointers. There are a few ways we could deal with this: 1. We could completely forbid subtracting pointers in getMinusSCEV() 2. We could forbid subracting pointers with different pointer bases (this patch). 3. We could try to ptrtoint pointer operands. The option in this patch is more friendly to non-integral pointers: code that works with normal pointers will also work with non-integral pointers. And it seems like there are very few places that actually benefit from the third option. As a minimal patch, the ScalarEvolution implementation of getMinusSCEV still ends up subtracting pointers if they have the same base. This should eliminate the shared pointer base, but eventually we'll need to rewrite it to avoid negating the pointer base. I plan to do this as a separate step to allow measuring the compile-time impact. This doesn't cause obvious functional changes in most cases; the one case that is significantly affected is ICmpZero handling in LSR (which is the source of almost all the test changes). The resulting changes seem okay to me, but suggestions welcome. As an alternative, I tried explicitly ptrtoint'ing the operands, but the result doesn't seem obviously better. I deleted the test lsr-undef-in-binop.ll becuase I couldn't figure out how to repair it to test what it was actually trying to test. Differential Revision: https://reviews.llvm.org/D104806
1 parent 458eac2 commit 74d6ce5

20 files changed

+121
-362
lines changed

llvm/include/llvm/Analysis/ScalarEvolution.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -633,6 +633,12 @@ class ScalarEvolution {
633633
const SCEV *getNotSCEV(const SCEV *V);
634634

635635
/// Return LHS-RHS. Minus is represented in SCEV as A+B*-1.
636+
///
637+
/// If the LHS and RHS are pointers which don't share a common base
638+
/// (according to getPointerBase()), this returns a SCEVCouldNotCompute.
639+
/// To compute the difference between two unrelated pointers, you can
640+
/// explicitly convert the arguments using getPtrToIntExpr(), for pointer
641+
/// types that support it.
636642
const SCEV *getMinusSCEV(const SCEV *LHS, const SCEV *RHS,
637643
SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap,
638644
unsigned Depth = 0);

llvm/lib/Analysis/ScalarEvolution.cpp

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4138,6 +4138,15 @@ const SCEV *ScalarEvolution::getMinusSCEV(const SCEV *LHS, const SCEV *RHS,
41384138
if (LHS == RHS)
41394139
return getZero(LHS->getType());
41404140

4141+
// If we subtract two pointers with different pointer bases, bail.
4142+
// Eventually, we're going to add an assertion to getMulExpr that we
4143+
// can't multiply by a pointer.
4144+
if (RHS->getType()->isPointerTy()) {
4145+
if (!LHS->getType()->isPointerTy() ||
4146+
getPointerBase(LHS) != getPointerBase(RHS))
4147+
return getCouldNotCompute();
4148+
}
4149+
41414150
// We represent LHS - RHS as LHS + (-1)*RHS. This transformation
41424151
// makes it so that we cannot make much use of NUW.
41434152
auto AddFlags = SCEV::FlagAnyWrap;
@@ -8029,6 +8038,16 @@ ScalarEvolution::computeExitLimitFromICmp(const Loop *L,
80298038
}
80308039
case ICmpInst::ICMP_EQ: { // while (X == Y)
80318040
// Convert to: while (X-Y == 0)
8041+
if (LHS->getType()->isPointerTy()) {
8042+
LHS = getLosslessPtrToIntExpr(LHS);
8043+
if (isa<SCEVCouldNotCompute>(LHS))
8044+
return LHS;
8045+
}
8046+
if (RHS->getType()->isPointerTy()) {
8047+
RHS = getLosslessPtrToIntExpr(RHS);
8048+
if (isa<SCEVCouldNotCompute>(RHS))
8049+
return RHS;
8050+
}
80328051
ExitLimit EL = howFarToNonZero(getMinusSCEV(LHS, RHS), L);
80338052
if (EL.hasAnyInfo()) return EL;
80348053
break;
@@ -10066,10 +10085,13 @@ bool ScalarEvolution::isKnownPredicateViaConstantRanges(
1006610085
if (Pred == CmpInst::ICMP_EQ)
1006710086
return false;
1006810087

10069-
if (Pred == CmpInst::ICMP_NE)
10070-
return CheckRanges(getSignedRange(LHS), getSignedRange(RHS)) ||
10071-
CheckRanges(getUnsignedRange(LHS), getUnsignedRange(RHS)) ||
10072-
isKnownNonZero(getMinusSCEV(LHS, RHS));
10088+
if (Pred == CmpInst::ICMP_NE) {
10089+
if (CheckRanges(getSignedRange(LHS), getSignedRange(RHS)) ||
10090+
CheckRanges(getUnsignedRange(LHS), getUnsignedRange(RHS)))
10091+
return true;
10092+
auto *Diff = getMinusSCEV(LHS, RHS);
10093+
return !isa<SCEVCouldNotCompute>(Diff) && isKnownNonZero(Diff);
10094+
}
1007310095

1007410096
if (CmpInst::isSigned(Pred))
1007510097
return CheckRanges(getSignedRange(LHS), getSignedRange(RHS));
@@ -10590,6 +10612,10 @@ bool ScalarEvolution::isImpliedCondBalancedTypes(
1059010612
if (!isa<SCEVConstant>(FoundRHS) && !isa<SCEVAddRecExpr>(FoundLHS))
1059110613
return isImpliedCondOperands(Pred, LHS, RHS, FoundRHS, FoundLHS, Context);
1059210614

10615+
// Don't try to getNotSCEV pointers.
10616+
if (LHS->getType()->isPointerTy() || FoundLHS->getType()->isPointerTy())
10617+
return false;
10618+
1059310619
// There's no clear preference between forms 3. and 4., try both.
1059410620
return isImpliedCondOperands(FoundPred, getNotSCEV(LHS), getNotSCEV(RHS),
1059510621
FoundLHS, FoundRHS, Context) ||

llvm/lib/Analysis/ScalarEvolutionAliasAnalysis.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@ AliasResult SCEVAAResult::alias(const MemoryLocation &LocA,
5757
// Test whether the difference is known to be great enough that memory of
5858
// the given sizes don't overlap. This assumes that ASizeInt and BSizeInt
5959
// are non-zero, which is special-cased above.
60-
if (ASizeInt.ule(SE.getUnsignedRange(BA).getUnsignedMin()) &&
60+
if (!isa<SCEVCouldNotCompute>(BA) &&
61+
ASizeInt.ule(SE.getUnsignedRange(BA).getUnsignedMin()) &&
6162
(-BSizeInt).uge(SE.getUnsignedRange(BA).getUnsignedMax()))
6263
return AliasResult::NoAlias;
6364

@@ -71,7 +72,8 @@ AliasResult SCEVAAResult::alias(const MemoryLocation &LocA,
7172
// Test whether the difference is known to be great enough that memory of
7273
// the given sizes don't overlap. This assumes that ASizeInt and BSizeInt
7374
// are non-zero, which is special-cased above.
74-
if (BSizeInt.ule(SE.getUnsignedRange(AB).getUnsignedMin()) &&
75+
if (!isa<SCEVCouldNotCompute>(AB) &&
76+
BSizeInt.ule(SE.getUnsignedRange(AB).getUnsignedMin()) &&
7577
(-ASizeInt).uge(SE.getUnsignedRange(AB).getUnsignedMax()))
7678
return AliasResult::NoAlias;
7779
}

llvm/lib/Analysis/StackSafetyAnalysis.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,8 @@ ConstantRange StackSafetyLocalAnalysis::offsetFrom(Value *Addr, Value *Base) {
263263
const SCEV *AddrExp = SE.getTruncateOrZeroExtend(SE.getSCEV(Addr), PtrTy);
264264
const SCEV *BaseExp = SE.getTruncateOrZeroExtend(SE.getSCEV(Base), PtrTy);
265265
const SCEV *Diff = SE.getMinusSCEV(AddrExp, BaseExp);
266+
if (isa<SCEVCouldNotCompute>(Diff))
267+
return UnknownRange;
266268

267269
ConstantRange Offset = SE.getSignedRange(Diff);
268270
if (isUnsafe(Offset))

llvm/lib/Transforms/Scalar/AlignmentFromAssumptions.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,8 @@ static Align getNewAlignment(const SCEV *AASCEV, const SCEV *AlignSCEV,
135135
PtrSCEV = SE->getTruncateOrZeroExtend(
136136
PtrSCEV, SE->getEffectiveSCEVType(AASCEV->getType()));
137137
const SCEV *DiffSCEV = SE->getMinusSCEV(PtrSCEV, AASCEV);
138+
if (isa<SCEVCouldNotCompute>(DiffSCEV))
139+
return Align(1);
138140

139141
// On 32-bit platforms, DiffSCEV might now have type i32 -- we've always
140142
// sign-extended OffSCEV to i64, so make sure they agree again.

llvm/lib/Transforms/Scalar/LoopRerollPass.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -911,6 +911,8 @@ bool LoopReroll::DAGRootTracker::validateRootSet(DAGRootSet &DRS) {
911911
// Check that the first root is evenly spaced.
912912
unsigned N = DRS.Roots.size() + 1;
913913
const SCEV *StepSCEV = SE->getMinusSCEV(SE->getSCEV(DRS.Roots[0]), ADR);
914+
if (isa<SCEVCouldNotCompute>(StepSCEV))
915+
return false;
914916
const SCEV *ScaleSCEV = SE->getConstant(StepSCEV->getType(), N);
915917
if (ADR->getStepRecurrence(*SE) != SE->getMulExpr(StepSCEV, ScaleSCEV))
916918
return false;

llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2963,7 +2963,7 @@ void LSRInstance::ChainInstruction(Instruction *UserInst, Instruction *IVOper,
29632963
// The increment must be loop-invariant so it can be kept in a register.
29642964
const SCEV *PrevExpr = SE.getSCEV(PrevIV);
29652965
const SCEV *IncExpr = SE.getMinusSCEV(OperExpr, PrevExpr);
2966-
if (!SE.isLoopInvariant(IncExpr, L))
2966+
if (isa<SCEVCouldNotCompute>(IncExpr) || !SE.isLoopInvariant(IncExpr, L))
29672967
continue;
29682968

29692969
if (Chain.isProfitableIncrement(OperExpr, IncExpr, SE)) {
@@ -3316,7 +3316,9 @@ void LSRInstance::CollectFixupsAndInitialFormulae() {
33163316

33173317
// x == y --> x - y == 0
33183318
const SCEV *N = SE.getSCEV(NV);
3319-
if (SE.isLoopInvariant(N, L) && isSafeToExpand(N, SE)) {
3319+
if (SE.isLoopInvariant(N, L) && isSafeToExpand(N, SE) &&
3320+
(!NV->getType()->isPointerTy() ||
3321+
SE.getPointerBase(N) == SE.getPointerBase(S))) {
33203322
// S is normalized, so normalize N before folding it into S
33213323
// to keep the result normalized.
33223324
N = normalizeForPostIncUse(N, TmpPostIncLoops, SE);

llvm/test/Analysis/StackSafetyAnalysis/local.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ define void @StoreInBounds4() {
7171
; CHECK-LABEL: @StoreInBounds4 dso_preemptable{{$}}
7272
; CHECK-NEXT: args uses:
7373
; CHECK-NEXT: allocas uses:
74-
; CHECK-NEXT: x[4]: [-9223372036854775808,9223372036854775807){{$}}
74+
; CHECK-NEXT: x[4]: full-set{{$}}
7575
; CHECK-EMPTY:
7676
entry:
7777
%x = alloca i32, align 4

0 commit comments

Comments
 (0)