Skip to content

Commit a9c2dc2

Browse files
LebedevRImemfrob
authored andcommitted
[SCEV] Introduce SCEVPtrToIntExpr (PR46786)
And use it to model LLVM IR's `ptrtoint` cast. This is essentially an alternative to D88806, but with no chance for all the problems it caused due to having the cast as implicit there. (see rG7ee6c402474a2f5fd21c403e7529f97f6362fdb3) As we've established by now, there are at least two reasons why we want this: * It will allow SCEV to actually model the `ptrtoint` casts and their operands, instead of treating them as `SCEVUnknown` * It should help with initial problem of PR46786 - this should eventually allow us to not loose pointer-ness of an expression in more cases As discussed in [[ https://bugs.llvm.org/show_bug.cgi?id=46786 | PR46786 ]], in principle, we could just extend `SCEVUnknown` with a `is ptrtoint` cast, because `ScalarEvolution::getPtrToIntExpr()` should sink the cast as far down into the expression as possible, so in the end we should always end up with `SCEVPtrToIntExpr` of `SCEVUnknown`. But i think that it isn't the best solution, because it doesn't really matter from memory consumption side - there probably won't be *that* many `SCEVPtrToIntExpr`s for it to matter, and it allows for much better discoverability. Reviewed By: mkazantsev Differential Revision: https://reviews.llvm.org/D89456
1 parent 2e902a8 commit a9c2dc2

File tree

19 files changed

+489
-214
lines changed

19 files changed

+489
-214
lines changed

llvm/include/llvm/Analysis/ScalarEvolution.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,7 @@ class ScalarEvolution {
512512
const SCEV *getConstant(ConstantInt *V);
513513
const SCEV *getConstant(const APInt &Val);
514514
const SCEV *getConstant(Type *Ty, uint64_t V, bool isSigned = false);
515+
const SCEV *getPtrToIntExpr(const SCEV *Op, Type *Ty, unsigned Depth = 0);
515516
const SCEV *getTruncateExpr(const SCEV *Op, Type *Ty, unsigned Depth = 0);
516517
const SCEV *getZeroExtendExpr(const SCEV *Op, Type *Ty, unsigned Depth = 0);
517518
const SCEV *getSignExtendExpr(const SCEV *Op, Type *Ty, unsigned Depth = 0);

llvm/include/llvm/Analysis/ScalarEvolutionDivision.h

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

3434
// Except in the trivial case described above, we do not know how to divide
3535
// Expr by Denominator for the following functions with empty implementation.
36+
void visitPtrToIntExpr(const SCEVPtrToIntExpr *Numerator) {}
3637
void visitTruncateExpr(const SCEVTruncateExpr *Numerator) {}
3738
void visitZeroExtendExpr(const SCEVZeroExtendExpr *Numerator) {}
3839
void visitSignExtendExpr(const SCEVSignExtendExpr *Numerator) {}

llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ class Type;
4040
// folders simpler.
4141
scConstant, scTruncate, scZeroExtend, scSignExtend, scAddExpr, scMulExpr,
4242
scUDivExpr, scAddRecExpr, scUMaxExpr, scSMaxExpr, scUMinExpr, scSMinExpr,
43-
scUnknown, scCouldNotCompute
43+
scPtrToInt, scUnknown, scCouldNotCompute
4444
};
4545

4646
/// This class represents a constant integer value.
@@ -72,13 +72,13 @@ class Type;
7272
}
7373

7474
/// This is the base class for unary cast operator classes.
75-
class SCEVIntegralCastExpr : public SCEV {
75+
class SCEVCastExpr : public SCEV {
7676
protected:
7777
std::array<const SCEV *, 1> Operands;
7878
Type *Ty;
7979

80-
SCEVIntegralCastExpr(const FoldingSetNodeIDRef ID, SCEVTypes SCEVTy,
81-
const SCEV *op, Type *ty);
80+
SCEVCastExpr(const FoldingSetNodeIDRef ID, SCEVTypes SCEVTy, const SCEV *op,
81+
Type *ty);
8282

8383
public:
8484
const SCEV *getOperand() const { return Operands[0]; }
@@ -95,6 +95,35 @@ class Type;
9595
size_t getNumOperands() const { return 1; }
9696
Type *getType() const { return Ty; }
9797

98+
/// Methods for support type inquiry through isa, cast, and dyn_cast:
99+
static bool classof(const SCEV *S) {
100+
return S->getSCEVType() == scPtrToInt || S->getSCEVType() == scTruncate ||
101+
S->getSCEVType() == scZeroExtend ||
102+
S->getSCEVType() == scSignExtend;
103+
}
104+
};
105+
106+
/// This class represents a cast from a pointer to a pointer-sized integer
107+
/// value.
108+
class SCEVPtrToIntExpr : public SCEVCastExpr {
109+
friend class ScalarEvolution;
110+
111+
SCEVPtrToIntExpr(const FoldingSetNodeIDRef ID, const SCEV *Op, Type *ITy);
112+
113+
public:
114+
/// Methods for support type inquiry through isa, cast, and dyn_cast:
115+
static bool classof(const SCEV *S) {
116+
return S->getSCEVType() == scPtrToInt;
117+
}
118+
};
119+
120+
/// This is the base class for unary integral cast operator classes.
121+
class SCEVIntegralCastExpr : public SCEVCastExpr {
122+
protected:
123+
SCEVIntegralCastExpr(const FoldingSetNodeIDRef ID, SCEVTypes SCEVTy,
124+
const SCEV *op, Type *ty);
125+
126+
public:
98127
/// Methods for support type inquiry through isa, cast, and dyn_cast:
99128
static bool classof(const SCEV *S) {
100129
return S->getSCEVType() == scTruncate ||
@@ -541,6 +570,8 @@ class Type;
541570
switch (S->getSCEVType()) {
542571
case scConstant:
543572
return ((SC*)this)->visitConstant((const SCEVConstant*)S);
573+
case scPtrToInt:
574+
return ((SC *)this)->visitPtrToIntExpr((const SCEVPtrToIntExpr *)S);
544575
case scTruncate:
545576
return ((SC*)this)->visitTruncateExpr((const SCEVTruncateExpr*)S);
546577
case scZeroExtend:
@@ -606,10 +637,11 @@ class Type;
606637
case scConstant:
607638
case scUnknown:
608639
continue;
640+
case scPtrToInt:
609641
case scTruncate:
610642
case scZeroExtend:
611643
case scSignExtend:
612-
push(cast<SCEVIntegralCastExpr>(S)->getOperand());
644+
push(cast<SCEVCastExpr>(S)->getOperand());
613645
continue;
614646
case scAddExpr:
615647
case scMulExpr:
@@ -698,6 +730,13 @@ class Type;
698730
return Constant;
699731
}
700732

733+
const SCEV *visitPtrToIntExpr(const SCEVPtrToIntExpr *Expr) {
734+
const SCEV *Operand = ((SC *)this)->visit(Expr->getOperand());
735+
return Operand == Expr->getOperand()
736+
? Expr
737+
: SE.getPtrToIntExpr(Operand, Expr->getType());
738+
}
739+
701740
const SCEV *visitTruncateExpr(const SCEVTruncateExpr *Expr) {
702741
const SCEV *Operand = ((SC*)this)->visit(Expr->getOperand());
703742
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
@@ -446,6 +446,8 @@ class SCEVExpander : public SCEVVisitor<SCEVExpander, Value *> {
446446

447447
Value *visitConstant(const SCEVConstant *S) { return S->getValue(); }
448448

449+
Value *visitPtrToIntExpr(const SCEVPtrToIntExpr *S);
450+
449451
Value *visitTruncateExpr(const SCEVTruncateExpr *S);
450452

451453
Value *visitZeroExtendExpr(const SCEVZeroExtendExpr *S);

0 commit comments

Comments
 (0)