//===- llvm/Analysis/ScalarEvolution.h - Scalar Evolution -------*- C++ -*-===//
-//
+//
// The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
+//
//===----------------------------------------------------------------------===//
//
// The ScalarEvolution class is an LLVM pass which can be used to analyze and
//
// This analysis is primarily useful for induction variable substitution and
// strength reduction.
-//
+//
//===----------------------------------------------------------------------===//
#ifndef LLVM_ANALYSIS_SCALAREVOLUTION_H
#define LLVM_ANALYSIS_SCALAREVOLUTION_H
#include "llvm/Pass.h"
+#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/Streams.h"
#include <set>
namespace llvm {
+ class APInt;
+ class ConstantInt;
class Instruction;
class Type;
class ConstantRange;
- class Loop;
- class LoopInfo;
class SCEVHandle;
+ class ScalarEvolution;
/// SCEV - This class represent an analyzed expression in the program. These
/// are reference counted opaque objects that the client is not allowed to
///
class SCEV {
const unsigned SCEVType; // The SCEV baseclass this node corresponds to
- unsigned RefCount;
+ mutable unsigned RefCount;
friend class SCEVHandle;
- void addRef() { ++RefCount; }
- void dropRef() {
+ void addRef() const { ++RefCount; }
+ void dropRef() const {
if (--RefCount == 0)
delete this;
}
protected:
virtual ~SCEV();
public:
- SCEV(unsigned SCEVTy) : SCEVType(SCEVTy), RefCount(0) {}
+ explicit SCEV(unsigned SCEVTy) : SCEVType(SCEVTy), RefCount(0) {}
unsigned getSCEVType() const { return SCEVType; }
///
virtual const Type *getType() const = 0;
+ /// getBitWidth - Get the bit width of the type, if it has one, 0 otherwise.
+ ///
+ uint32_t getBitWidth() const;
+
+ /// replaceSymbolicValuesWithConcrete - If this SCEV internally references
+ /// the symbolic value "Sym", construct and return a new SCEV that produces
+ /// the same value, but which uses the concrete value Conc instead of the
+ /// symbolic value. If this SCEV does not use the symbolic value, it
+ /// returns itself.
+ virtual SCEVHandle
+ replaceSymbolicValuesWithConcrete(const SCEVHandle &Sym,
+ const SCEVHandle &Conc,
+ ScalarEvolution &SE) 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(std::ostream &OS) const = 0;
+ void print(std::ostream *OS) const { if (OS) print(*OS); }
/// dump - This method is used for debugging.
///
void dump() const;
};
-
+
inline std::ostream &operator<<(std::ostream &OS, const SCEV &S) {
S.print(OS);
return OS;
virtual const Type *getType() const;
virtual bool hasComputableLoopEvolution(const Loop *L) const;
virtual void print(std::ostream &OS) const;
-
+ void print(std::ostream *OS) const { if (OS) print(*OS); }
+ virtual SCEVHandle
+ replaceSymbolicValuesWithConcrete(const SCEVHandle &Sym,
+ const SCEVHandle &Conc,
+ ScalarEvolution &SE) const;
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const SCEVCouldNotCompute *S) { return true; }
SCEV *S;
SCEVHandle(); // DO NOT IMPLEMENT
public:
- SCEVHandle(SCEV *s) : S(s) {
+ SCEVHandle(const SCEV *s) : S(const_cast<SCEV*>(s)) {
assert(S && "Cannot create a handle to a null SCEV!");
S->addRef();
}
SCEVHandle(const SCEVHandle &RHS) : S(RHS.S) {
- S->addRef();
+ S->addRef();
}
~SCEVHandle() { S->dropRef(); }
class ScalarEvolution : public FunctionPass {
void *Impl; // ScalarEvolution uses the pimpl pattern
public:
- ScalarEvolution() : Impl(0) {}
-
+ static char ID; // Pass identification, replacement for typeid
+ ScalarEvolution() : FunctionPass((intptr_t)&ID), Impl(0) {}
+
/// getSCEV - Return a SCEV expression handle for the full generality of the
/// specified expression.
SCEVHandle getSCEV(Value *V) const;
+ SCEVHandle getConstant(ConstantInt *V);
+ SCEVHandle getConstant(const APInt& Val);
+ SCEVHandle getTruncateExpr(const SCEVHandle &Op, const Type *Ty);
+ SCEVHandle getZeroExtendExpr(const SCEVHandle &Op, const Type *Ty);
+ SCEVHandle getSignExtendExpr(const SCEVHandle &Op, const Type *Ty);
+ SCEVHandle getAddExpr(std::vector<SCEVHandle> &Ops);
+ SCEVHandle getAddExpr(const SCEVHandle &LHS, const SCEVHandle &RHS) {
+ std::vector<SCEVHandle> Ops;
+ Ops.push_back(LHS);
+ Ops.push_back(RHS);
+ return getAddExpr(Ops);
+ }
+ SCEVHandle getAddExpr(const SCEVHandle &Op0, const SCEVHandle &Op1,
+ const SCEVHandle &Op2) {
+ std::vector<SCEVHandle> Ops;
+ Ops.push_back(Op0);
+ Ops.push_back(Op1);
+ Ops.push_back(Op2);
+ return getAddExpr(Ops);
+ }
+ SCEVHandle getMulExpr(std::vector<SCEVHandle> &Ops);
+ SCEVHandle getMulExpr(const SCEVHandle &LHS, const SCEVHandle &RHS) {
+ std::vector<SCEVHandle> Ops;
+ Ops.push_back(LHS);
+ Ops.push_back(RHS);
+ return getMulExpr(Ops);
+ }
+ SCEVHandle getSDivExpr(const SCEVHandle &LHS, const SCEVHandle &RHS);
+ SCEVHandle getAddRecExpr(const SCEVHandle &Start, const SCEVHandle &Step,
+ const Loop *L);
+ SCEVHandle getAddRecExpr(std::vector<SCEVHandle> &Operands,
+ const Loop *L);
+ SCEVHandle getAddRecExpr(const std::vector<SCEVHandle> &Operands,
+ const Loop *L) {
+ std::vector<SCEVHandle> NewOp(Operands);
+ return getAddRecExpr(NewOp, L);
+ }
+ SCEVHandle getUnknown(Value *V);
+
+ /// getNegativeSCEV - Return the SCEV object corresponding to -V.
+ ///
+ SCEVHandle getNegativeSCEV(const SCEVHandle &V);
+
+ /// getMinusSCEV - Return LHS-RHS.
+ ///
+ SCEVHandle getMinusSCEV(const SCEVHandle &LHS,
+ const SCEVHandle &RHS);
+
+ /// getIntegerSCEV - Given an integer or FP type, create a constant for the
+ /// specified signed integer value and return a SCEV for the constant.
+ SCEVHandle getIntegerSCEV(int Val, const Type *Ty);
+
+ /// hasSCEV - Return true if the SCEV for this value has already been
+ /// computed.
+ bool hasSCEV(Value *V) const;
+
+ /// setSCEV - Insert the specified SCEV into the map of current SCEVs for
+ /// the specified value.
+ void setSCEV(Value *V, const SCEVHandle &H);
+
/// getSCEVAtScope - Return a SCEV expression handle for the specified value
/// at the specified scope in the program. The L value specifies a loop
/// nest to evaluate the expression at, where null is the top-level or a
/// an analyzable loop-invariant iteration count.
bool hasLoopInvariantIterationCount(const Loop *L) const;
- /// deleteInstructionFromRecords - This method should be called by the
- /// client before it removes an instruction from the program, to make sure
+ /// deleteValueFromRecords - This method should be called by the
+ /// client before it removes a Value from the program, to make sure
/// that no dangling references are left around.
- void deleteInstructionFromRecords(Instruction *I) const;
-
- /// shouldSubstituteIndVar - Return true if we should perform induction
- /// variable substitution for this variable. This is a hack because we
- /// don't have a strength reduction pass yet. When we do we will promote
- /// all vars, because we can strength reduce them later as desired.
- bool shouldSubstituteIndVar(const SCEV *S) const;
+ void deleteValueFromRecords(Value *V) const;
virtual bool runOnFunction(Function &F);
virtual void releaseMemory();
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
- virtual void print(std::ostream &OS) const;
+ virtual void print(std::ostream &OS, const Module* = 0) const;
+ void print(std::ostream *OS, const Module* M = 0) const {
+ if (OS) print(*OS, M);
+ }
};
}