diff --git a/include/llvm/Analysis/PHITransAddr.h b/include/llvm/Analysis/PHITransAddr.h index 8257396a09f..d090dc38f1d 100644 --- a/include/llvm/Analysis/PHITransAddr.h +++ b/include/llvm/Analysis/PHITransAddr.h @@ -80,6 +80,13 @@ public: Value *PHITranslateWithInsertion(BasicBlock *CurBB, BasicBlock *PredBB, const DominatorTree &DT, SmallVectorImpl &NewInsts); + + void dump() const; + + /// Verify - Check internal consistency of this data structure. Though it + /// claims to return a bool, it actually aborts on error and always returns + /// true. + bool Verify() const; private: Value *PHITranslateSubExpr(Value *V, BasicBlock *CurBB, BasicBlock *PredBB); @@ -103,6 +110,7 @@ private: /// array that are due to the specified instruction that is about to be /// removed from the address, and add any corresponding to V. This returns V. Value *ReplaceInstWithValue(Instruction *I, Value *V); + }; } // end namespace llvm diff --git a/lib/Analysis/PHITransAddr.cpp b/lib/Analysis/PHITransAddr.cpp index edb41f7f4cc..187924f45a8 100644 --- a/lib/Analysis/PHITransAddr.cpp +++ b/lib/Analysis/PHITransAddr.cpp @@ -14,6 +14,7 @@ #include "llvm/Analysis/PHITransAddr.h" #include "llvm/Analysis/Dominators.h" #include "llvm/Analysis/InstructionSimplify.h" +#include "llvm/Support/raw_ostream.h" using namespace llvm; static bool CanPHITrans(Instruction *Inst) { @@ -32,6 +33,72 @@ static bool CanPHITrans(Instruction *Inst) { return false; } +void PHITransAddr::dump() const { + if (Addr == 0) { + errs() << "PHITransAddr: null\n"; + return; + } + errs() << "PHITransAddr: " << *Addr << "\n"; + for (unsigned i = 0, e = InstInputs.size(); i != e; ++i) + errs() << " Input #" << i << " is " << *InstInputs[i] << "\n"; +} + + +static bool VerifySubExpr(Value *Expr, + SmallVectorImpl &InstInputs) { + // If this is a non-instruction value, there is nothing to do. + Instruction *I = dyn_cast(Expr); + if (I == 0) return true; + + // If it's an instruction, it is either in Tmp or its operands recursively + // are. + SmallVectorImpl::iterator Entry = + std::find(InstInputs.begin(), InstInputs.end(), I); + if (Entry != InstInputs.end()) { + InstInputs.erase(Entry); + return true; + } + + // If it isn't in the InstInputs list it is a subexpr incorporated into the + // address. Sanity check that it is phi translatable. + if (!CanPHITrans(I)) { + errs() << "Non phi translatable instruction found in PHITransAddr, either " + "something is missing from InstInputs or CanPHITrans is wrong:\n"; + errs() << *I << '\n'; + return false; + } + + // Validate the operands of the instruction. + for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) + if (!VerifySubExpr(I->getOperand(i), InstInputs)) + return false; + + return true; +} + +/// Verify - Check internal consistency of this data structure. If the +/// structure is valid, it returns true. If invalid, it prints errors and +/// returns false. +bool PHITransAddr::Verify() const { + if (Addr == 0) return true; + + SmallVector Tmp(InstInputs.begin(), InstInputs.end()); + + if (!VerifySubExpr(Addr, Tmp)) + return false; + + if (!Tmp.empty()) { + errs() << "PHITransAddr inconsistent, contains extra instructions:\n"; + for (unsigned i = 0, e = InstInputs.size(); i != e; ++i) + errs() << " InstInput #" << i << " is " << *InstInputs[i] << "\n"; + return false; + } + + // a-ok. + return true; +} + + /// IsPotentiallyPHITranslatable - If this needs PHI translation, return true /// if we have some hope of doing it. This should be used as a filter to /// avoid calling PHITranslateValue in hopeless situations. @@ -236,7 +303,9 @@ Value *PHITransAddr::PHITranslateSubExpr(Value *V, BasicBlock *CurBB, /// CurBB to Pred, updating our state the reflect any needed changes. This /// returns true on failure and sets Addr to null. bool PHITransAddr::PHITranslateValue(BasicBlock *CurBB, BasicBlock *PredBB) { + assert(Verify() && "Invalid PHITransAddr!"); Addr = PHITranslateSubExpr(Addr, CurBB, PredBB); + assert(Verify() && "Invalid PHITransAddr!"); return Addr == 0; }