#include "llvm/Analysis/Dominators.h"
#include "llvm/Assembly/Writer.h"
#include "llvm/Support/CFG.h"
-#include "llvm/Support/Compiler.h"
#include "llvm/Support/ConstantRange.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/InstVisitor.h"
#ifndef NDEBUG
virtual void dump() const {
- dump(*cerr.stream());
+ dump(errs());
}
- void dump(std::ostream &os) const {
+ void dump(raw_ostream &os) const {
os << "Predicate simplifier DomTreeDFS: \n";
dump(Entry, 0, os);
os << "\n\n";
}
- void dump(Node *N, int depth, std::ostream &os) const {
+ void dump(Node *N, int depth, raw_ostream &os) const {
++depth;
for (int i = 0; i < depth; ++i) { os << " "; }
os << "[" << depth << "] ";
}
/// ValueNumbering stores the scope-specific value numbers for a given Value.
- class VISIBILITY_HIDDEN ValueNumbering {
+ class ValueNumbering {
/// VNPair is a tuple of {Value, index number, DomTreeDFS::Node}. It
/// includes the comparison operators necessary to allow you to store it
/// in a sorted vector.
- class VISIBILITY_HIDDEN VNPair {
+ class VNPair {
public:
Value *V;
unsigned index;
#ifndef NDEBUG
virtual ~ValueNumbering() {}
virtual void dump() {
- dump(*cerr.stream());
+ print(errs());
}
- void dump(std::ostream &os) {
+ void print(raw_ostream &os) {
for (unsigned i = 1; i <= Values.size(); ++i) {
os << i << " = ";
WriteAsOperand(os, Values[i-1]);
/// valueNumber - finds the value number for V under the Subtree. If
/// there is no value number, returns zero.
unsigned valueNumber(Value *V, DomTreeDFS::Node *Subtree) {
- if (!(isa<Constant>(V) || isa<Argument>(V) || isa<Instruction>(V))
- || V->getType() == Type::VoidTy) return 0;
+ if (!(isa<Constant>(V) || isa<Argument>(V) || isa<Instruction>(V)) ||
+ V->getType() == Type::getVoidTy(V->getContext())) return 0;
VNMapType::iterator E = VNMap.end();
VNPair pair(V, 0, Subtree);
unsigned newVN(Value *V) {
assert((isa<Constant>(V) || isa<Argument>(V) || isa<Instruction>(V)) &&
"Bad Value for value numbering.");
- assert(V->getType() != Type::VoidTy && "Won't value number a void value");
+ assert(V->getType() != Type::getVoidTy(V->getContext()) &&
+ "Won't value number a void value");
Values.push_back(V);
///
/// The InequalityGraph class may invalidate Node*s after any mutator call.
/// @brief The InequalityGraph stores the relationships between values.
- class VISIBILITY_HIDDEN InequalityGraph {
+ class InequalityGraph {
ValueNumbering &VN;
DomTreeDFS::Node *TreeRoot;
/// and contains a pointer to the other end. The edge contains a lattice
/// value specifying the relationship and an DomTreeDFS::Node specifying
/// the root in the dominator tree to which this edge applies.
- class VISIBILITY_HIDDEN Edge {
+ class Edge {
public:
Edge(unsigned T, LatticeVal V, DomTreeDFS::Node *ST)
: To(T), LV(V), Subtree(ST) {}
/// for the node, as well as the relationships with the neighbours.
///
/// @brief A single node in the InequalityGraph.
- class VISIBILITY_HIDDEN Node {
+ class Node {
friend class InequalityGraph;
typedef SmallVector<Edge, 4> RelationsType;
#ifndef NDEBUG
virtual ~Node() {}
virtual void dump() const {
- dump(*cerr.stream());
+ dump(errs());
}
private:
- void dump(std::ostream &os) const {
+ void dump(raw_ostream &os) const {
static const std::string names[32] =
{ "000000", "000001", "000002", "000003", "000004", "000005",
"000006", "000007", "000008", "000009", " >", " >=",
#ifndef NDEBUG
virtual ~InequalityGraph() {}
virtual void dump() {
- dump(*cerr.stream());
+ dump(errs());
}
- void dump(std::ostream &os) {
+ void dump(raw_ostream &os) {
for (unsigned i = 1; i <= Nodes.size(); ++i) {
os << i << " = {";
node(i)->dump(os);
/// ValueRanges tracks the known integer ranges and anti-ranges of the nodes
/// in the InequalityGraph.
- class VISIBILITY_HIDDEN ValueRanges {
+ class ValueRanges {
ValueNumbering &VN;
TargetData *TD;
LLVMContext *Context;
- class VISIBILITY_HIDDEN ScopedRange {
+ class ScopedRange {
typedef std::vector<std::pair<DomTreeDFS::Node *, ConstantRange> >
RangeListType;
RangeListType RangeList;
#ifndef NDEBUG
virtual ~ScopedRange() {}
virtual void dump() const {
- dump(*cerr.stream());
+ dump(errs());
}
- void dump(std::ostream &os) const {
+ void dump(raw_ostream &os) const {
os << "{";
for (const_iterator I = begin(), E = end(); I != E; ++I) {
os << &I->second << " (" << I->first->getDFSNumIn() << "), ";
virtual ~ValueRanges() {}
virtual void dump() const {
- dump(*cerr.stream());
+ dump(errs());
}
- void dump(std::ostream &os) const {
+ void dump(raw_ostream &os) const {
for (unsigned i = 0, e = Ranges.size(); i != e; ++i) {
os << (i+1) << " = ";
Ranges[i].dump(os);
/// another discovered to be unreachable. This is used to cull the graph when
/// analyzing instructions, and to mark blocks with the "unreachable"
/// terminator instruction after the function has executed.
- class VISIBILITY_HIDDEN UnreachableBlocks {
+ class UnreachableBlocks {
private:
std::vector<BasicBlock *> DeadBlocks;
TerminatorInst *TI = BB->getTerminator();
TI->replaceAllUsesWith(UndefValue::get(TI->getType()));
TI->eraseFromParent();
- new UnreachableInst(BB);
+ new UnreachableInst(BB->getContext(), BB);
++NumBlocks;
modified = true;
}
/// variables, and forwards changes along to the InequalityGraph. It
/// also maintains the correct choice for "canonical" in the IG.
/// @brief VRPSolver calculates inferences from a new relationship.
- class VISIBILITY_HIDDEN VRPSolver {
+ class VRPSolver {
private:
friend class ValueRanges;
}
bool makeEqual(Value *V1, Value *V2) {
- DOUT << "makeEqual(" << *V1 << ", " << *V2 << ")\n";
- DOUT << "context is ";
+ DEBUG(errs() << "makeEqual(" << *V1 << ", " << *V2 << ")\n");
+ DEBUG(errs() << "context is ");
DEBUG(if (TopInst)
errs() << "I: " << *TopInst << "\n";
else
ToNotify.push_back(I);
}
- DOUT << "Simply removing " << *I2
- << ", replacing with " << *V1 << "\n";
+ DEBUG(errs() << "Simply removing " << *I2
+ << ", replacing with " << *V1 << "\n");
I2->replaceAllUsesWith(V1);
// leave it dead; it'll get erased later.
++NumInstruction;
// If that killed the instruction, stop here.
if (I2 && isInstructionTriviallyDead(I2)) {
- DOUT << "Killed all uses of " << *I2
- << ", replacing with " << *V1 << "\n";
+ DEBUG(errs() << "Killed all uses of " << *I2
+ << ", replacing with " << *V1 << "\n");
continue;
}
/// add - adds a new property to the work queue
void add(Value *V1, Value *V2, ICmpInst::Predicate Pred,
Instruction *I = NULL) {
- DOUT << "adding " << *V1 << " " << Pred << " " << *V2;
- if (I) DOUT << " context: " << *I;
- else DOUT << " default context (" << Top->getDFSNumIn() << ")";
- DOUT << "\n";
+ DEBUG(errs() << "adding " << *V1 << " " << Pred << " " << *V2);
+ if (I)
+ DEBUG(errs() << " context: " << *I);
+ else
+ DEBUG(errs() << " default context (" << Top->getDFSNumIn() << ")");
+ DEBUG(errs() << "\n");
assert(V1->getType() == V2->getType() &&
"Can't relate two values with different types.");
switch (BO->getOpcode()) {
case Instruction::And: {
// "and i32 %a, %b" EQ -1 then %a EQ -1 and %b EQ -1
- ConstantInt *CI = cast<ConstantInt>(Context->getAllOnesValue(Ty));
+ ConstantInt *CI = cast<ConstantInt>(Constant::getAllOnesValue(Ty));
if (Canonical == CI) {
add(CI, Op0, ICmpInst::ICMP_EQ, NewContext);
add(CI, Op1, ICmpInst::ICMP_EQ, NewContext);
} break;
case Instruction::Or: {
// "or i32 %a, %b" EQ 0 then %a EQ 0 and %b EQ 0
- Constant *Zero = Context->getNullValue(Ty);
+ Constant *Zero = Constant::getNullValue(Ty);
if (Canonical == Zero) {
add(Zero, Op0, ICmpInst::ICMP_EQ, NewContext);
add(Zero, Op1, ICmpInst::ICMP_EQ, NewContext);
}
if (Canonical == LHS) {
if (isa<ConstantInt>(Canonical))
- add(RHS, Context->getNullValue(Ty), ICmpInst::ICMP_EQ,
+ add(RHS, Constant::getNullValue(Ty), ICmpInst::ICMP_EQ,
NewContext);
} else if (isRelatedBy(LHS, Canonical, ICmpInst::ICMP_NE)) {
- add(RHS, Context->getNullValue(Ty), ICmpInst::ICMP_NE,
+ add(RHS, Constant::getNullValue(Ty), ICmpInst::ICMP_NE,
NewContext);
}
} break;
}
// TODO: The GEPI indices are all zero. Copy from definition to operand,
// jumping the type plane as needed.
- if (isRelatedBy(GEPI, Context->getNullValue(GEPI->getType()),
+ if (isRelatedBy(GEPI, Constant::getNullValue(GEPI->getType()),
ICmpInst::ICMP_NE)) {
Value *Ptr = GEPI->getPointerOperand();
- add(Ptr, Context->getNullValue(Ptr->getType()), ICmpInst::ICMP_NE,
+ add(Ptr, Constant::getNullValue(Ptr->getType()), ICmpInst::ICMP_NE,
NewContext);
}
} else if (CastInst *CI = dyn_cast<CastInst>(I)) {
const Type *Ty = BO->getType();
assert(!Ty->isFPOrFPVector() && "Float in work queue!");
- Constant *Zero = Context->getNullValue(Ty);
+ Constant *Zero = Constant::getNullValue(Ty);
Constant *One = ConstantInt::get(Ty, 1);
- ConstantInt *AllOnes = cast<ConstantInt>(Context->getAllOnesValue(Ty));
+ ConstantInt *AllOnes = cast<ConstantInt>(Constant::getAllOnesValue(Ty));
switch (Opcode) {
default: break;
// TODO: The GEPI indices are all zero. Copy from operand to definition,
// jumping the type plane as needed.
Value *Ptr = GEPI->getPointerOperand();
- if (isRelatedBy(Ptr, Context->getNullValue(Ptr->getType()),
+ if (isRelatedBy(Ptr, Constant::getNullValue(Ptr->getType()),
ICmpInst::ICMP_NE)) {
- add(GEPI, Context->getNullValue(GEPI->getType()), ICmpInst::ICMP_NE,
+ add(GEPI, Constant::getNullValue(GEPI->getType()), ICmpInst::ICMP_NE,
NewContext);
}
}
/// solve - process the work queue
void solve() {
- //DOUT << "WorkList entry, size: " << WorkList.size() << "\n";
+ //DEBUG(errs() << "WorkList entry, size: " << WorkList.size() << "\n");
while (!WorkList.empty()) {
- //DOUT << "WorkList size: " << WorkList.size() << "\n";
+ //DEBUG(errs() << "WorkList size: " << WorkList.size() << "\n");
Operation &O = WorkList.front();
TopInst = O.ContextInst;
/// one equivalent variable with another. It also tracks what
/// can't be equal and will solve setcc instructions when possible.
/// @brief Root of the predicate simplifier optimization.
- class VISIBILITY_HIDDEN PredicateSimplifier : public FunctionPass {
+ class PredicateSimplifier : public FunctionPass {
DomTreeDFS *DTDFS;
bool modified;
ValueNumbering *VN;
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequiredID(BreakCriticalEdgesID);
AU.addRequired<DominatorTree>();
- AU.addRequired<TargetData>();
- AU.addPreserved<TargetData>();
}
private:
/// PredicateSimplifier::proceedToSuccessor(s) interface to enter the
/// basic block.
/// @brief Performs abstract execution of the program.
- class VISIBILITY_HIDDEN Forwards : public InstVisitor<Forwards> {
+ class Forwards : public InstVisitor<Forwards> {
friend class InstVisitor<Forwards>;
PredicateSimplifier *PS;
DomTreeDFS::Node *DTNode;
// Tries to simplify each Instruction and add new properties.
void visitInstruction(Instruction *I, DomTreeDFS::Node *DT) {
- DOUT << "Considering instruction " << *I << "\n";
+ DEBUG(errs() << "Considering instruction " << *I << "\n");
DEBUG(VN->dump());
DEBUG(IG->dump());
DEBUG(VR->dump());
if (V != I) {
modified = true;
++NumInstruction;
- DOUT << "Removing " << *I << ", replacing with " << *V << "\n";
+ DEBUG(errs() << "Removing " << *I << ", replacing with " << *V << "\n");
if (unsigned n = VN->valueNumber(I, DTDFS->getRootNode()))
if (VN->value(n) == I) IG->remove(n);
VN->remove(I);
if (V != Oper) {
modified = true;
++NumVarsReplaced;
- DOUT << "Resolving " << *I;
+ DEBUG(errs() << "Resolving " << *I);
I->setOperand(i, V);
- DOUT << " into " << *I;
+ DEBUG(errs() << " into " << *I);
}
}
#endif
std::string name = I->getParent()->getName();
- DOUT << "push (%" << name << ")\n";
+ DEBUG(errs() << "push (%" << name << ")\n");
Forwards visit(this, DT);
visit.visit(*I);
- DOUT << "pop (%" << name << ")\n";
+ DEBUG(errs() << "pop (%" << name << ")\n");
}
};
bool PredicateSimplifier::runOnFunction(Function &F) {
DominatorTree *DT = &getAnalysis<DominatorTree>();
DTDFS = new DomTreeDFS(DT);
- TargetData *TD = &getAnalysis<TargetData>();
+ TargetData *TD = getAnalysisIfAvailable<TargetData>();
+
+ // FIXME: PredicateSimplifier should still be able to do basic
+ // optimizations without TargetData. But for now, just exit if
+ // it's not available.
+ if (!TD) return false;
+
Context = &F.getContext();
DEBUG(errs() << "Entering Function: " << F.getName() << "\n");
void PredicateSimplifier::Forwards::visitAllocaInst(AllocaInst &AI) {
VRPSolver VRP(VN, IG, UB, VR, PS->DTDFS, PS->modified, &AI);
- VRP.add(AI.getContext().getNullValue(AI.getType()),
+ VRP.add(Constant::getNullValue(AI.getType()),
&AI, ICmpInst::ICMP_NE);
VRP.solve();
}
if (isa<Constant>(Ptr)) return;
VRPSolver VRP(VN, IG, UB, VR, PS->DTDFS, PS->modified, &LI);
- VRP.add(LI.getContext().getNullValue(Ptr->getType()),
+ VRP.add(Constant::getNullValue(Ptr->getType()),
Ptr, ICmpInst::ICMP_NE);
VRP.solve();
}
if (isa<Constant>(Ptr)) return;
VRPSolver VRP(VN, IG, UB, VR, PS->DTDFS, PS->modified, &SI);
- VRP.add(SI.getContext().getNullValue(Ptr->getType()),
+ VRP.add(Constant::getNullValue(Ptr->getType()),
Ptr, ICmpInst::ICMP_NE);
VRP.solve();
}
case Instruction::SDiv: {
Value *Divisor = BO.getOperand(1);
VRPSolver VRP(VN, IG, UB, VR, PS->DTDFS, PS->modified, &BO);
- VRP.add(BO.getContext().getNullValue(Divisor->getType()),
+ VRP.add(Constant::getNullValue(Divisor->getType()),
Divisor, ICmpInst::ICMP_NE);
VRP.solve();
break;