[llvm-commits] CVS: llvm/include/llvm/Analysis/ScalarEvolution.h

Chris Lattner lattner at cs.uiuc.edu
Fri Apr 2 14:44:45 PST 2004


Changes in directory llvm/include/llvm/Analysis:

ScalarEvolution.h added (r1.1)

---
Log message:

Add a new analysis


---
Diffs of the changes:  (+270 -0)

Index: llvm/include/llvm/Analysis/ScalarEvolution.h
diff -c /dev/null llvm/include/llvm/Analysis/ScalarEvolution.h:1.1
*** /dev/null	Fri Apr  2 14:23:11 2004
--- llvm/include/llvm/Analysis/ScalarEvolution.h	Fri Apr  2 14:23:00 2004
***************
*** 0 ****
--- 1,270 ----
+ //===- 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
+ // catagorize scalar expressions in loops.  It specializes in recognizing
+ // general induction variables, representing them with the abstract and opaque
+ // SCEV class.  Given this analysis, trip counts of loops and other important
+ // properties can be obtained.
+ //
+ // 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 <set>
+ 
+ namespace llvm {
+   class Instruction;
+   class Type;
+   class ConstantRange;
+   class Loop;
+   class LoopInfo;
+   class SCEVHandle;
+   class ScalarEvolutionRewriter;
+ 
+   /// SCEV - This class represent an analyzed expression in the program.  These
+   /// are reference counted opaque objects that the client is not allowed to
+   /// do much with directly.
+   ///
+   class SCEV {
+     const unsigned SCEVType;      // The SCEV baseclass this node corresponds to
+     unsigned RefCount;
+ 
+     friend class SCEVHandle;
+     void addRef() { ++RefCount; }
+     void dropRef() {
+       if (--RefCount == 0) {
+ #if 0
+         std::cerr << "DELETING: " << this << ": ";
+         print(std::cerr);
+         std::cerr << "\n";
+ #endif
+         delete this;
+       }
+     }
+ 
+     SCEV(const SCEV &);            // DO NOT IMPLEMENT
+     void operator=(const SCEV &);  // DO NOT IMPLEMENT
+   protected:
+     virtual ~SCEV();
+   public:
+     SCEV(unsigned SCEVTy) : SCEVType(SCEVTy), RefCount(0) {}
+ 
+     unsigned getSCEVType() const { return SCEVType; }
+ 
+     /// getValueRange - Return the tightest constant bounds that this value is
+     /// known to have.  This method is only valid on integer SCEV objects.
+     virtual ConstantRange getValueRange() const;
+ 
+     /// isLoopInvariant - Return true if the value of this SCEV is unchanging in
+     /// the specified loop.
+     virtual bool isLoopInvariant(const Loop *L) const = 0;
+ 
+     /// hasComputableLoopEvolution - Return true if this SCEV changes value in a
+     /// known way in the specified loop.  This property being true implies that
+     /// the value is variant in the loop AND that we can emit an expression to
+     /// compute the value of the expression at any particular loop iteration.
+     virtual bool hasComputableLoopEvolution(const Loop *L) const = 0;
+ 
+     /// getType - Return the LLVM type of this SCEV expression.
+     ///
+     virtual const Type *getType() const = 0;
+ 
+     /// expandCodeFor - Given a rewriter object, expand this SCEV into a closed
+     /// form expression and return a Value corresponding to the expression in
+     /// question.
+     virtual Value *expandCodeFor(ScalarEvolutionRewriter &SER,
+                                  Instruction *InsertPt) = 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;
+ 
+     /// 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;
+   }
+ 
+   /// SCEVCouldNotCompute - An object of this class is returned by queries that
+   /// could not be answered.  For example, if you ask for the number of
+   /// iterations of a linked-list traversal loop, you will get one of these.
+   /// None of the standard SCEV operations are valid on this class, it is just a
+   /// marker.
+   struct SCEVCouldNotCompute : public SCEV {
+     SCEVCouldNotCompute();
+ 
+     // None of these methods are valid for this object.
+     virtual bool isLoopInvariant(const Loop *L) const;
+     virtual const Type *getType() const;
+     virtual bool hasComputableLoopEvolution(const Loop *L) const;
+     virtual Value *expandCodeFor(ScalarEvolutionRewriter &, Instruction *);
+     virtual void print(std::ostream &OS) 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);
+   };
+ 
+   /// SCEVHandle - This class is used to maintain the SCEV object's refcounts,
+   /// freeing the objects when the last reference is dropped.
+   class SCEVHandle {
+     SCEV *S;
+     SCEVHandle();  // DO NOT IMPLEMENT
+   public:
+     SCEVHandle(SCEV *s) : S(s) {
+       assert(S && "Cannot create a handle to a null SCEV!");
+       S->addRef();
+     }
+     SCEVHandle(const SCEVHandle &RHS) : S(RHS.S) {
+       S->addRef();      
+     }
+     ~SCEVHandle() { S->dropRef(); }
+ 
+     operator SCEV*() const { return S; }
+ 
+     SCEV &operator*() const { return *S; }
+     SCEV *operator->() const { return S; }
+ 
+     bool operator==(SCEV *RHS) const { return S == RHS; }
+     bool operator!=(SCEV *RHS) const { return S != RHS; }
+ 
+     const SCEVHandle &operator=(SCEV *RHS) {
+       if (S != RHS) {
+         S->dropRef();
+         S = RHS;
+         S->addRef();
+       }
+       return *this;
+     }
+ 
+     const SCEVHandle &operator=(const SCEVHandle &RHS) {
+       if (S != RHS.S) {
+         S->dropRef();
+         S = RHS.S;
+         S->addRef();
+       }
+       return *this;
+     }
+   };
+ 
+   template<typename From> struct simplify_type;
+   template<> struct simplify_type<const SCEVHandle> {
+     typedef SCEV* SimpleType;
+     static SimpleType getSimplifiedValue(const SCEVHandle &Node) {
+       return Node;
+     }
+   };
+   template<> struct simplify_type<SCEVHandle>
+     : public simplify_type<const SCEVHandle> {};
+ 
+   /// ScalarEvolution - This class is the main scalar evolution driver.  Because
+   /// client code (intentionally) can't do much with the SCEV objects directly,
+   /// they must ask this class for services.
+   ///
+   class ScalarEvolution : public FunctionPass {
+     void *Impl;    // ScalarEvolution uses the pimpl pattern
+   public:
+     ScalarEvolution() : Impl(0) {}
+     
+     /// getSCEV - Return a SCEV expression handle for the full generality of the
+     /// specified expression.
+     SCEVHandle getSCEV(Value *V) const;
+ 
+     /// 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
+     /// specified loop is immediately inside of the loop.
+     ///
+     /// This method can be used to compute the exit value for a variable defined
+     /// in a loop by querying what the value will hold in the parent loop.
+     ///
+     /// If this value is not computable at this scope, a SCEVCouldNotCompute
+     /// object is returned.
+     SCEVHandle getSCEVAtScope(Value *V, const Loop *L) const;
+ 
+     /// getIterationCount - If the specified loop has a predictable iteration
+     /// count, return it, otherwise return a SCEVCouldNotCompute object.
+     SCEVHandle getIterationCount(const Loop *L) const;
+ 
+     /// hasLoopInvariantIterationCount - Return true if the specified loop has
+     /// 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
+     /// 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;
+ 
+     virtual bool runOnFunction(Function &F);
+     virtual void releaseMemory();
+     virtual void getAnalysisUsage(AnalysisUsage &AU) const;
+     virtual void print(std::ostream &OS) const;
+   };
+ 
+   /// ScalarEvolutionRewriter - This class uses information about analyze
+   /// scalars to rewrite expressions in canonical form.  This can be used for
+   /// induction variable substitution, strength reduction, or loop exit value
+   /// replacement.
+   ///
+   /// Clients should create an instance of this class when rewriting is needed,
+   /// and destroying it when finished to allow the release of the associated
+   /// memory.
+   class ScalarEvolutionRewriter {
+     ScalarEvolution &SE;
+     LoopInfo &LI;
+     std::map<SCEVHandle, Value*> InsertedExpressions;
+     std::set<Instruction*> InsertedInstructions;
+   public:
+     ScalarEvolutionRewriter(ScalarEvolution &se, LoopInfo &li)
+       : SE(se), LI(li) {}
+ 
+     /// isInsertedInstruction - Return true if the specified instruction was
+     /// inserted by the code rewriter.  If so, the client should not modify the
+     /// instruction.
+     bool isInsertedInstruction(Instruction *I) const {
+       return InsertedInstructions.count(I);
+     }
+     
+     /// GetOrInsertCanonicalInductionVariable - This method returns the
+     /// canonical induction variable of the specified type for the specified
+     /// loop (inserts one if there is none).  A canonical induction variable
+     /// starts at zero and steps by one on each iteration.
+     Value *GetOrInsertCanonicalInductionVariable(const Loop *L, const Type *Ty);
+ 
+     /// ExpandCodeFor - Insert code to directly compute the specified SCEV
+     /// expression into the program.  The inserted code is inserted into the
+     /// specified block.
+     ///
+     /// If a particular value sign is required, a type may be specified for the
+     /// result.
+     Value *ExpandCodeFor(SCEVHandle SH, Instruction *InsertPt,
+                          const Type *Ty = 0);
+   };
+ }
+ 
+ #endif





More information about the llvm-commits mailing list