Skip to content

Commit f41eb1c

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 301fa24 commit f41eb1c

File tree

12 files changed

+219
-54
lines changed

12 files changed

+219
-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

@@ -4072,6 +4114,8 @@ class SCEVSequentialMinMaxDeduplicatingVisitor final
40724114

40734115
RetVal visitVScale(const SCEVVScale *VScale) { return VScale; }
40744116

4117+
RetVal visitPtrToAddrExpr(const SCEVPtrToAddrExpr *Expr) { return Expr; }
4118+
40754119
RetVal visitPtrToIntExpr(const SCEVPtrToIntExpr *Expr) { return Expr; }
40764120

40774121
RetVal visitTruncateExpr(const SCEVTruncateExpr *Expr) { return Expr; }
@@ -4122,6 +4166,7 @@ static bool scevUnconditionallyPropagatesPoisonFromOperands(SCEVTypes Kind) {
41224166
case scTruncate:
41234167
case scZeroExtend:
41244168
case scSignExtend:
4169+
case scPtrToAddr:
41254170
case scPtrToInt:
41264171
case scAddExpr:
41274172
case scMulExpr:
@@ -6351,8 +6396,9 @@ APInt ScalarEvolution::getConstantMultipleImpl(const SCEV *S,
63516396
switch (S->getSCEVType()) {
63526397
case scConstant:
63536398
return cast<SCEVConstant>(S)->getAPInt();
6399+
case scPtrToAddr:
63546400
case scPtrToInt:
6355-
return getConstantMultiple(cast<SCEVPtrToIntExpr>(S)->getOperand(), CtxI);
6401+
return getConstantMultiple(cast<SCEVCastExpr>(S)->getOperand());
63566402
case scUDivExpr:
63576403
case scVScale:
63586404
return APInt(BitWidth, 1);
@@ -6629,6 +6675,7 @@ ScalarEvolution::getRangeRefIter(const SCEV *S,
66296675
case scTruncate:
66306676
case scZeroExtend:
66316677
case scSignExtend:
6678+
case scPtrToAddr:
66326679
case scPtrToInt:
66336680
case scAddExpr:
66346681
case scMulExpr:
@@ -6756,10 +6803,11 @@ const ConstantRange &ScalarEvolution::getRangeRef(
67566803
SExt, SignHint,
67576804
ConservativeResult.intersectWith(X.signExtend(BitWidth), RangeType));
67586805
}
6806+
case scPtrToAddr:
67596807
case scPtrToInt: {
6760-
const SCEVPtrToIntExpr *PtrToInt = cast<SCEVPtrToIntExpr>(S);
6761-
ConstantRange X = getRangeRef(PtrToInt->getOperand(), SignHint, Depth + 1);
6762-
return setRange(PtrToInt, SignHint, X);
6808+
const SCEVCastExpr *Cast = cast<SCEVCastExpr>(S);
6809+
ConstantRange X = getRangeRef(Cast->getOperand(), SignHint, Depth + 1);
6810+
return setRange(Cast, SignHint, X);
67636811
}
67646812
case scAddExpr: {
67656813
const SCEVAddExpr *Add = cast<SCEVAddExpr>(S);
@@ -7652,6 +7700,7 @@ ScalarEvolution::getOperandsToCreate(Value *V, SmallVectorImpl<Value *> &Ops) {
76527700
case Instruction::Trunc:
76537701
case Instruction::ZExt:
76547702
case Instruction::SExt:
7703+
case Instruction::PtrToAddr:
76557704
case Instruction::PtrToInt:
76567705
Ops.push_back(U->getOperand(0));
76577706
return nullptr;
@@ -8124,13 +8173,16 @@ const SCEV *ScalarEvolution::createSCEV(Value *V) {
81248173
return getSCEV(U->getOperand(0));
81258174
break;
81268175

8176+
case Instruction::PtrToAddr:
81278177
case Instruction::PtrToInt: {
81288178
// Pointer to integer cast is straight-forward, so do model it.
81298179
const SCEV *Op = getSCEV(U->getOperand(0));
81308180
Type *DstIntTy = U->getType();
81318181
// But only if effective SCEV (integer) type is wide enough to represent
81328182
// all possible pointer values.
8133-
const SCEV *IntOp = getPtrToIntExpr(Op, DstIntTy);
8183+
const SCEV *IntOp = U->getOpcode() == Instruction::PtrToInt
8184+
? getPtrToIntExpr(Op, DstIntTy)
8185+
: getPtrToAddrExpr(Op, DstIntTy);
81348186
if (isa<SCEVCouldNotCompute>(IntOp))
81358187
return getUnknown(V);
81368188
return IntOp;
@@ -9932,6 +9984,13 @@ static Constant *BuildConstantFromSCEV(const SCEV *V) {
99329984
return cast<SCEVConstant>(V)->getValue();
99339985
case scUnknown:
99349986
return dyn_cast<Constant>(cast<SCEVUnknown>(V)->getValue());
9987+
case scPtrToAddr: {
9988+
const SCEVPtrToAddrExpr *P2I = cast<SCEVPtrToAddrExpr>(V);
9989+
if (Constant *CastOp = BuildConstantFromSCEV(P2I->getOperand()))
9990+
return ConstantExpr::getPtrToAddr(CastOp, P2I->getType());
9991+
9992+
return nullptr;
9993+
}
99359994
case scPtrToInt: {
99369995
const SCEVPtrToIntExpr *P2I = cast<SCEVPtrToIntExpr>(V);
99379996
if (Constant *CastOp = BuildConstantFromSCEV(P2I->getOperand()))
@@ -9990,6 +10049,7 @@ ScalarEvolution::getWithOperands(const SCEV *S,
999010049
case scTruncate:
999110050
case scZeroExtend:
999210051
case scSignExtend:
10052+
case scPtrToAddr:
999310053
case scPtrToInt:
999410054
return getCastExpr(S->getSCEVType(), NewOps[0], S->getType());
999510055
case scAddRecExpr: {
@@ -10074,6 +10134,7 @@ const SCEV *ScalarEvolution::computeSCEVAtScope(const SCEV *V, const Loop *L) {
1007410134
case scTruncate:
1007510135
case scZeroExtend:
1007610136
case scSignExtend:
10137+
case scPtrToAddr:
1007710138
case scPtrToInt:
1007810139
case scAddExpr:
1007910140
case scMulExpr:
@@ -14169,6 +14230,7 @@ ScalarEvolution::computeLoopDisposition(const SCEV *S, const Loop *L) {
1416914230
case scTruncate:
1417014231
case scZeroExtend:
1417114232
case scSignExtend:
14233+
case scPtrToAddr:
1417214234
case scPtrToInt:
1417314235
case scAddExpr:
1417414236
case scMulExpr:
@@ -14250,6 +14312,7 @@ ScalarEvolution::computeBlockDisposition(const SCEV *S, const BasicBlock *BB) {
1425014312
case scTruncate:
1425114313
case scZeroExtend:
1425214314
case scSignExtend:
14315+
case scPtrToAddr:
1425314316
case scPtrToInt:
1425414317
case scAddExpr:
1425514318
case scMulExpr:

0 commit comments

Comments
 (0)