00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #ifndef LLVM_ANALYSIS_SCALAREVOLUTION_EXPRESSIONS_H
00015 #define LLVM_ANALYSIS_SCALAREVOLUTION_EXPRESSIONS_H
00016
00017 #include "llvm/Analysis/ScalarEvolution.h"
00018 #include "llvm/Support/ErrorHandling.h"
00019
00020 namespace llvm {
00021 class ConstantInt;
00022 class ConstantRange;
00023 class DominatorTree;
00024
00025 enum SCEVTypes {
00026
00027
00028 scConstant, scTruncate, scZeroExtend, scSignExtend, scAddExpr, scMulExpr,
00029 scUDivExpr, scAddRecExpr, scUMaxExpr, scSMaxExpr,
00030 scUnknown, scCouldNotCompute
00031 };
00032
00033
00036 class SCEVConstant : public SCEV {
00037 friend class ScalarEvolution;
00038
00039 ConstantInt *V;
00040 SCEVConstant(const FoldingSetNodeIDRef ID, ConstantInt *v) :
00041 SCEV(ID, scConstant), V(v) {}
00042 public:
00043 ConstantInt *getValue() const { return V; }
00044
00045 virtual bool isLoopInvariant(const Loop *L) const {
00046 return true;
00047 }
00048
00049 virtual bool hasComputableLoopEvolution(const Loop *L) const {
00050 return false;
00051 }
00052
00053 virtual const Type *getType() const;
00054
00055 virtual bool hasOperand(const SCEV *) const {
00056 return false;
00057 }
00058
00059 bool dominates(BasicBlock *BB, DominatorTree *DT) const {
00060 return true;
00061 }
00062
00063 bool properlyDominates(BasicBlock *BB, DominatorTree *DT) const {
00064 return true;
00065 }
00066
00067 virtual void print(raw_ostream &OS) const;
00068
00070 static inline bool classof(const SCEVConstant *S) { return true; }
00071 static inline bool classof(const SCEV *S) {
00072 return S->getSCEVType() == scConstant;
00073 }
00074 };
00075
00076
00079 class SCEVCastExpr : public SCEV {
00080 protected:
00081 const SCEV *Op;
00082 const Type *Ty;
00083
00084 SCEVCastExpr(const FoldingSetNodeIDRef ID,
00085 unsigned SCEVTy, const SCEV *op, const Type *ty);
00086
00087 public:
00088 const SCEV *getOperand() const { return Op; }
00089 virtual const Type *getType() const { return Ty; }
00090
00091 virtual bool isLoopInvariant(const Loop *L) const {
00092 return Op->isLoopInvariant(L);
00093 }
00094
00095 virtual bool hasComputableLoopEvolution(const Loop *L) const {
00096 return Op->hasComputableLoopEvolution(L);
00097 }
00098
00099 virtual bool hasOperand(const SCEV *O) const {
00100 return Op == O || Op->hasOperand(O);
00101 }
00102
00103 virtual bool dominates(BasicBlock *BB, DominatorTree *DT) const;
00104
00105 virtual bool properlyDominates(BasicBlock *BB, DominatorTree *DT) const;
00106
00108 static inline bool classof(const SCEVCastExpr *S) { return true; }
00109 static inline bool classof(const SCEV *S) {
00110 return S->getSCEVType() == scTruncate ||
00111 S->getSCEVType() == scZeroExtend ||
00112 S->getSCEVType() == scSignExtend;
00113 }
00114 };
00115
00116
00120 class SCEVTruncateExpr : public SCEVCastExpr {
00121 friend class ScalarEvolution;
00122
00123 SCEVTruncateExpr(const FoldingSetNodeIDRef ID,
00124 const SCEV *op, const Type *ty);
00125
00126 public:
00127 virtual void print(raw_ostream &OS) const;
00128
00130 static inline bool classof(const SCEVTruncateExpr *S) { return true; }
00131 static inline bool classof(const SCEV *S) {
00132 return S->getSCEVType() == scTruncate;
00133 }
00134 };
00135
00136
00140 class SCEVZeroExtendExpr : public SCEVCastExpr {
00141 friend class ScalarEvolution;
00142
00143 SCEVZeroExtendExpr(const FoldingSetNodeIDRef ID,
00144 const SCEV *op, const Type *ty);
00145
00146 public:
00147 virtual void print(raw_ostream &OS) const;
00148
00150 static inline bool classof(const SCEVZeroExtendExpr *S) { return true; }
00151 static inline bool classof(const SCEV *S) {
00152 return S->getSCEVType() == scZeroExtend;
00153 }
00154 };
00155
00156
00160 class SCEVSignExtendExpr : public SCEVCastExpr {
00161 friend class ScalarEvolution;
00162
00163 SCEVSignExtendExpr(const FoldingSetNodeIDRef ID,
00164 const SCEV *op, const Type *ty);
00165
00166 public:
00167 virtual void print(raw_ostream &OS) const;
00168
00170 static inline bool classof(const SCEVSignExtendExpr *S) { return true; }
00171 static inline bool classof(const SCEV *S) {
00172 return S->getSCEVType() == scSignExtend;
00173 }
00174 };
00175
00176
00177
00181 class SCEVNAryExpr : public SCEV {
00182 protected:
00183
00184
00185
00186
00187 const SCEV *const *Operands;
00188 size_t NumOperands;
00189
00190 SCEVNAryExpr(const FoldingSetNodeIDRef ID,
00191 enum SCEVTypes T, const SCEV *const *O, size_t N)
00192 : SCEV(ID, T), Operands(O), NumOperands(N) {}
00193
00194 public:
00195 size_t getNumOperands() const { return NumOperands; }
00196 const SCEV *getOperand(unsigned i) const {
00197 assert(i < NumOperands && "Operand index out of range!");
00198 return Operands[i];
00199 }
00200
00201 typedef const SCEV *const *op_iterator;
00202 op_iterator op_begin() const { return Operands; }
00203 op_iterator op_end() const { return Operands + NumOperands; }
00204
00205 virtual bool isLoopInvariant(const Loop *L) const {
00206 for (unsigned i = 0, e = getNumOperands(); i != e; ++i)
00207 if (!getOperand(i)->isLoopInvariant(L)) return false;
00208 return true;
00209 }
00210
00211
00212
00213
00214 virtual bool hasComputableLoopEvolution(const Loop *L) const {
00215 bool HasVarying = false;
00216 for (unsigned i = 0, e = getNumOperands(); i != e; ++i)
00217 if (!getOperand(i)->isLoopInvariant(L)) {
00218 if (getOperand(i)->hasComputableLoopEvolution(L))
00219 HasVarying = true;
00220 else
00221 return false;
00222 }
00223 return HasVarying;
00224 }
00225
00226 virtual bool hasOperand(const SCEV *O) const {
00227 for (unsigned i = 0, e = getNumOperands(); i != e; ++i)
00228 if (O == getOperand(i) || getOperand(i)->hasOperand(O))
00229 return true;
00230 return false;
00231 }
00232
00233 bool dominates(BasicBlock *BB, DominatorTree *DT) const;
00234
00235 bool properlyDominates(BasicBlock *BB, DominatorTree *DT) const;
00236
00237 virtual const Type *getType() const { return getOperand(0)->getType(); }
00238
00239 bool hasNoUnsignedWrap() const { return SubclassData & (1 << 0); }
00240 void setHasNoUnsignedWrap(bool B) {
00241 SubclassData = (SubclassData & ~(1 << 0)) | (B << 0);
00242 }
00243 bool hasNoSignedWrap() const { return SubclassData & (1 << 1); }
00244 void setHasNoSignedWrap(bool B) {
00245 SubclassData = (SubclassData & ~(1 << 1)) | (B << 1);
00246 }
00247
00249 static inline bool classof(const SCEVNAryExpr *S) { return true; }
00250 static inline bool classof(const SCEV *S) {
00251 return S->getSCEVType() == scAddExpr ||
00252 S->getSCEVType() == scMulExpr ||
00253 S->getSCEVType() == scSMaxExpr ||
00254 S->getSCEVType() == scUMaxExpr ||
00255 S->getSCEVType() == scAddRecExpr;
00256 }
00257 };
00258
00259
00263 class SCEVCommutativeExpr : public SCEVNAryExpr {
00264 protected:
00265 SCEVCommutativeExpr(const FoldingSetNodeIDRef ID,
00266 enum SCEVTypes T, const SCEV *const *O, size_t N)
00267 : SCEVNAryExpr(ID, T, O, N) {}
00268
00269 public:
00270 virtual const char *getOperationStr() const = 0;
00271
00272 virtual void print(raw_ostream &OS) const;
00273
00275 static inline bool classof(const SCEVCommutativeExpr *S) { return true; }
00276 static inline bool classof(const SCEV *S) {
00277 return S->getSCEVType() == scAddExpr ||
00278 S->getSCEVType() == scMulExpr ||
00279 S->getSCEVType() == scSMaxExpr ||
00280 S->getSCEVType() == scUMaxExpr;
00281 }
00282 };
00283
00284
00285
00288 class SCEVAddExpr : public SCEVCommutativeExpr {
00289 friend class ScalarEvolution;
00290
00291 SCEVAddExpr(const FoldingSetNodeIDRef ID,
00292 const SCEV *const *O, size_t N)
00293 : SCEVCommutativeExpr(ID, scAddExpr, O, N) {
00294 }
00295
00296 public:
00297 virtual const char *getOperationStr() const { return " + "; }
00298
00299 virtual const Type *getType() const {
00300
00301
00302
00303 return getOperand(getNumOperands() - 1)->getType();
00304 }
00305
00307 static inline bool classof(const SCEVAddExpr *S) { return true; }
00308 static inline bool classof(const SCEV *S) {
00309 return S->getSCEVType() == scAddExpr;
00310 }
00311 };
00312
00313
00316 class SCEVMulExpr : public SCEVCommutativeExpr {
00317 friend class ScalarEvolution;
00318
00319 SCEVMulExpr(const FoldingSetNodeIDRef ID,
00320 const SCEV *const *O, size_t N)
00321 : SCEVCommutativeExpr(ID, scMulExpr, O, N) {
00322 }
00323
00324 public:
00325 virtual const char *getOperationStr() const { return " * "; }
00326
00328 static inline bool classof(const SCEVMulExpr *S) { return true; }
00329 static inline bool classof(const SCEV *S) {
00330 return S->getSCEVType() == scMulExpr;
00331 }
00332 };
00333
00334
00335
00338 class SCEVUDivExpr : public SCEV {
00339 friend class ScalarEvolution;
00340
00341 const SCEV *LHS;
00342 const SCEV *RHS;
00343 SCEVUDivExpr(const FoldingSetNodeIDRef ID, const SCEV *lhs, const SCEV *rhs)
00344 : SCEV(ID, scUDivExpr), LHS(lhs), RHS(rhs) {}
00345
00346 public:
00347 const SCEV *getLHS() const { return LHS; }
00348 const SCEV *getRHS() const { return RHS; }
00349
00350 virtual bool isLoopInvariant(const Loop *L) const {
00351 return LHS->isLoopInvariant(L) && RHS->isLoopInvariant(L);
00352 }
00353
00354 virtual bool hasComputableLoopEvolution(const Loop *L) const {
00355 return LHS->hasComputableLoopEvolution(L) &&
00356 RHS->hasComputableLoopEvolution(L);
00357 }
00358
00359 virtual bool hasOperand(const SCEV *O) const {
00360 return O == LHS || O == RHS || LHS->hasOperand(O) || RHS->hasOperand(O);
00361 }
00362
00363 bool dominates(BasicBlock *BB, DominatorTree *DT) const;
00364
00365 bool properlyDominates(BasicBlock *BB, DominatorTree *DT) const;
00366
00367 virtual const Type *getType() const;
00368
00369 void print(raw_ostream &OS) const;
00370
00372 static inline bool classof(const SCEVUDivExpr *S) { return true; }
00373 static inline bool classof(const SCEV *S) {
00374 return S->getSCEVType() == scUDivExpr;
00375 }
00376 };
00377
00378
00379
00388 class SCEVAddRecExpr : public SCEVNAryExpr {
00389 friend class ScalarEvolution;
00390
00391 const Loop *L;
00392
00393 SCEVAddRecExpr(const FoldingSetNodeIDRef ID,
00394 const SCEV *const *O, size_t N, const Loop *l)
00395 : SCEVNAryExpr(ID, scAddRecExpr, O, N), L(l) {
00396 for (size_t i = 0, e = NumOperands; i != e; ++i)
00397 assert(Operands[i]->isLoopInvariant(l) &&
00398 "Operands of AddRec must be loop-invariant!");
00399 }
00400
00401 public:
00402 const SCEV *getStart() const { return Operands[0]; }
00403 const Loop *getLoop() const { return L; }
00404
00408 const SCEV *getStepRecurrence(ScalarEvolution &SE) const {
00409 if (isAffine()) return getOperand(1);
00410 return SE.getAddRecExpr(SmallVector<const SCEV *, 3>(op_begin()+1,
00411 op_end()),
00412 getLoop());
00413 }
00414
00415 virtual bool hasComputableLoopEvolution(const Loop *QL) const {
00416 return L == QL;
00417 }
00418
00419 virtual bool isLoopInvariant(const Loop *QueryLoop) const;
00420
00421 bool dominates(BasicBlock *BB, DominatorTree *DT) const;
00422
00423 bool properlyDominates(BasicBlock *BB, DominatorTree *DT) const;
00424
00427 bool isAffine() const {
00428
00429
00430 return getNumOperands() == 2;
00431 }
00432
00436 bool isQuadratic() const {
00437 return getNumOperands() == 3;
00438 }
00439
00442 const SCEV *evaluateAtIteration(const SCEV *It, ScalarEvolution &SE) const;
00443
00450 const SCEV *getNumIterationsInRange(ConstantRange Range,
00451 ScalarEvolution &SE) const;
00452
00455 const SCEVAddRecExpr *getPostIncExpr(ScalarEvolution &SE) const {
00456 return cast<SCEVAddRecExpr>(SE.getAddExpr(this, getStepRecurrence(SE)));
00457 }
00458
00459 virtual void print(raw_ostream &OS) const;
00460
00462 static inline bool classof(const SCEVAddRecExpr *S) { return true; }
00463 static inline bool classof(const SCEV *S) {
00464 return S->getSCEVType() == scAddRecExpr;
00465 }
00466 };
00467
00468
00469
00472 class SCEVSMaxExpr : public SCEVCommutativeExpr {
00473 friend class ScalarEvolution;
00474
00475 SCEVSMaxExpr(const FoldingSetNodeIDRef ID,
00476 const SCEV *const *O, size_t N)
00477 : SCEVCommutativeExpr(ID, scSMaxExpr, O, N) {
00478
00479 setHasNoUnsignedWrap(true);
00480 setHasNoSignedWrap(true);
00481 }
00482
00483 public:
00484 virtual const char *getOperationStr() const { return " smax "; }
00485
00487 static inline bool classof(const SCEVSMaxExpr *S) { return true; }
00488 static inline bool classof(const SCEV *S) {
00489 return S->getSCEVType() == scSMaxExpr;
00490 }
00491 };
00492
00493
00494
00497 class SCEVUMaxExpr : public SCEVCommutativeExpr {
00498 friend class ScalarEvolution;
00499
00500 SCEVUMaxExpr(const FoldingSetNodeIDRef ID,
00501 const SCEV *const *O, size_t N)
00502 : SCEVCommutativeExpr(ID, scUMaxExpr, O, N) {
00503
00504 setHasNoUnsignedWrap(true);
00505 setHasNoSignedWrap(true);
00506 }
00507
00508 public:
00509 virtual const char *getOperationStr() const { return " umax "; }
00510
00512 static inline bool classof(const SCEVUMaxExpr *S) { return true; }
00513 static inline bool classof(const SCEV *S) {
00514 return S->getSCEVType() == scUMaxExpr;
00515 }
00516 };
00517
00518
00523 class SCEVUnknown : public SCEV {
00524 friend class ScalarEvolution;
00525
00526 Value *V;
00527 SCEVUnknown(const FoldingSetNodeIDRef ID, Value *v) :
00528 SCEV(ID, scUnknown), V(v) {}
00529
00530 public:
00531 Value *getValue() const { return V; }
00532
00539 bool isSizeOf(const Type *&AllocTy) const;
00540 bool isAlignOf(const Type *&AllocTy) const;
00541 bool isOffsetOf(const Type *&STy, Constant *&FieldNo) const;
00542
00543 virtual bool isLoopInvariant(const Loop *L) const;
00544 virtual bool hasComputableLoopEvolution(const Loop *QL) const {
00545 return false;
00546 }
00547
00548 virtual bool hasOperand(const SCEV *) const {
00549 return false;
00550 }
00551
00552 bool dominates(BasicBlock *BB, DominatorTree *DT) const;
00553
00554 bool properlyDominates(BasicBlock *BB, DominatorTree *DT) const;
00555
00556 virtual const Type *getType() const;
00557
00558 virtual void print(raw_ostream &OS) const;
00559
00561 static inline bool classof(const SCEVUnknown *S) { return true; }
00562 static inline bool classof(const SCEV *S) {
00563 return S->getSCEVType() == scUnknown;
00564 }
00565 };
00566
00569 template<typename SC, typename RetVal=void>
00570 struct SCEVVisitor {
00571 RetVal visit(const SCEV *S) {
00572 switch (S->getSCEVType()) {
00573 case scConstant:
00574 return ((SC*)this)->visitConstant((const SCEVConstant*)S);
00575 case scTruncate:
00576 return ((SC*)this)->visitTruncateExpr((const SCEVTruncateExpr*)S);
00577 case scZeroExtend:
00578 return ((SC*)this)->visitZeroExtendExpr((const SCEVZeroExtendExpr*)S);
00579 case scSignExtend:
00580 return ((SC*)this)->visitSignExtendExpr((const SCEVSignExtendExpr*)S);
00581 case scAddExpr:
00582 return ((SC*)this)->visitAddExpr((const SCEVAddExpr*)S);
00583 case scMulExpr:
00584 return ((SC*)this)->visitMulExpr((const SCEVMulExpr*)S);
00585 case scUDivExpr:
00586 return ((SC*)this)->visitUDivExpr((const SCEVUDivExpr*)S);
00587 case scAddRecExpr:
00588 return ((SC*)this)->visitAddRecExpr((const SCEVAddRecExpr*)S);
00589 case scSMaxExpr:
00590 return ((SC*)this)->visitSMaxExpr((const SCEVSMaxExpr*)S);
00591 case scUMaxExpr:
00592 return ((SC*)this)->visitUMaxExpr((const SCEVUMaxExpr*)S);
00593 case scUnknown:
00594 return ((SC*)this)->visitUnknown((const SCEVUnknown*)S);
00595 case scCouldNotCompute:
00596 return ((SC*)this)->visitCouldNotCompute((const SCEVCouldNotCompute*)S);
00597 default:
00598 llvm_unreachable("Unknown SCEV type!");
00599 }
00600 }
00601
00602 RetVal visitCouldNotCompute(const SCEVCouldNotCompute *S) {
00603 llvm_unreachable("Invalid use of SCEVCouldNotCompute!");
00604 return RetVal();
00605 }
00606 };
00607 }
00608
00609 #endif