[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