[llvm-commits] [llvm] r86789 - in /llvm/trunk: include/llvm/Analysis/LazyValueInfo.h lib/Analysis/LazyValueInfo.cpp lib/Transforms/Scalar/JumpThreading.cpp

Chris Lattner sabre at nondot.org
Tue Nov 10 18:08:33 PST 2009


Author: lattner
Date: Tue Nov 10 20:08:33 2009
New Revision: 86789

URL: http://llvm.org/viewvc/llvm-project?rev=86789&view=rev
Log:
stub out some LazyValueInfo interfaces, and have JumpThreading
start using them in a trivial way when -enable-jump-threading-lvi
is passed.  enable-jump-threading-lvi will be my playground for 
awhile.

Modified:
    llvm/trunk/include/llvm/Analysis/LazyValueInfo.h
    llvm/trunk/lib/Analysis/LazyValueInfo.cpp
    llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp

Modified: llvm/trunk/include/llvm/Analysis/LazyValueInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/LazyValueInfo.h?rev=86789&r1=86788&r2=86789&view=diff

==============================================================================
--- llvm/trunk/include/llvm/Analysis/LazyValueInfo.h (original)
+++ llvm/trunk/include/llvm/Analysis/LazyValueInfo.h Tue Nov 10 20:08:33 2009
@@ -18,23 +18,44 @@
 #include "llvm/Pass.h"
 
 namespace llvm {
-
+  class Constant;
+  class TargetData;
+  class Value;
+  
 /// LazyValueInfo - This pass computes, caches, and vends lazy value constraint
 /// information.
 class LazyValueInfo : public FunctionPass {
+  class TargetData *TD;
+  void *PImpl;
 public:
   static char ID;
-  LazyValueInfo();
+  LazyValueInfo() : FunctionPass(&ID), PImpl(0) {}
 
+  /// Tristate - This is used to return yes/no/dunno results.
+  enum Tristate {
+    Unknown = -1, No = 0, Yes = 1
+  };
+  
+  
+  // Public query interface.
+  
+  
+  /// isEqual - Determine whether the specified value is known to be equal or
+  /// not-equal to the specified constant at the end of the specified block.
+  Tristate isEqual(Value *V, Constant *C, BasicBlock *BB);
+
+  /// getConstant - Determine whether the specified value is known to be a
+  /// constant at the end of the specified block.  Return null if not.
+  Constant *getConstant(Value *V, BasicBlock *BB);
+  
+  
+  // Implementation boilerplate.
+  
   virtual void getAnalysisUsage(AnalysisUsage &AU) const {
     AU.setPreservesAll();
   }
   virtual void releaseMemory();
-  
-  virtual bool runOnFunction(Function &F) {
-    // Fully lazy.
-    return false;
-  }
+  virtual bool runOnFunction(Function &F);
 };
 
 }  // end namespace llvm

Modified: llvm/trunk/lib/Analysis/LazyValueInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/LazyValueInfo.cpp?rev=86789&r1=86788&r2=86789&view=diff

==============================================================================
--- llvm/trunk/lib/Analysis/LazyValueInfo.cpp (original)
+++ llvm/trunk/lib/Analysis/LazyValueInfo.cpp Tue Nov 10 20:08:33 2009
@@ -13,6 +13,11 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/Analysis/LazyValueInfo.h"
+#include "llvm/Constants.h"
+#include "llvm/Instructions.h"
+#include "llvm/Analysis/ConstantFolding.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/ADT/PointerIntPair.h"
 using namespace llvm;
 
 char LazyValueInfo::ID = 0;
@@ -23,9 +28,119 @@
   FunctionPass *createLazyValueInfoPass() { return new LazyValueInfo(); }
 }
 
-LazyValueInfo::LazyValueInfo() : FunctionPass(&ID) {
+
+//===----------------------------------------------------------------------===//
+//                               LVILatticeVal
+//===----------------------------------------------------------------------===//
+
+/// LVILatticeVal - This is the information tracked by LazyValueInfo for each
+/// value.
+///
+/// FIXME: This is basically just for bringup, this can be made a lot more rich
+/// in the future.
+///
+namespace {
+class LVILatticeVal {
+  enum LatticeValueTy {
+    /// undefined - This LLVM Value has no known value yet.
+    undefined,
+    /// constant - This LLVM Value has a specific constant value.
+    constant,
+    /// overdefined - This instruction is not known to be constant, and we know
+    /// it has a value.
+    overdefined
+  };
+  
+  /// Val: This stores the current lattice value along with the Constant* for
+  /// the constant if this is a 'constant' value.
+  PointerIntPair<Constant *, 2, LatticeValueTy> Val;
+  
+public:
+  LVILatticeVal() : Val(0, undefined) {}
+
+  bool isUndefined() const   { return Val.getInt() == undefined; }
+  bool isConstant() const    { return Val.getInt() == constant; }
+  bool isOverdefined() const { return Val.getInt() == overdefined; }
+  
+  Constant *getConstant() const {
+    assert(isConstant() && "Cannot get the constant of a non-constant!");
+    return Val.getPointer();
+  }
+  
+  /// getConstantInt - If this is a constant with a ConstantInt value, return it
+  /// otherwise return null.
+  ConstantInt *getConstantInt() const {
+    if (isConstant())
+      return dyn_cast<ConstantInt>(getConstant());
+    return 0;
+  }
+  
+  /// markOverdefined - Return true if this is a change in status.
+  bool markOverdefined() {
+    if (isOverdefined())
+      return false;
+    Val.setInt(overdefined);
+    return true;
+  }
+
+  /// markConstant - Return true if this is a change in status.
+  bool markConstant(Constant *V) {
+    if (isConstant()) {
+      assert(getConstant() == V && "Marking constant with different value");
+      return false;
+    }
+    
+    assert(isUndefined());
+    Val.setInt(constant);
+    assert(V && "Marking constant with NULL");
+    Val.setPointer(V);
+  }
+  
+};
+  
+} // end anonymous namespace.
+
+
+//===----------------------------------------------------------------------===//
+//                            LazyValueInfo Impl
+//===----------------------------------------------------------------------===//
+
+bool LazyValueInfo::runOnFunction(Function &F) {
+  TD = getAnalysisIfAvailable<TargetData>();
+  // Fully lazy.
+  return false;
 }
 
 void LazyValueInfo::releaseMemory() {
+  // No caching yet.
+}
+
+
+/// isEqual - Determine whether the specified value is known to be equal or
+/// not-equal to the specified constant at the end of the specified block.
+LazyValueInfo::Tristate
+LazyValueInfo::isEqual(Value *V, Constant *C, BasicBlock *BB) {
+  // If already a constant, we can use constant folding.
+  if (Constant *VC = dyn_cast<Constant>(V)) {
+    // Ignore FP for now.  TODO, consider what form of equality we want.
+    if (C->getType()->isFPOrFPVector())
+      return Unknown;
+    
+    Constant *Res = ConstantFoldCompareInstOperands(ICmpInst::ICMP_EQ, VC,C,TD);
+    if (ConstantInt *ResCI = dyn_cast<ConstantInt>(Res))
+      return ResCI->isZero() ? No : Yes;
+  }
   
+  // Not a very good implementation.
+  return Unknown;
 }
+
+Constant *LazyValueInfo::getConstant(Value *V, BasicBlock *BB) {
+  // If already a constant, return it.
+  if (Constant *VC = dyn_cast<Constant>(V))
+    return VC;
+    
+  // Not a very good implementation.
+  return 0;
+}
+

Modified: llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp?rev=86789&r1=86788&r2=86789&view=diff

==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp Tue Nov 10 20:08:33 2009
@@ -17,6 +17,7 @@
 #include "llvm/LLVMContext.h"
 #include "llvm/Pass.h"
 #include "llvm/Analysis/InstructionSimplify.h"
+#include "llvm/Analysis/LazyValueInfo.h"
 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
 #include "llvm/Transforms/Utils/Local.h"
 #include "llvm/Transforms/Utils/SSAUpdater.h"
@@ -40,6 +41,12 @@
           cl::desc("Max block size to duplicate for jump threading"),
           cl::init(6), cl::Hidden);
 
+// Turn on use of LazyValueInfo.
+static cl::opt<bool>
+EnableLVI("enable-jump-threading-lvi", cl::ReallyHidden);
+
+
+
 namespace {
   /// This pass performs 'jump threading', which looks at blocks that have
   /// multiple predecessors and multiple successors.  If one or more of the
@@ -59,6 +66,7 @@
   ///
   class JumpThreading : public FunctionPass {
     TargetData *TD;
+    LazyValueInfo *LVI;
 #ifdef NDEBUG
     SmallPtrSet<BasicBlock*, 16> LoopHeaders;
 #else
@@ -69,8 +77,13 @@
     JumpThreading() : FunctionPass(&ID) {}
 
     bool runOnFunction(Function &F);
-    void FindLoopHeaders(Function &F);
     
+    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+      if (EnableLVI)
+        AU.addRequired<LazyValueInfo>();
+    }
+    
+    void FindLoopHeaders(Function &F);
     bool ProcessBlock(BasicBlock *BB);
     bool ThreadEdge(BasicBlock *BB, const SmallVectorImpl<BasicBlock*> &PredBBs,
                     BasicBlock *SuccBB);
@@ -106,6 +119,7 @@
 bool JumpThreading::runOnFunction(Function &F) {
   DEBUG(errs() << "Jump threading on function '" << F.getName() << "'\n");
   TD = getAnalysisIfAvailable<TargetData>();
+  LVI = EnableLVI ? &getAnalysis<LazyValueInfo>() : 0;
   
   FindLoopHeaders(F);
   
@@ -235,31 +249,48 @@
 /// predecessors.  If so, return the known list of value and pred BB in the
 /// result vector.  If a value is known to be undef, it is returned as null.
 ///
-/// The BB basic block is known to start with a PHI node.
-///
 /// This returns true if there were any known values.
 ///
-///
-/// TODO: Per PR2563, we could infer value range information about a predecessor
-/// based on its terminator.
 bool JumpThreading::
 ComputeValueKnownInPredecessors(Value *V, BasicBlock *BB,PredValueInfo &Result){
-  PHINode *TheFirstPHI = cast<PHINode>(BB->begin());
-  
   // If V is a constantint, then it is known in all predecessors.
   if (isa<ConstantInt>(V) || isa<UndefValue>(V)) {
     ConstantInt *CI = dyn_cast<ConstantInt>(V);
-    Result.resize(TheFirstPHI->getNumIncomingValues());
-    for (unsigned i = 0, e = Result.size(); i != e; ++i)
-      Result[i] = std::make_pair(CI, TheFirstPHI->getIncomingBlock(i));
+    
+    for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI)
+      Result.push_back(std::make_pair(CI, *PI));
     return true;
   }
   
   // If V is a non-instruction value, or an instruction in a different block,
   // then it can't be derived from a PHI.
   Instruction *I = dyn_cast<Instruction>(V);
-  if (I == 0 || I->getParent() != BB)
+  if (I == 0 || I->getParent() != BB) {
+    
+    // Okay, if this is a live-in value, see if it has a known value at the end
+    // of any of our predecessors.
+    //
+    // FIXME: This should be an edge property, not a block end property.
+    /// TODO: Per PR2563, we could infer value range information about a
+    /// predecessor based on its terminator.
+    //
+    if (LVI) {
+      for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI) {
+        // If the value is known by LazyValueInfo to be a constant in a
+        // predecessor, use that information to try to thread this block.
+        Constant *PredCst = LVI->getConstant(V, *PI);
+        if (PredCst == 0 ||
+            (!isa<ConstantInt>(PredCst) && !isa<UndefValue>(PredCst)))
+          continue;
+        
+        Result.push_back(std::make_pair(dyn_cast<ConstantInt>(PredCst), *PI));
+      }
+      
+      return !Result.empty();
+    }
+    
     return false;
+  }
   
   /// If I is a PHI node, then we know the incoming values for any constants.
   if (PHINode *PN = dyn_cast<PHINode>(I)) {
@@ -517,12 +548,8 @@
   // a PHI node in the current block.  If we can prove that any predecessors
   // compute a predictable value based on a PHI node, thread those predecessors.
   //
-  // We only bother doing this if the current block has a PHI node and if the
-  // conditional instruction lives in the current block.  If either condition
-  // fails, this won't be a computable value anyway.
-  if (CondInst->getParent() == BB && isa<PHINode>(BB->front()))
-    if (ProcessThreadableEdges(CondInst, BB))
-      return true;
+  if (ProcessThreadableEdges(CondInst, BB))
+    return true;
   
   
   // TODO: If we have: "br (X > 0)"  and we have a predecessor where we know





More information about the llvm-commits mailing list