Make SCEV::getType() and SCEV::print non-virtual. Move SCEV::hasOperand

to ScalarEvolution. Delete SCEV::~SCEV. SCEV is no longer virtual.

llvm-svn: 119578
This commit is contained in:
Dan Gohman 2010-11-17 22:27:42 +00:00
parent ea6ac4cdff
commit fb6ea18d0a
3 changed files with 186 additions and 167 deletions

View File

@ -70,8 +70,7 @@ namespace llvm {
private:
SCEV(const SCEV &); // DO NOT IMPLEMENT
void operator=(const SCEV &); // DO NOT IMPLEMENT
protected:
virtual ~SCEV();
public:
explicit SCEV(const FoldingSetNodeIDRef ID, unsigned SCEVTy) :
FastID(ID), SCEVType(SCEVTy), SubclassData(0) {}
@ -80,7 +79,7 @@ namespace llvm {
/// getType - Return the LLVM type of this SCEV expression.
///
virtual const Type *getType() const = 0;
const Type *getType() const;
/// isZero - Return true if the expression is a constant zero.
///
@ -95,14 +94,10 @@ namespace llvm {
///
bool isAllOnesValue() const;
/// hasOperand - Test whether this SCEV has Op as a direct or
/// indirect operand.
virtual bool hasOperand(const SCEV *Op) const = 0;
/// print - Print out the internal representation of this scalar to the
/// specified stream. This should really only be used for debugging
/// purposes.
virtual void print(raw_ostream &OS) const = 0;
void print(raw_ostream &OS) const;
/// dump - This method is used for debugging.
///
@ -137,11 +132,6 @@ namespace llvm {
struct SCEVCouldNotCompute : public SCEV {
SCEVCouldNotCompute();
// None of these methods are valid for this object.
virtual const Type *getType() const;
virtual void print(raw_ostream &OS) const;
virtual bool hasOperand(const SCEV *Op) const;
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const SCEVCouldNotCompute *S) { return true; }
static bool classof(const SCEV *S);
@ -691,6 +681,10 @@ namespace llvm {
/// properly dominate the specified basic block.
bool properlyDominates(const SCEV *S, BasicBlock *BB) const;
/// hasOperand - Test whether the given SCEV has Op as a direct or
/// indirect operand.
bool hasOperand(const SCEV *S, const SCEV *Op) const;
virtual bool runOnFunction(Function &F);
virtual void releaseMemory();
virtual void getAnalysisUsage(AnalysisUsage &AU) const;

View File

@ -42,13 +42,7 @@ namespace llvm {
public:
ConstantInt *getValue() const { return V; }
virtual const Type *getType() const;
virtual bool hasOperand(const SCEV *) const {
return false;
}
virtual void print(raw_ostream &OS) const;
const Type *getType() const { return V->getType(); }
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const SCEVConstant *S) { return true; }
@ -70,11 +64,7 @@ namespace llvm {
public:
const SCEV *getOperand() const { return Op; }
virtual const Type *getType() const { return Ty; }
virtual bool hasOperand(const SCEV *O) const {
return Op == O || Op->hasOperand(O);
}
const Type *getType() const { return Ty; }
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const SCEVCastExpr *S) { return true; }
@ -96,8 +86,6 @@ namespace llvm {
const SCEV *op, const Type *ty);
public:
virtual void print(raw_ostream &OS) const;
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const SCEVTruncateExpr *S) { return true; }
static inline bool classof(const SCEV *S) {
@ -116,8 +104,6 @@ namespace llvm {
const SCEV *op, const Type *ty);
public:
virtual void print(raw_ostream &OS) const;
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const SCEVZeroExtendExpr *S) { return true; }
static inline bool classof(const SCEV *S) {
@ -136,8 +122,6 @@ namespace llvm {
const SCEV *op, const Type *ty);
public:
virtual void print(raw_ostream &OS) const;
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const SCEVSignExtendExpr *S) { return true; }
static inline bool classof(const SCEV *S) {
@ -174,9 +158,7 @@ namespace llvm {
op_iterator op_begin() const { return Operands; }
op_iterator op_end() const { return Operands + NumOperands; }
virtual bool hasOperand(const SCEV *O) const;
virtual const Type *getType() const { return getOperand(0)->getType(); }
const Type *getType() const { return getOperand(0)->getType(); }
bool hasNoUnsignedWrap() const { return SubclassData & (1 << 0); }
void setHasNoUnsignedWrap(bool B) {
@ -209,10 +191,6 @@ namespace llvm {
: SCEVNAryExpr(ID, T, O, N) {}
public:
virtual const char *getOperationStr() const = 0;
virtual void print(raw_ostream &OS) const;
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const SCEVCommutativeExpr *S) { return true; }
static inline bool classof(const SCEV *S) {
@ -236,9 +214,7 @@ namespace llvm {
}
public:
virtual const char *getOperationStr() const { return " + "; }
virtual const Type *getType() const {
const Type *getType() const {
// Use the type of the last operand, which is likely to be a pointer
// type, if there is one. This doesn't usually matter, but it can help
// reduce casts when the expressions are expanded.
@ -264,8 +240,6 @@ namespace llvm {
}
public:
virtual const char *getOperationStr() const { return " * "; }
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const SCEVMulExpr *S) { return true; }
static inline bool classof(const SCEV *S) {
@ -289,14 +263,15 @@ namespace llvm {
const SCEV *getLHS() const { return LHS; }
const SCEV *getRHS() const { return RHS; }
virtual bool hasOperand(const SCEV *O) const {
return O == LHS || O == RHS || LHS->hasOperand(O) || RHS->hasOperand(O);
const Type *getType() const {
// In most cases the types of LHS and RHS will be the same, but in some
// crazy cases one or the other may be a pointer. ScalarEvolution doesn't
// depend on the type for correctness, but handling types carefully can
// avoid extra casts in the SCEVExpander. The LHS is more likely to be
// a pointer type than the RHS, so use the RHS' type here.
return getRHS()->getType();
}
virtual const Type *getType() const;
void print(raw_ostream &OS) const;
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const SCEVUDivExpr *S) { return true; }
static inline bool classof(const SCEV *S) {
@ -371,8 +346,6 @@ namespace llvm {
return cast<SCEVAddRecExpr>(SE.getAddExpr(this, getStepRecurrence(SE)));
}
virtual void print(raw_ostream &OS) const;
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const SCEVAddRecExpr *S) { return true; }
static inline bool classof(const SCEV *S) {
@ -396,8 +369,6 @@ namespace llvm {
}
public:
virtual const char *getOperationStr() const { return " smax "; }
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const SCEVSMaxExpr *S) { return true; }
static inline bool classof(const SCEV *S) {
@ -421,8 +392,6 @@ namespace llvm {
}
public:
virtual const char *getOperationStr() const { return " umax "; }
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const SCEVUMaxExpr *S) { return true; }
static inline bool classof(const SCEV *S) {
@ -468,13 +437,7 @@ namespace llvm {
bool isAlignOf(const Type *&AllocTy) const;
bool isOffsetOf(const Type *&STy, Constant *&FieldNo) const;
virtual bool hasOperand(const SCEV *) const {
return false;
}
virtual const Type *getType() const;
virtual void print(raw_ostream &OS) const;
const Type *getType() const { return getValPtr()->getType(); }
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const SCEVUnknown *S) { return true; }

View File

@ -120,13 +120,135 @@ char ScalarEvolution::ID = 0;
// Implementation of the SCEV class.
//
SCEV::~SCEV() {}
void SCEV::dump() const {
print(dbgs());
dbgs() << '\n';
}
void SCEV::print(raw_ostream &OS) const {
switch (getSCEVType()) {
case scConstant:
WriteAsOperand(OS, cast<SCEVConstant>(this)->getValue(), false);
return;
case scTruncate: {
const SCEVTruncateExpr *Trunc = cast<SCEVTruncateExpr>(this);
const SCEV *Op = Trunc->getOperand();
OS << "(trunc " << *Op->getType() << " " << *Op << " to "
<< *Trunc->getType() << ")";
return;
}
case scZeroExtend: {
const SCEVZeroExtendExpr *ZExt = cast<SCEVZeroExtendExpr>(this);
const SCEV *Op = ZExt->getOperand();
OS << "(zext " << *Op->getType() << " " << *Op << " to "
<< *ZExt->getType() << ")";
return;
}
case scSignExtend: {
const SCEVSignExtendExpr *SExt = cast<SCEVSignExtendExpr>(this);
const SCEV *Op = SExt->getOperand();
OS << "(sext " << *Op->getType() << " " << *Op << " to "
<< *SExt->getType() << ")";
return;
}
case scAddRecExpr: {
const SCEVAddRecExpr *AR = cast<SCEVAddRecExpr>(this);
OS << "{" << *AR->getOperand(0);
for (unsigned i = 1, e = AR->getNumOperands(); i != e; ++i)
OS << ",+," << *AR->getOperand(i);
OS << "}<";
WriteAsOperand(OS, AR->getLoop()->getHeader(), /*PrintType=*/false);
OS << ">";
return;
}
case scAddExpr:
case scMulExpr:
case scUMaxExpr:
case scSMaxExpr: {
const SCEVNAryExpr *NAry = cast<SCEVNAryExpr>(this);
const char *OpStr;
switch (NAry->getSCEVType()) {
case scAddExpr: OpStr = " + "; break;
case scMulExpr: OpStr = " * "; break;
case scUMaxExpr: OpStr = " umax "; break;
case scSMaxExpr: OpStr = " smax "; break;
}
OS << "(";
for (SCEVNAryExpr::op_iterator I = NAry->op_begin(), E = NAry->op_end();
I != E; ++I) {
OS << **I;
if (llvm::next(I) != E)
OS << OpStr;
}
OS << ")";
return;
}
case scUDivExpr: {
const SCEVUDivExpr *UDiv = cast<SCEVUDivExpr>(this);
OS << "(" << *UDiv->getLHS() << " /u " << *UDiv->getRHS() << ")";
return;
}
case scUnknown: {
const SCEVUnknown *U = cast<SCEVUnknown>(this);
const Type *AllocTy;
if (U->isSizeOf(AllocTy)) {
OS << "sizeof(" << *AllocTy << ")";
return;
}
if (U->isAlignOf(AllocTy)) {
OS << "alignof(" << *AllocTy << ")";
return;
}
const Type *CTy;
Constant *FieldNo;
if (U->isOffsetOf(CTy, FieldNo)) {
OS << "offsetof(" << *CTy << ", ";
WriteAsOperand(OS, FieldNo, false);
OS << ")";
return;
}
// Otherwise just print it normally.
WriteAsOperand(OS, U->getValue(), false);
return;
}
case scCouldNotCompute:
OS << "***COULDNOTCOMPUTE***";
return;
default: break;
}
llvm_unreachable("Unknown SCEV kind!");
}
const Type *SCEV::getType() const {
switch (getSCEVType()) {
case scConstant:
return cast<SCEVConstant>(this)->getType();
case scTruncate:
case scZeroExtend:
case scSignExtend:
return cast<SCEVCastExpr>(this)->getType();
case scAddRecExpr:
case scMulExpr:
case scUMaxExpr:
case scSMaxExpr:
return cast<SCEVNAryExpr>(this)->getType();
case scAddExpr:
return cast<SCEVAddExpr>(this)->getType();
case scUDivExpr:
return cast<SCEVUDivExpr>(this)->getType();
case scUnknown:
return cast<SCEVUnknown>(this)->getType();
case scCouldNotCompute:
llvm_unreachable("Attempt to use a SCEVCouldNotCompute object!");
return 0;
default: break;
}
llvm_unreachable("Unknown SCEV kind!");
return 0;
}
bool SCEV::isZero() const {
if (const SCEVConstant *SC = dyn_cast<SCEVConstant>(this))
return SC->getValue()->isZero();
@ -148,20 +270,6 @@ bool SCEV::isAllOnesValue() const {
SCEVCouldNotCompute::SCEVCouldNotCompute() :
SCEV(FoldingSetNodeIDRef(), scCouldNotCompute) {}
const Type *SCEVCouldNotCompute::getType() const {
llvm_unreachable("Attempt to use a SCEVCouldNotCompute object!");
return 0;
}
bool SCEVCouldNotCompute::hasOperand(const SCEV *) const {
llvm_unreachable("Attempt to use a SCEVCouldNotCompute object!");
return false;
}
void SCEVCouldNotCompute::print(raw_ostream &OS) const {
OS << "***COULDNOTCOMPUTE***";
}
bool SCEVCouldNotCompute::classof(const SCEV *S) {
return S->getSCEVType() == scCouldNotCompute;
}
@ -187,12 +295,6 @@ ScalarEvolution::getConstant(const Type *Ty, uint64_t V, bool isSigned) {
return getConstant(ConstantInt::get(ITy, V, isSigned));
}
const Type *SCEVConstant::getType() const { return V->getType(); }
void SCEVConstant::print(raw_ostream &OS) const {
WriteAsOperand(OS, V, false);
}
SCEVCastExpr::SCEVCastExpr(const FoldingSetNodeIDRef ID,
unsigned SCEVTy, const SCEV *op, const Type *ty)
: SCEV(ID, SCEVTy), Op(op), Ty(ty) {}
@ -205,10 +307,6 @@ SCEVTruncateExpr::SCEVTruncateExpr(const FoldingSetNodeIDRef ID,
"Cannot truncate non-integer value!");
}
void SCEVTruncateExpr::print(raw_ostream &OS) const {
OS << "(trunc " << *Op->getType() << " " << *Op << " to " << *Ty << ")";
}
SCEVZeroExtendExpr::SCEVZeroExtendExpr(const FoldingSetNodeIDRef ID,
const SCEV *op, const Type *ty)
: SCEVCastExpr(ID, scZeroExtend, op, ty) {
@ -217,10 +315,6 @@ SCEVZeroExtendExpr::SCEVZeroExtendExpr(const FoldingSetNodeIDRef ID,
"Cannot zero extend non-integer value!");
}
void SCEVZeroExtendExpr::print(raw_ostream &OS) const {
OS << "(zext " << *Op->getType() << " " << *Op << " to " << *Ty << ")";
}
SCEVSignExtendExpr::SCEVSignExtendExpr(const FoldingSetNodeIDRef ID,
const SCEV *op, const Type *ty)
: SCEVCastExpr(ID, scSignExtend, op, ty) {
@ -229,52 +323,6 @@ SCEVSignExtendExpr::SCEVSignExtendExpr(const FoldingSetNodeIDRef ID,
"Cannot sign extend non-integer value!");
}
void SCEVSignExtendExpr::print(raw_ostream &OS) const {
OS << "(sext " << *Op->getType() << " " << *Op << " to " << *Ty << ")";
}
void SCEVCommutativeExpr::print(raw_ostream &OS) const {
const char *OpStr = getOperationStr();
OS << "(";
for (op_iterator I = op_begin(), E = op_end(); I != E; ++I) {
OS << **I;
if (llvm::next(I) != E)
OS << OpStr;
}
OS << ")";
}
bool SCEVNAryExpr::hasOperand(const SCEV *O) const {
for (op_iterator I = op_begin(), E = op_end(); I != E; ++I) {
const SCEV *S = *I;
if (O == S || S->hasOperand(O))
return true;
}
return false;
}
void SCEVUDivExpr::print(raw_ostream &OS) const {
OS << "(" << *LHS << " /u " << *RHS << ")";
}
const Type *SCEVUDivExpr::getType() const {
// In most cases the types of LHS and RHS will be the same, but in some
// crazy cases one or the other may be a pointer. ScalarEvolution doesn't
// depend on the type for correctness, but handling types carefully can
// avoid extra casts in the SCEVExpander. The LHS is more likely to be
// a pointer type than the RHS, so use the RHS' type here.
return RHS->getType();
}
void SCEVAddRecExpr::print(raw_ostream &OS) const {
OS << "{" << *Operands[0];
for (unsigned i = 1, e = NumOperands; i != e; ++i)
OS << ",+," << *Operands[i];
OS << "}<";
WriteAsOperand(OS, L->getHeader(), /*PrintType=*/false);
OS << ">";
}
void SCEVUnknown::deleted() {
// Clear this SCEVUnknown from various maps.
SE->ValuesAtScopes.erase(this);
@ -303,10 +351,6 @@ void SCEVUnknown::allUsesReplacedWith(Value *New) {
setValPtr(New);
}
const Type *SCEVUnknown::getType() const {
return getValue()->getType();
}
bool SCEVUnknown::isSizeOf(const Type *&AllocTy) const {
if (ConstantExpr *VCE = dyn_cast<ConstantExpr>(getValue()))
if (VCE->getOpcode() == Instruction::PtrToInt)
@ -371,30 +415,6 @@ bool SCEVUnknown::isOffsetOf(const Type *&CTy, Constant *&FieldNo) const {
return false;
}
void SCEVUnknown::print(raw_ostream &OS) const {
const Type *AllocTy;
if (isSizeOf(AllocTy)) {
OS << "sizeof(" << *AllocTy << ")";
return;
}
if (isAlignOf(AllocTy)) {
OS << "alignof(" << *AllocTy << ")";
return;
}
const Type *CTy;
Constant *FieldNo;
if (isOffsetOf(CTy, FieldNo)) {
OS << "offsetof(" << *CTy << ", ";
WriteAsOperand(OS, FieldNo, false);
OS << ")";
return;
}
// Otherwise just print it normally.
WriteAsOperand(OS, getValue(), false);
}
//===----------------------------------------------------------------------===//
// SCEV Utilities
//===----------------------------------------------------------------------===//
@ -2601,7 +2621,7 @@ ScalarEvolution::ForgetSymbolicName(Instruction *PN, const SCEV *SymName) {
// Short-circuit the def-use traversal if the symbolic name
// ceases to appear in expressions.
if (Old != SymName && !Old->hasOperand(SymName))
if (Old != SymName && !hasOperand(Old, SymName))
continue;
// SCEVUnknown for a PHI either means that it has an unrecognized
@ -6092,3 +6112,45 @@ bool ScalarEvolution::properlyDominates(const SCEV *S, BasicBlock *BB) const {
llvm_unreachable("Unknown SCEV kind!");
return false;
}
bool ScalarEvolution::hasOperand(const SCEV *S, const SCEV *Op) const {
switch (S->getSCEVType()) {
case scConstant:
return false;
case scTruncate:
case scZeroExtend:
case scSignExtend: {
const SCEVCastExpr *Cast = cast<SCEVCastExpr>(S);
const SCEV *CastOp = Cast->getOperand();
return Op == CastOp || hasOperand(CastOp, Op);
}
case scAddRecExpr:
case scAddExpr:
case scMulExpr:
case scUMaxExpr:
case scSMaxExpr: {
const SCEVNAryExpr *NAry = cast<SCEVNAryExpr>(S);
for (SCEVNAryExpr::op_iterator I = NAry->op_begin(), E = NAry->op_end();
I != E; ++I) {
const SCEV *NAryOp = *I;
if (NAryOp == Op || hasOperand(NAryOp, Op))
return true;
}
return false;
}
case scUDivExpr: {
const SCEVUDivExpr *UDiv = cast<SCEVUDivExpr>(S);
const SCEV *LHS = UDiv->getLHS(), *RHS = UDiv->getRHS();
return LHS == Op || hasOperand(LHS, Op) ||
RHS == Op || hasOperand(RHS, Op);
}
case scUnknown:
return false;
case scCouldNotCompute:
llvm_unreachable("Attempt to use a SCEVCouldNotCompute object!");
return false;
default: break;
}
llvm_unreachable("Unknown SCEV kind!");
return false;
}