Skip to content

Commit 0053414

Browse files
committed
[SCEV] Add initial support for ptrtoaddr.
Add support for PtrToAddr to SCEV and use it to compute pointer difference when computing backedge taken counts. This patch retains SCEVPtrToInt, which is mostly used to expressions comping directly from IR. PtrToAddr more closely matches the semantics of most uses in SCEV. See #156978 for some related discussion. The patch still retains SCEVPtrToInt, as it is used for cases where a SCEV expression is used in IR by a ptrtoint, e.g. https://github.com/llvm/llvm-project/blob/main/llvm/test/Transforms/IndVarSimplify/pr59633.ll. Some (or perhaps all, still need to check) should probably just be SCEVUnknown.
1 parent 53575e7 commit 0053414

File tree

8 files changed

+209
-54
lines changed

8 files changed

+209
-54
lines changed

llvm/include/llvm/Analysis/ScalarEvolution.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -563,8 +563,13 @@ class ScalarEvolution {
563563
LLVM_ABI const SCEV *getConstant(ConstantInt *V);
564564
LLVM_ABI const SCEV *getConstant(const APInt &Val);
565565
LLVM_ABI const SCEV *getConstant(Type *Ty, uint64_t V, bool isSigned = false);
566-
LLVM_ABI const SCEV *getLosslessPtrToIntExpr(const SCEV *Op,
567-
unsigned Depth = 0);
566+
LLVM_ABI const SCEV *getLosslessPtrToIntOrAddrExpr(SCEVTypes Kind,
567+
const SCEV *Op,
568+
unsigned Depth = 0);
569+
LLVM_ABI const SCEV *getLosslessPtrToIntExpr(const SCEV *Op);
570+
LLVM_ABI const SCEV *getLosslessPtrToAddrExpr(const SCEV *Op);
571+
572+
LLVM_ABI const SCEV *getPtrToAddrExpr(const SCEV *Op, Type *Ty);
568573
LLVM_ABI const SCEV *getPtrToIntExpr(const SCEV *Op, Type *Ty);
569574
LLVM_ABI const SCEV *getTruncateExpr(const SCEV *Op, Type *Ty,
570575
unsigned Depth = 0);

llvm/include/llvm/Analysis/ScalarEvolutionDivision.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ struct SCEVDivision : public SCEVVisitor<SCEVDivision, void> {
4646

4747
// Except in the trivial case described above, we do not know how to divide
4848
// Expr by Denominator for the following functions with empty implementation.
49+
void visitPtrToAddrExpr(const SCEVPtrToAddrExpr *Numerator) {}
4950
void visitPtrToIntExpr(const SCEVPtrToIntExpr *Numerator) {}
5051
void visitTruncateExpr(const SCEVTruncateExpr *Numerator) {}
5152
void visitZeroExtendExpr(const SCEVZeroExtendExpr *Numerator) {}

llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ enum SCEVTypes : unsigned short {
5353
scSMinExpr,
5454
scSequentialUMinExpr,
5555
scPtrToInt,
56+
scPtrToAddr,
5657
scUnknown,
5758
scCouldNotCompute
5859
};
@@ -121,8 +122,9 @@ class SCEVCastExpr : public SCEV {
121122

122123
/// Methods for support type inquiry through isa, cast, and dyn_cast:
123124
static bool classof(const SCEV *S) {
124-
return S->getSCEVType() == scPtrToInt || S->getSCEVType() == scTruncate ||
125-
S->getSCEVType() == scZeroExtend || S->getSCEVType() == scSignExtend;
125+
return S->getSCEVType() == scPtrToAddr || S->getSCEVType() == scPtrToInt ||
126+
S->getSCEVType() == scTruncate || S->getSCEVType() == scZeroExtend ||
127+
S->getSCEVType() == scSignExtend;
126128
}
127129
};
128130

@@ -138,6 +140,18 @@ class SCEVPtrToIntExpr : public SCEVCastExpr {
138140
static bool classof(const SCEV *S) { return S->getSCEVType() == scPtrToInt; }
139141
};
140142

143+
/// This class represents a cast from a pointer to a pointer-sized integer
144+
/// value, without capturing the provenance of the pointer.
145+
class SCEVPtrToAddrExpr : public SCEVCastExpr {
146+
friend class ScalarEvolution;
147+
148+
SCEVPtrToAddrExpr(const FoldingSetNodeIDRef ID, const SCEV *Op, Type *ITy);
149+
150+
public:
151+
/// Methods for support type inquiry through isa, cast, and dyn_cast:
152+
static bool classof(const SCEV *S) { return S->getSCEVType() == scPtrToAddr; }
153+
};
154+
141155
/// This is the base class for unary integral cast operator classes.
142156
class SCEVIntegralCastExpr : public SCEVCastExpr {
143157
protected:
@@ -615,6 +629,8 @@ template <typename SC, typename RetVal = void> struct SCEVVisitor {
615629
return ((SC *)this)->visitConstant((const SCEVConstant *)S);
616630
case scVScale:
617631
return ((SC *)this)->visitVScale((const SCEVVScale *)S);
632+
case scPtrToAddr:
633+
return ((SC *)this)->visitPtrToAddrExpr((const SCEVPtrToAddrExpr *)S);
618634
case scPtrToInt:
619635
return ((SC *)this)->visitPtrToIntExpr((const SCEVPtrToIntExpr *)S);
620636
case scTruncate:
@@ -685,6 +701,7 @@ template <typename SV> class SCEVTraversal {
685701
case scVScale:
686702
case scUnknown:
687703
continue;
704+
case scPtrToAddr:
688705
case scPtrToInt:
689706
case scTruncate:
690707
case scZeroExtend:
@@ -774,6 +791,13 @@ class SCEVRewriteVisitor : public SCEVVisitor<SC, const SCEV *> {
774791

775792
const SCEV *visitVScale(const SCEVVScale *VScale) { return VScale; }
776793

794+
const SCEV *visitPtrToAddrExpr(const SCEVPtrToAddrExpr *Expr) {
795+
const SCEV *Operand = ((SC *)this)->visit(Expr->getOperand());
796+
return Operand == Expr->getOperand()
797+
? Expr
798+
: SE.getPtrToAddrExpr(Operand, Expr->getType());
799+
}
800+
777801
const SCEV *visitPtrToIntExpr(const SCEVPtrToIntExpr *Expr) {
778802
const SCEV *Operand = ((SC *)this)->visit(Expr->getOperand());
779803
return Operand == Expr->getOperand()

llvm/include/llvm/Transforms/Utils/ScalarEvolutionExpander.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,8 @@ class SCEVExpander : public SCEVVisitor<SCEVExpander, Value *> {
498498

499499
Value *visitVScale(const SCEVVScale *S);
500500

501+
Value *visitPtrToAddrExpr(const SCEVPtrToAddrExpr *S);
502+
501503
Value *visitPtrToIntExpr(const SCEVPtrToIntExpr *S);
502504

503505
Value *visitTruncateExpr(const SCEVTruncateExpr *S);

llvm/lib/Analysis/ScalarEvolution.cpp

Lines changed: 92 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -277,11 +277,13 @@ void SCEV::print(raw_ostream &OS) const {
277277
case scVScale:
278278
OS << "vscale";
279279
return;
280+
case scPtrToAddr:
280281
case scPtrToInt: {
281-
const SCEVPtrToIntExpr *PtrToInt = cast<SCEVPtrToIntExpr>(this);
282-
const SCEV *Op = PtrToInt->getOperand();
283-
OS << "(ptrtoint " << *Op->getType() << " " << *Op << " to "
284-
<< *PtrToInt->getType() << ")";
282+
const SCEVCastExpr *PtrCast = cast<SCEVCastExpr>(this);
283+
const SCEV *Op = PtrCast->getOperand();
284+
StringRef OpS = getSCEVType() == scPtrToAddr ? "addr" : "int";
285+
OS << "(ptrto" << OpS << " " << *Op->getType() << " " << *Op << " to "
286+
<< *PtrCast->getType() << ")";
285287
return;
286288
}
287289
case scTruncate: {
@@ -386,6 +388,7 @@ Type *SCEV::getType() const {
386388
return cast<SCEVConstant>(this)->getType();
387389
case scVScale:
388390
return cast<SCEVVScale>(this)->getType();
391+
case scPtrToAddr:
389392
case scPtrToInt:
390393
case scTruncate:
391394
case scZeroExtend:
@@ -420,6 +423,7 @@ ArrayRef<const SCEV *> SCEV::operands() const {
420423
case scVScale:
421424
case scUnknown:
422425
return {};
426+
case scPtrToAddr:
423427
case scPtrToInt:
424428
case scTruncate:
425429
case scZeroExtend:
@@ -512,6 +516,13 @@ SCEVCastExpr::SCEVCastExpr(const FoldingSetNodeIDRef ID, SCEVTypes SCEVTy,
512516
const SCEV *op, Type *ty)
513517
: SCEV(ID, SCEVTy, computeExpressionSize(op)), Op(op), Ty(ty) {}
514518

519+
SCEVPtrToAddrExpr::SCEVPtrToAddrExpr(const FoldingSetNodeIDRef ID,
520+
const SCEV *Op, Type *ITy)
521+
: SCEVCastExpr(ID, scPtrToAddr, Op, ITy) {
522+
assert(getOperand()->getType()->isPointerTy() && Ty->isIntegerTy() &&
523+
"Must be a non-bit-width-changing pointer-to-integer cast!");
524+
}
525+
515526
SCEVPtrToIntExpr::SCEVPtrToIntExpr(const FoldingSetNodeIDRef ID, const SCEV *Op,
516527
Type *ITy)
517528
: SCEVCastExpr(ID, scPtrToInt, Op, ITy) {
@@ -724,6 +735,7 @@ CompareSCEVComplexity(const LoopInfo *const LI, const SCEV *LHS,
724735
case scTruncate:
725736
case scZeroExtend:
726737
case scSignExtend:
738+
case scPtrToAddr:
727739
case scPtrToInt:
728740
case scAddExpr:
729741
case scMulExpr:
@@ -1004,10 +1016,11 @@ SCEVAddRecExpr::evaluateAtIteration(ArrayRef<const SCEV *> Operands,
10041016
// SCEV Expression folder implementations
10051017
//===----------------------------------------------------------------------===//
10061018

1007-
const SCEV *ScalarEvolution::getLosslessPtrToIntExpr(const SCEV *Op,
1008-
unsigned Depth) {
1019+
const SCEV *ScalarEvolution::getLosslessPtrToIntOrAddrExpr(SCEVTypes Kind,
1020+
const SCEV *Op,
1021+
unsigned Depth) {
10091022
assert(Depth <= 1 &&
1010-
"getLosslessPtrToIntExpr() should self-recurse at most once.");
1023+
"getLosslessPtrToIntOrAddrExpr() should self-recurse at most once.");
10111024

10121025
// We could be called with an integer-typed operands during SCEV rewrites.
10131026
// Since the operand is an integer already, just perform zext/trunc/self cast.
@@ -1052,35 +1065,45 @@ const SCEV *ScalarEvolution::getLosslessPtrToIntExpr(const SCEV *Op,
10521065
// Create an explicit cast node.
10531066
// We can reuse the existing insert position since if we get here,
10541067
// we won't have made any changes which would invalidate it.
1055-
SCEV *S = new (SCEVAllocator)
1056-
SCEVPtrToIntExpr(ID.Intern(SCEVAllocator), Op, IntPtrTy);
1068+
SCEV *S;
1069+
if (Kind == scPtrToInt) {
1070+
S = new (SCEVAllocator)
1071+
SCEVPtrToIntExpr(ID.Intern(SCEVAllocator), Op, IntPtrTy);
1072+
} else {
1073+
S = new (SCEVAllocator)
1074+
SCEVPtrToAddrExpr(ID.Intern(SCEVAllocator), Op, IntPtrTy);
1075+
}
10571076
UniqueSCEVs.InsertNode(S, IP);
10581077
registerUser(S, Op);
10591078
return S;
10601079
}
10611080

1062-
assert(Depth == 0 && "getLosslessPtrToIntExpr() should not self-recurse for "
1063-
"non-SCEVUnknown's.");
1081+
assert(Depth == 0 &&
1082+
"getLosslessPtrToIntOrAddrExpr() should not self-recurse for "
1083+
"non-SCEVUnknown's.");
10641084

10651085
// Otherwise, we've got some expression that is more complex than just a
1066-
// single SCEVUnknown. But we don't want to have a SCEVPtrToIntExpr of an
1067-
// arbitrary expression, we want to have SCEVPtrToIntExpr of an SCEVUnknown
1068-
// only, and the expressions must otherwise be integer-typed.
1069-
// So sink the cast down to the SCEVUnknown's.
1086+
// single SCEVUnknown. But we don't want to have a SCEVPtrTo(Int|Addr)Expr of
1087+
// an arbitrary expression, we want to have SCEVPtrTo(Int|Addr)Expr of an
1088+
// SCEVUnknown only, and the expressions must otherwise be integer-typed. So
1089+
// sink the cast down to the SCEVUnknown's.
10701090

1071-
/// The SCEVPtrToIntSinkingRewriter takes a scalar evolution expression,
1091+
/// The SCEVPtrToIntOrAddrSinkingRewriter takes a scalar evolution expression,
10721092
/// which computes a pointer-typed value, and rewrites the whole expression
10731093
/// tree so that *all* the computations are done on integers, and the only
10741094
/// pointer-typed operands in the expression are SCEVUnknown.
1075-
class SCEVPtrToIntSinkingRewriter
1076-
: public SCEVRewriteVisitor<SCEVPtrToIntSinkingRewriter> {
1077-
using Base = SCEVRewriteVisitor<SCEVPtrToIntSinkingRewriter>;
1095+
class SCEVPtrToIntOrAddrSinkingRewriter
1096+
: public SCEVRewriteVisitor<SCEVPtrToIntOrAddrSinkingRewriter> {
1097+
using Base = SCEVRewriteVisitor<SCEVPtrToIntOrAddrSinkingRewriter>;
1098+
const SCEVTypes Kind;
10781099

10791100
public:
1080-
SCEVPtrToIntSinkingRewriter(ScalarEvolution &SE) : SCEVRewriteVisitor(SE) {}
1101+
SCEVPtrToIntOrAddrSinkingRewriter(SCEVTypes Kind, ScalarEvolution &SE)
1102+
: SCEVRewriteVisitor(SE), Kind(Kind) {}
10811103

1082-
static const SCEV *rewrite(const SCEV *Scev, ScalarEvolution &SE) {
1083-
SCEVPtrToIntSinkingRewriter Rewriter(SE);
1104+
static const SCEV *rewrite(const SCEV *Scev, SCEVTypes Kind,
1105+
ScalarEvolution &SE) {
1106+
SCEVPtrToIntOrAddrSinkingRewriter Rewriter(Kind, SE);
10841107
return Rewriter.visit(Scev);
10851108
}
10861109

@@ -1116,18 +1139,37 @@ const SCEV *ScalarEvolution::getLosslessPtrToIntExpr(const SCEV *Op,
11161139
const SCEV *visitUnknown(const SCEVUnknown *Expr) {
11171140
assert(Expr->getType()->isPointerTy() &&
11181141
"Should only reach pointer-typed SCEVUnknown's.");
1119-
return SE.getLosslessPtrToIntExpr(Expr, /*Depth=*/1);
1142+
return SE.getLosslessPtrToIntOrAddrExpr(Kind, Expr, /*Depth=*/1);
11201143
}
11211144
};
11221145

11231146
// And actually perform the cast sinking.
1124-
const SCEV *IntOp = SCEVPtrToIntSinkingRewriter::rewrite(Op, *this);
1147+
const SCEV *IntOp =
1148+
SCEVPtrToIntOrAddrSinkingRewriter::rewrite(Op, Kind, *this);
11251149
assert(IntOp->getType()->isIntegerTy() &&
11261150
"We must have succeeded in sinking the cast, "
11271151
"and ending up with an integer-typed expression!");
11281152
return IntOp;
11291153
}
11301154

1155+
const SCEV *ScalarEvolution::getLosslessPtrToAddrExpr(const SCEV *Op) {
1156+
return getLosslessPtrToIntOrAddrExpr(scPtrToAddr, Op);
1157+
}
1158+
1159+
const SCEV *ScalarEvolution::getLosslessPtrToIntExpr(const SCEV *Op) {
1160+
return getLosslessPtrToIntOrAddrExpr(scPtrToInt, Op);
1161+
}
1162+
1163+
const SCEV *ScalarEvolution::getPtrToAddrExpr(const SCEV *Op, Type *Ty) {
1164+
assert(Ty->isIntegerTy() && "Target type must be an integer type!");
1165+
1166+
const SCEV *IntOp = getLosslessPtrToAddrExpr(Op);
1167+
if (isa<SCEVCouldNotCompute>(IntOp))
1168+
return IntOp;
1169+
1170+
return getTruncateOrZeroExtend(IntOp, Ty);
1171+
}
1172+
11311173
const SCEV *ScalarEvolution::getPtrToIntExpr(const SCEV *Op, Type *Ty) {
11321174
assert(Ty->isIntegerTy() && "Target type must be an integer type!");
11331175

@@ -4076,6 +4118,8 @@ class SCEVSequentialMinMaxDeduplicatingVisitor final
40764118

40774119
RetVal visitVScale(const SCEVVScale *VScale) { return VScale; }
40784120

4121+
RetVal visitPtrToAddrExpr(const SCEVPtrToAddrExpr *Expr) { return Expr; }
4122+
40794123
RetVal visitPtrToIntExpr(const SCEVPtrToIntExpr *Expr) { return Expr; }
40804124

40814125
RetVal visitTruncateExpr(const SCEVTruncateExpr *Expr) { return Expr; }
@@ -4126,6 +4170,7 @@ static bool scevUnconditionallyPropagatesPoisonFromOperands(SCEVTypes Kind) {
41264170
case scTruncate:
41274171
case scZeroExtend:
41284172
case scSignExtend:
4173+
case scPtrToAddr:
41294174
case scPtrToInt:
41304175
case scAddExpr:
41314176
case scMulExpr:
@@ -6361,8 +6406,9 @@ APInt ScalarEvolution::getConstantMultipleImpl(const SCEV *S,
63616406
switch (S->getSCEVType()) {
63626407
case scConstant:
63636408
return cast<SCEVConstant>(S)->getAPInt();
6409+
case scPtrToAddr:
63646410
case scPtrToInt:
6365-
return getConstantMultiple(cast<SCEVPtrToIntExpr>(S)->getOperand(), CtxI);
6411+
return getConstantMultiple(cast<SCEVCastExpr>(S)->getOperand());
63666412
case scUDivExpr:
63676413
case scVScale:
63686414
return APInt(BitWidth, 1);
@@ -6639,6 +6685,7 @@ ScalarEvolution::getRangeRefIter(const SCEV *S,
66396685
case scTruncate:
66406686
case scZeroExtend:
66416687
case scSignExtend:
6688+
case scPtrToAddr:
66426689
case scPtrToInt:
66436690
case scAddExpr:
66446691
case scMulExpr:
@@ -6766,10 +6813,11 @@ const ConstantRange &ScalarEvolution::getRangeRef(
67666813
SExt, SignHint,
67676814
ConservativeResult.intersectWith(X.signExtend(BitWidth), RangeType));
67686815
}
6816+
case scPtrToAddr:
67696817
case scPtrToInt: {
6770-
const SCEVPtrToIntExpr *PtrToInt = cast<SCEVPtrToIntExpr>(S);
6771-
ConstantRange X = getRangeRef(PtrToInt->getOperand(), SignHint, Depth + 1);
6772-
return setRange(PtrToInt, SignHint, X);
6818+
const SCEVCastExpr *Cast = cast<SCEVCastExpr>(S);
6819+
ConstantRange X = getRangeRef(Cast->getOperand(), SignHint, Depth + 1);
6820+
return setRange(Cast, SignHint, X);
67736821
}
67746822
case scAddExpr: {
67756823
const SCEVAddExpr *Add = cast<SCEVAddExpr>(S);
@@ -7662,6 +7710,7 @@ ScalarEvolution::getOperandsToCreate(Value *V, SmallVectorImpl<Value *> &Ops) {
76627710
case Instruction::Trunc:
76637711
case Instruction::ZExt:
76647712
case Instruction::SExt:
7713+
case Instruction::PtrToAddr:
76657714
case Instruction::PtrToInt:
76667715
Ops.push_back(U->getOperand(0));
76677716
return nullptr;
@@ -8134,13 +8183,16 @@ const SCEV *ScalarEvolution::createSCEV(Value *V) {
81348183
return getSCEV(U->getOperand(0));
81358184
break;
81368185

8186+
case Instruction::PtrToAddr:
81378187
case Instruction::PtrToInt: {
81388188
// Pointer to integer cast is straight-forward, so do model it.
81398189
const SCEV *Op = getSCEV(U->getOperand(0));
81408190
Type *DstIntTy = U->getType();
81418191
// But only if effective SCEV (integer) type is wide enough to represent
81428192
// all possible pointer values.
8143-
const SCEV *IntOp = getPtrToIntExpr(Op, DstIntTy);
8193+
const SCEV *IntOp = U->getOpcode() == Instruction::PtrToInt
8194+
? getPtrToIntExpr(Op, DstIntTy)
8195+
: getPtrToAddrExpr(Op, DstIntTy);
81448196
if (isa<SCEVCouldNotCompute>(IntOp))
81458197
return getUnknown(V);
81468198
return IntOp;
@@ -9942,6 +9994,13 @@ static Constant *BuildConstantFromSCEV(const SCEV *V) {
99429994
return cast<SCEVConstant>(V)->getValue();
99439995
case scUnknown:
99449996
return dyn_cast<Constant>(cast<SCEVUnknown>(V)->getValue());
9997+
case scPtrToAddr: {
9998+
const SCEVPtrToAddrExpr *P2I = cast<SCEVPtrToAddrExpr>(V);
9999+
if (Constant *CastOp = BuildConstantFromSCEV(P2I->getOperand()))
10000+
return ConstantExpr::getPtrToAddr(CastOp, P2I->getType());
10001+
10002+
return nullptr;
10003+
}
994510004
case scPtrToInt: {
994610005
const SCEVPtrToIntExpr *P2I = cast<SCEVPtrToIntExpr>(V);
994710006
if (Constant *CastOp = BuildConstantFromSCEV(P2I->getOperand()))
@@ -10000,6 +10059,7 @@ ScalarEvolution::getWithOperands(const SCEV *S,
1000010059
case scTruncate:
1000110060
case scZeroExtend:
1000210061
case scSignExtend:
10062+
case scPtrToAddr:
1000310063
case scPtrToInt:
1000410064
return getCastExpr(S->getSCEVType(), NewOps[0], S->getType());
1000510065
case scAddRecExpr: {
@@ -10084,6 +10144,7 @@ const SCEV *ScalarEvolution::computeSCEVAtScope(const SCEV *V, const Loop *L) {
1008410144
case scTruncate:
1008510145
case scZeroExtend:
1008610146
case scSignExtend:
10147+
case scPtrToAddr:
1008710148
case scPtrToInt:
1008810149
case scAddExpr:
1008910150
case scMulExpr:
@@ -14187,6 +14248,7 @@ ScalarEvolution::computeLoopDisposition(const SCEV *S, const Loop *L) {
1418714248
case scTruncate:
1418814249
case scZeroExtend:
1418914250
case scSignExtend:
14251+
case scPtrToAddr:
1419014252
case scPtrToInt:
1419114253
case scAddExpr:
1419214254
case scMulExpr:
@@ -14268,6 +14330,7 @@ ScalarEvolution::computeBlockDisposition(const SCEV *S, const BasicBlock *BB) {
1426814330
case scTruncate:
1426914331
case scZeroExtend:
1427014332
case scSignExtend:
14333+
case scPtrToAddr:
1427114334
case scPtrToInt:
1427214335
case scAddExpr:
1427314336
case scMulExpr:

0 commit comments

Comments
 (0)