X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTransforms%2FScalar%2FPredicateSimplifier.cpp;h=24707bd4d86722a6296c7a529359967bc1f7b3bf;hb=333c40096561218bc3597cf153c0a3895274414c;hp=8805deeda085eee4759c4c52cf410b5a20086d7c;hpb=f3a9e368f68d9a9a64f8f35d4e2c03469d515bde;p=oota-llvm.git diff --git a/lib/Transforms/Scalar/PredicateSimplifier.cpp b/lib/Transforms/Scalar/PredicateSimplifier.cpp index 8805deeda08..24707bd4d86 100644 --- a/lib/Transforms/Scalar/PredicateSimplifier.cpp +++ b/lib/Transforms/Scalar/PredicateSimplifier.cpp @@ -2,8 +2,8 @@ // // The LLVM Compiler Infrastructure // -// This file was developed by Nick Lewycky and is distributed under the -// University of Illinois Open Source License. See LICENSE.TXT for details. +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // @@ -70,8 +70,7 @@ // // The ValueRanges class stores the known integer bounds of a Value. When we // encounter i8 %a u< %b, the ValueRanges stores that %a = [1, 255] and -// %b = [0, 254]. Because we store these by Value*, you should always -// canonicalize through the InequalityGraph first. +// %b = [0, 254]. // // It never stores an empty range, because that means that the code is // unreachable. It never stores a single-element range since that's an equality @@ -92,7 +91,7 @@ #include "llvm/ADT/Statistic.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Analysis/Dominators.h" -#include "llvm/Analysis/ET-Forest.h" +#include "llvm/Assembly/Writer.h" #include "llvm/Support/CFG.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ConstantRange.h" @@ -102,7 +101,7 @@ #include "llvm/Transforms/Utils/Local.h" #include #include -#include +#include using namespace llvm; STATISTIC(NumVarsReplaced, "Number of argument substitutions"); @@ -111,7 +110,198 @@ STATISTIC(NumSimple , "Number of simple replacements"); STATISTIC(NumBlocks , "Number of blocks marked unreachable"); STATISTIC(NumSnuggle , "Number of comparisons snuggled"); +static const ConstantRange empty(1, false); + namespace { + class DomTreeDFS { + public: + class Node { + friend class DomTreeDFS; + public: + typedef std::vector::iterator iterator; + typedef std::vector::const_iterator const_iterator; + + unsigned getDFSNumIn() const { return DFSin; } + unsigned getDFSNumOut() const { return DFSout; } + + BasicBlock *getBlock() const { return BB; } + + iterator begin() { return Children.begin(); } + iterator end() { return Children.end(); } + + const_iterator begin() const { return Children.begin(); } + const_iterator end() const { return Children.end(); } + + bool dominates(const Node *N) const { + return DFSin <= N->DFSin && DFSout >= N->DFSout; + } + + bool DominatedBy(const Node *N) const { + return N->dominates(this); + } + + /// Sorts by the number of descendants. With this, you can iterate + /// through a sorted list and the first matching entry is the most + /// specific match for your basic block. The order provided is stable; + /// DomTreeDFS::Nodes with the same number of descendants are sorted by + /// DFS in number. + bool operator<(const Node &N) const { + unsigned spread = DFSout - DFSin; + unsigned N_spread = N.DFSout - N.DFSin; + if (spread == N_spread) return DFSin < N.DFSin; + return spread < N_spread; + } + bool operator>(const Node &N) const { return N < *this; } + + private: + unsigned DFSin, DFSout; + BasicBlock *BB; + + std::vector Children; + }; + + // XXX: this may be slow. Instead of using "new" for each node, consider + // putting them in a vector to keep them contiguous. + explicit DomTreeDFS(DominatorTree *DT) { + std::stack > S; + + Entry = new Node; + Entry->BB = DT->getRootNode()->getBlock(); + S.push(std::make_pair(Entry, DT->getRootNode())); + + NodeMap[Entry->BB] = Entry; + + while (!S.empty()) { + std::pair &Pair = S.top(); + Node *N = Pair.first; + DomTreeNode *DTNode = Pair.second; + S.pop(); + + for (DomTreeNode::iterator I = DTNode->begin(), E = DTNode->end(); + I != E; ++I) { + Node *NewNode = new Node; + NewNode->BB = (*I)->getBlock(); + N->Children.push_back(NewNode); + S.push(std::make_pair(NewNode, *I)); + + NodeMap[NewNode->BB] = NewNode; + } + } + + renumber(); + +#ifndef NDEBUG + DEBUG(dump()); +#endif + } + +#ifndef NDEBUG + virtual +#endif + ~DomTreeDFS() { + std::stack S; + + S.push(Entry); + while (!S.empty()) { + Node *N = S.top(); S.pop(); + + for (Node::iterator I = N->begin(), E = N->end(); I != E; ++I) + S.push(*I); + + delete N; + } + } + + /// getRootNode - This returns the entry node for the CFG of the function. + Node *getRootNode() const { return Entry; } + + /// getNodeForBlock - return the node for the specified basic block. + Node *getNodeForBlock(BasicBlock *BB) const { + if (!NodeMap.count(BB)) return 0; + return const_cast(this)->NodeMap[BB]; + } + + /// dominates - returns true if the basic block for I1 dominates that of + /// the basic block for I2. If the instructions belong to the same basic + /// block, the instruction first instruction sequentially in the block is + /// considered dominating. + bool dominates(Instruction *I1, Instruction *I2) { + BasicBlock *BB1 = I1->getParent(), + *BB2 = I2->getParent(); + if (BB1 == BB2) { + if (isa(I1)) return false; + if (isa(I2)) return true; + if ( isa(I1) && !isa(I2)) return true; + if (!isa(I1) && isa(I2)) return false; + + for (BasicBlock::const_iterator I = BB2->begin(), E = BB2->end(); + I != E; ++I) { + if (&*I == I1) return true; + else if (&*I == I2) return false; + } + assert(!"Instructions not found in parent BasicBlock?"); + } else { + Node *Node1 = getNodeForBlock(BB1), + *Node2 = getNodeForBlock(BB2); + return Node1 && Node2 && Node1->dominates(Node2); + } + return false; // Not reached + } + + private: + /// renumber - calculates the depth first search numberings and applies + /// them onto the nodes. + void renumber() { + std::stack > S; + unsigned n = 0; + + Entry->DFSin = ++n; + S.push(std::make_pair(Entry, Entry->begin())); + + while (!S.empty()) { + std::pair &Pair = S.top(); + Node *N = Pair.first; + Node::iterator &I = Pair.second; + + if (I == N->end()) { + N->DFSout = ++n; + S.pop(); + } else { + Node *Next = *I++; + Next->DFSin = ++n; + S.push(std::make_pair(Next, Next->begin())); + } + } + } + +#ifndef NDEBUG + virtual void dump() const { + dump(*cerr.stream()); + } + + void dump(std::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 { + ++depth; + for (int i = 0; i < depth; ++i) { os << " "; } + os << "[" << depth << "] "; + + os << N->getBlock()->getName() << " (" << N->getDFSNumIn() + << ", " << N->getDFSNumOut() << ")\n"; + + for (Node::iterator I = N->begin(), E = N->end(); I != E; ++I) + dump(*I, depth, os); + } +#endif + + Node *Entry; + std::map NodeMap; + }; + // SLT SGT ULT UGT EQ // 0 1 0 1 0 -- GT 10 // 0 1 0 1 1 -- GE 11 @@ -153,6 +343,9 @@ namespace { UGE = UGT | EQ_BIT }; +#ifndef NDEBUG + /// validPredicate - determines whether a given value is actually a lattice + /// value. Only used in assertions or debugging. static bool validPredicate(LatticeVal LV) { switch (LV) { case GT: case GE: case LT: case LE: case NE: @@ -165,6 +358,7 @@ namespace { return false; } } +#endif /// reversePredicate - reverse the direction of the inequality static LatticeVal reversePredicate(LatticeVal LV) { @@ -181,17 +375,211 @@ namespace { return Rev; } - /// This is a StrictWeakOrdering predicate that sorts ETNodes by how many - /// descendants they have. With this, you can iterate through a list sorted - /// by this operation and the first matching entry is the most specific - /// match for your basic block. The order provided is stable; ETNodes with - /// the same number of children are sorted by pointer address. - struct VISIBILITY_HIDDEN OrderByDominance { - bool operator()(const ETNode *LHS, const ETNode *RHS) const { - unsigned LHS_spread = LHS->getDFSNumOut() - LHS->getDFSNumIn(); - unsigned RHS_spread = RHS->getDFSNumOut() - RHS->getDFSNumIn(); - if (LHS_spread != RHS_spread) return LHS_spread < RHS_spread; - else return LHS < RHS; + /// ValueNumbering stores the scope-specific value numbers for a given Value. + class VISIBILITY_HIDDEN 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 { + public: + Value *V; + unsigned index; + DomTreeDFS::Node *Subtree; + + VNPair(Value *V, unsigned index, DomTreeDFS::Node *Subtree) + : V(V), index(index), Subtree(Subtree) {} + + bool operator==(const VNPair &RHS) const { + return V == RHS.V && Subtree == RHS.Subtree; + } + + bool operator<(const VNPair &RHS) const { + if (V != RHS.V) return V < RHS.V; + return *Subtree < *RHS.Subtree; + } + + bool operator<(Value *RHS) const { + return V < RHS; + } + + bool operator>(Value *RHS) const { + return V > RHS; + } + + friend bool operator<(Value *RHS, const VNPair &pair) { + return pair.operator>(RHS); + } + }; + + typedef std::vector VNMapType; + VNMapType VNMap; + + /// The canonical choice for value number at index. + std::vector Values; + + DomTreeDFS *DTDFS; + + public: +#ifndef NDEBUG + virtual ~ValueNumbering() {} + virtual void dump() { + dump(*cerr.stream()); + } + + void dump(std::ostream &os) { + for (unsigned i = 1; i <= Values.size(); ++i) { + os << i << " = "; + WriteAsOperand(os, Values[i-1]); + os << " {"; + for (unsigned j = 0; j < VNMap.size(); ++j) { + if (VNMap[j].index == i) { + WriteAsOperand(os, VNMap[j].V); + os << " (" << VNMap[j].Subtree->getDFSNumIn() << ") "; + } + } + os << "}\n"; + } + } +#endif + + /// compare - returns true if V1 is a better canonical value than V2. + bool compare(Value *V1, Value *V2) const { + if (isa(V1)) + return !isa(V2); + else if (isa(V2)) + return false; + else if (isa(V1)) + return !isa(V2); + else if (isa(V2)) + return false; + + Instruction *I1 = dyn_cast(V1); + Instruction *I2 = dyn_cast(V2); + + if (!I1 || !I2) + return V1->getNumUses() < V2->getNumUses(); + + return DTDFS->dominates(I1, I2); + } + + ValueNumbering(DomTreeDFS *DTDFS) : DTDFS(DTDFS) {} + + /// 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(V) || isa(V) || isa(V)) + || V->getType() == Type::VoidTy) return 0; + + VNMapType::iterator E = VNMap.end(); + VNPair pair(V, 0, Subtree); + VNMapType::iterator I = std::lower_bound(VNMap.begin(), E, pair); + while (I != E && I->V == V) { + if (I->Subtree->dominates(Subtree)) + return I->index; + ++I; + } + return 0; + } + + /// getOrInsertVN - always returns a value number, creating it if necessary. + unsigned getOrInsertVN(Value *V, DomTreeDFS::Node *Subtree) { + if (unsigned n = valueNumber(V, Subtree)) + return n; + else + return newVN(V); + } + + /// newVN - creates a new value number. Value V must not already have a + /// value number assigned. + unsigned newVN(Value *V) { + assert((isa(V) || isa(V) || isa(V)) && + "Bad Value for value numbering."); + assert(V->getType() != Type::VoidTy && "Won't value number a void value"); + + Values.push_back(V); + + VNPair pair = VNPair(V, Values.size(), DTDFS->getRootNode()); + VNMapType::iterator I = std::lower_bound(VNMap.begin(), VNMap.end(), pair); + assert((I == VNMap.end() || value(I->index) != V) && + "Attempt to create a duplicate value number."); + VNMap.insert(I, pair); + + return Values.size(); + } + + /// value - returns the Value associated with a value number. + Value *value(unsigned index) const { + assert(index != 0 && "Zero index is reserved for not found."); + assert(index <= Values.size() && "Index out of range."); + return Values[index-1]; + } + + /// canonicalize - return a Value that is equal to V under Subtree. + Value *canonicalize(Value *V, DomTreeDFS::Node *Subtree) { + if (isa(V)) return V; + + if (unsigned n = valueNumber(V, Subtree)) + return value(n); + else + return V; + } + + /// addEquality - adds that value V belongs to the set of equivalent + /// values defined by value number n under Subtree. + void addEquality(unsigned n, Value *V, DomTreeDFS::Node *Subtree) { + assert(canonicalize(value(n), Subtree) == value(n) && + "Node's 'canonical' choice isn't best within this subtree."); + + // Suppose that we are given "%x -> node #1 (%y)". The problem is that + // we may already have "%z -> node #2 (%x)" somewhere above us in the + // graph. We need to find those edges and add "%z -> node #1 (%y)" + // to keep the lookups canonical. + + std::vector ToRepoint(1, V); + + if (unsigned Conflict = valueNumber(V, Subtree)) { + for (VNMapType::iterator I = VNMap.begin(), E = VNMap.end(); + I != E; ++I) { + if (I->index == Conflict && I->Subtree->dominates(Subtree)) + ToRepoint.push_back(I->V); + } + } + + for (std::vector::iterator VI = ToRepoint.begin(), + VE = ToRepoint.end(); VI != VE; ++VI) { + Value *V = *VI; + + VNPair pair(V, n, Subtree); + VNMapType::iterator B = VNMap.begin(), E = VNMap.end(); + VNMapType::iterator I = std::lower_bound(B, E, pair); + if (I != E && I->V == V && I->Subtree == Subtree) + I->index = n; // Update best choice + else + VNMap.insert(I, pair); // New Value + + // XXX: we currently don't have to worry about updating values with + // more specific Subtrees, but we will need to for PHI node support. + +#ifndef NDEBUG + Value *V_n = value(n); + if (isa(V) && isa(V_n)) { + assert(V == V_n && "Constant equals different constant?"); + } +#endif + } + } + + /// remove - removes all references to value V. + void remove(Value *V) { + VNMapType::iterator B = VNMap.begin(), E = VNMap.end(); + VNPair pair(V, 0, DTDFS->getRootNode()); + VNMapType::iterator J = std::upper_bound(B, E, pair); + VNMapType::iterator I = J; + + while (I != B && (I == E || I->V == V)) --I; + + VNMap.erase(I, J); } }; @@ -203,35 +591,46 @@ namespace { /// The InequalityGraph class may invalidate Node*s after any mutator call. /// @brief The InequalityGraph stores the relationships between values. class VISIBILITY_HIDDEN InequalityGraph { - ETNode *TreeRoot; + ValueNumbering &VN; + DomTreeDFS::Node *TreeRoot; InequalityGraph(); // DO NOT IMPLEMENT InequalityGraph(InequalityGraph &); // DO NOT IMPLEMENT public: - explicit InequalityGraph(ETNode *TreeRoot) : TreeRoot(TreeRoot) {} + InequalityGraph(ValueNumbering &VN, DomTreeDFS::Node *TreeRoot) + : VN(VN), TreeRoot(TreeRoot) {} class Node; /// An Edge is contained inside a Node making one end of the edge implicit /// and contains a pointer to the other end. The edge contains a lattice - /// value specifying the relationship and an ETNode specifying the root - /// in the dominator tree to which this edge applies. + /// value specifying the relationship and an DomTreeDFS::Node specifying + /// the root in the dominator tree to which this edge applies. class VISIBILITY_HIDDEN Edge { public: - Edge(unsigned T, LatticeVal V, ETNode *ST) + Edge(unsigned T, LatticeVal V, DomTreeDFS::Node *ST) : To(T), LV(V), Subtree(ST) {} unsigned To; LatticeVal LV; - ETNode *Subtree; + DomTreeDFS::Node *Subtree; bool operator<(const Edge &edge) const { if (To != edge.To) return To < edge.To; - else return OrderByDominance()(Subtree, edge.Subtree); + return *Subtree < *edge.Subtree; } + bool operator<(unsigned to) const { return To < to; } + + bool operator>(unsigned to) const { + return To > to; + } + + friend bool operator<(unsigned to, const Edge &edge) { + return edge.operator>(to); + } }; /// A single node in the InequalityGraph. This stores the canonical Value @@ -244,8 +643,6 @@ namespace { typedef SmallVector RelationsType; RelationsType Relations; - Value *Canonical; - // TODO: can this idea improve performance? //friend class std::vector; //Node(Node &N) { RelationsType.swap(N.RelationsType); } @@ -254,39 +651,34 @@ namespace { typedef RelationsType::iterator iterator; typedef RelationsType::const_iterator const_iterator; - Node(Value *V) : Canonical(V) {} - - private: #ifndef NDEBUG - public: virtual ~Node() {} virtual void dump() const { dump(*cerr.stream()); } private: - void dump(std::ostream &os) const { - os << *getValue() << ":\n"; + void dump(std::ostream &os) const { + static const std::string names[32] = + { "000000", "000001", "000002", "000003", "000004", "000005", + "000006", "000007", "000008", "000009", " >", " >=", + " s>u<", "s>=u<=", " s>", " s>=", "000016", "000017", + " s", "s<=u>=", " <", " <=", " s<", " s<=", + "000024", "000025", " u>", " u>=", " u<", " u<=", + " !=", "000031" }; for (Node::const_iterator NI = begin(), NE = end(); NI != NE; ++NI) { - static const std::string names[32] = - { "000000", "000001", "000002", "000003", "000004", "000005", - "000006", "000007", "000008", "000009", " >", " >=", - " s>u<", "s>=u<=", " s>", " s>=", "000016", "000017", - " s", "s<=u>=", " <", " <=", " s<", " s<=", - "000024", "000025", " u>", " u>=", " u<", " u<=", - " !=", "000031" }; - os << " " << names[NI->LV] << " " << NI->To - << " (" << NI->Subtree->getDFSNumIn() << ")\n"; + os << names[NI->LV] << " " << NI->To + << " (" << NI->Subtree->getDFSNumIn() << "), "; } } + public: #endif - public: iterator begin() { return Relations.begin(); } iterator end() { return Relations.end(); } const_iterator begin() const { return Relations.begin(); } const_iterator end() const { return Relations.end(); } - iterator find(unsigned n, ETNode *Subtree) { + iterator find(unsigned n, DomTreeDFS::Node *Subtree) { iterator E = end(); for (iterator I = std::lower_bound(begin(), E, n); I != E && I->To == n; ++I) { @@ -296,7 +688,7 @@ namespace { return E; } - const_iterator find(unsigned n, ETNode *Subtree) const { + const_iterator find(unsigned n, DomTreeDFS::Node *Subtree) const { const_iterator E = end(); for (const_iterator I = std::lower_bound(begin(), E, n); I != E && I->To == n; ++I) { @@ -306,136 +698,65 @@ namespace { return E; } - Value *getValue() const - { - return Canonical; - } - - /// Updates the lattice value for a given node. Create a new entry if - /// one doesn't exist, otherwise it merges the values. The new lattice - /// value must not be inconsistent with any previously existing value. - void update(unsigned n, LatticeVal R, ETNode *Subtree) { + /// update - updates the lattice value for a given node, creating a new + /// entry if one doesn't exist. The new lattice value must not be + /// inconsistent with any previously existing value. + void update(unsigned n, LatticeVal R, DomTreeDFS::Node *Subtree) { assert(validPredicate(R) && "Invalid predicate."); - iterator I = find(n, Subtree); - if (I == end()) { - Edge edge(n, R, Subtree); - iterator Insert = std::lower_bound(begin(), end(), edge); - Relations.insert(Insert, edge); - } else { - LatticeVal LV = static_cast(I->LV & R); - assert(validPredicate(LV) && "Invalid union of lattice values."); - if (LV != I->LV) { - if (Subtree != I->Subtree) { - assert(Subtree->DominatedBy(I->Subtree) && - "Find returned subtree that doesn't apply."); - - Edge edge(n, R, Subtree); - iterator Insert = std::lower_bound(begin(), end(), edge); - Relations.insert(Insert, edge); // invalidates I - I = find(n, Subtree); - } - // Also, we have to tighten any edge that Subtree dominates. - for (iterator B = begin(); I->To == n; --I) { - if (I->Subtree->DominatedBy(Subtree)) { - LatticeVal LV = static_cast(I->LV & R); - assert(validPredicate(LV) && "Invalid union of lattice values."); - I->LV = LV; - } - if (I == B) break; - } - } - } - } - }; + Edge edge(n, R, Subtree); + iterator B = begin(), E = end(); + iterator I = std::lower_bound(B, E, edge); - private: - struct VISIBILITY_HIDDEN NodeMapEdge { - Value *V; - unsigned index; - ETNode *Subtree; + iterator J = I; + while (J != E && J->To == n) { + if (Subtree->DominatedBy(J->Subtree)) + break; + ++J; + } - NodeMapEdge(Value *V, unsigned index, ETNode *Subtree) - : V(V), index(index), Subtree(Subtree) {} + if (J != E && J->To == n) { + edge.LV = static_cast(J->LV & R); + assert(validPredicate(edge.LV) && "Invalid union of lattice values."); - bool operator==(const NodeMapEdge &RHS) const { - return V == RHS.V && - Subtree == RHS.Subtree; - } + if (edge.LV == J->LV) + return; // This update adds nothing new. + } - bool operator<(const NodeMapEdge &RHS) const { - if (V != RHS.V) return V < RHS.V; - return OrderByDominance()(Subtree, RHS.Subtree); - } + if (I != B) { + // We also have to tighten any edge beneath our update. + for (iterator K = I - 1; K->To == n; --K) { + if (K->Subtree->DominatedBy(Subtree)) { + LatticeVal LV = static_cast(K->LV & edge.LV); + assert(validPredicate(LV) && "Invalid union of lattice values"); + K->LV = LV; + } + if (K == B) break; + } + } - bool operator<(Value *RHS) const { - return V < RHS; + // Insert new edge at Subtree if it isn't already there. + if (I == E || I->To != n || Subtree != I->Subtree) + Relations.insert(I, edge); } }; - typedef std::vector NodeMapType; - NodeMapType NodeMap; + private: std::vector Nodes; public: - /// node - returns the node object at a given index retrieved from getNode. - /// Index zero is reserved and may not be passed in here. The pointer - /// returned is valid until the next call to newNode or getOrInsertNode. + /// node - returns the node object at a given value number. The pointer + /// returned may be invalidated on the next call to node(). Node *node(unsigned index) { - assert(index != 0 && "Zero index is reserved for not found."); - assert(index <= Nodes.size() && "Index out of range."); + assert(VN.value(index)); // This triggers the necessary checks. + if (Nodes.size() < index) Nodes.resize(index); return &Nodes[index-1]; } - /// Returns the node currently representing Value V, or zero if no such - /// node exists. - unsigned getNode(Value *V, ETNode *Subtree) { - NodeMapType::iterator E = NodeMap.end(); - NodeMapEdge Edge(V, 0, Subtree); - NodeMapType::iterator I = std::lower_bound(NodeMap.begin(), E, Edge); - while (I != E && I->V == V) { - if (Subtree->DominatedBy(I->Subtree)) - return I->index; - ++I; - } - return 0; - } - - /// getOrInsertNode - always returns a valid node index, creating a node - /// to match the Value if needed. - unsigned getOrInsertNode(Value *V, ETNode *Subtree) { - if (unsigned n = getNode(V, Subtree)) - return n; - else - return newNode(V); - } - - /// newNode - creates a new node for a given Value and returns the index. - unsigned newNode(Value *V) { - Nodes.push_back(Node(V)); - - NodeMapEdge MapEntry = NodeMapEdge(V, Nodes.size(), TreeRoot); - assert(!std::binary_search(NodeMap.begin(), NodeMap.end(), MapEntry) && - "Attempt to create a duplicate Node."); - NodeMap.insert(std::lower_bound(NodeMap.begin(), NodeMap.end(), - MapEntry), MapEntry); - return MapEntry.index; - } - - /// If the Value is in the graph, return the canonical form. Otherwise, - /// return the original Value. - Value *canonicalize(Value *V, ETNode *Subtree) { - if (isa(V)) return V; - - if (unsigned n = getNode(V, Subtree)) - return node(n)->getValue(); - else - return V; - } - /// isRelatedBy - true iff n1 op n2 - bool isRelatedBy(unsigned n1, unsigned n2, ETNode *Subtree, LatticeVal LV) { + bool isRelatedBy(unsigned n1, unsigned n2, DomTreeDFS::Node *Subtree, + LatticeVal LV) { if (n1 == n2) return LV & EQ_BIT; Node *N1 = node(n1); @@ -448,56 +769,9 @@ namespace { // The add* methods assume that your input is logically valid and may // assertion-fail or infinitely loop if you attempt a contradiction. - void addEquality(unsigned n, Value *V, ETNode *Subtree) { - assert(canonicalize(node(n)->getValue(), Subtree) == node(n)->getValue() - && "Node's 'canonical' choice isn't best within this subtree."); - - // Suppose that we are given "%x -> node #1 (%y)". The problem is that - // we may already have "%z -> node #2 (%x)" somewhere above us in the - // graph. We need to find those edges and add "%z -> node #1 (%y)" - // to keep the lookups canonical. - - std::vector ToRepoint; - ToRepoint.push_back(V); - - if (unsigned Conflict = getNode(V, Subtree)) { - for (NodeMapType::iterator I = NodeMap.begin(), E = NodeMap.end(); - I != E; ++I) { - if (I->index == Conflict && Subtree->DominatedBy(I->Subtree)) - ToRepoint.push_back(I->V); - } - } - - for (std::vector::iterator VI = ToRepoint.begin(), - VE = ToRepoint.end(); VI != VE; ++VI) { - Value *V = *VI; - - // XXX: review this code. This may be doing too many insertions. - NodeMapEdge Edge(V, n, Subtree); - NodeMapType::iterator E = NodeMap.end(); - NodeMapType::iterator I = std::lower_bound(NodeMap.begin(), E, Edge); - if (I == E || I->V != V || I->Subtree != Subtree) { - // New Value - NodeMap.insert(I, Edge); - } else if (I != E && I->V == V && I->Subtree == Subtree) { - // Update best choice - I->index = n; - } - -#ifndef NDEBUG - Node *N = node(n); - if (isa(V)) { - if (isa(N->getValue())) { - assert(V == N->getValue() && "Constant equals different constant?"); - } - } -#endif - } - } - /// addInequality - Sets n1 op n2. /// It is also an error to call this on an inequality that is already true. - void addInequality(unsigned n1, unsigned n2, ETNode *Subtree, + void addInequality(unsigned n1, unsigned n2, DomTreeDFS::Node *Subtree, LatticeVal LV1) { assert(n1 != n2 && "A node can't be inequal to itself."); @@ -505,9 +779,6 @@ namespace { assert(!isRelatedBy(n1, n2, Subtree, reversePredicate(LV1)) && "Contradictory inequality."); - Node *N1 = node(n1); - Node *N2 = node(n2); - // Suppose we're adding %n1 < %n2. Find all the %a < %n1 and // add %a < %n2 too. This keeps the graph fully connected. if (LV1 != NE) { @@ -519,10 +790,10 @@ namespace { unsigned LV1_s = LV1 & (SLT_BIT|SGT_BIT); unsigned LV1_u = LV1 & (ULT_BIT|UGT_BIT); - for (Node::iterator I = N1->begin(), E = N1->end(); I != E; ++I) { + for (Node::iterator I = node(n1)->begin(), E = node(n1)->end(); I != E; ++I) { if (I->LV != NE && I->To != n2) { - ETNode *Local_Subtree = NULL; + DomTreeDFS::Node *Local_Subtree = NULL; if (Subtree->DominatedBy(I->Subtree)) Local_Subtree = Subtree; else if (I->Subtree->DominatedBy(Subtree)) @@ -550,15 +821,15 @@ namespace { LatticeVal NewLV = static_cast(new_relationship); node(I->To)->update(n2, NewLV, Local_Subtree); - N2->update(I->To, reversePredicate(NewLV), Local_Subtree); + node(n2)->update(I->To, reversePredicate(NewLV), Local_Subtree); } } } } - for (Node::iterator I = N2->begin(), E = N2->end(); I != E; ++I) { + for (Node::iterator I = node(n2)->begin(), E = node(n2)->end(); I != E; ++I) { if (I->LV != NE && I->To != n1) { - ETNode *Local_Subtree = NULL; + DomTreeDFS::Node *Local_Subtree = NULL; if (Subtree->DominatedBy(I->Subtree)) Local_Subtree = Subtree; else if (I->Subtree->DominatedBy(Subtree)) @@ -585,7 +856,7 @@ namespace { LatticeVal NewLV = static_cast(new_relationship); - N1->update(I->To, NewLV, Local_Subtree); + node(n1)->update(I->To, NewLV, Local_Subtree); node(I->To)->update(n1, reversePredicate(NewLV), Local_Subtree); } } @@ -593,32 +864,22 @@ namespace { } } - N1->update(n2, LV1, Subtree); - N2->update(n1, reversePredicate(LV1), Subtree); + node(n1)->update(n2, LV1, Subtree); + node(n2)->update(n1, reversePredicate(LV1), Subtree); } - /// remove - Removes a Value from the graph. If the value is the canonical - /// choice for a Node, destroys the Node from the graph deleting all edges - /// to and from it. This method does not renumber the nodes. - void remove(Value *V) { - for (unsigned i = 0; i < NodeMap.size();) { - NodeMapType::iterator I = NodeMap.begin()+i; - if (I->V == V) { - Node *N = node(I->index); - if (node(I->index)->getValue() == V) { - for (Node::iterator NI = N->begin(), NE = N->end(); NI != NE; ++NI){ - Node::iterator Iter = node(NI->To)->find(I->index, TreeRoot); - do { - node(NI->To)->Relations.erase(Iter); - Iter = node(NI->To)->find(I->index, TreeRoot); - } while (Iter != node(NI->To)->end()); - } - N->Canonical = NULL; - } - N->Relations.clear(); - NodeMap.erase(I); - } else ++i; + /// remove - removes a node from the graph by removing all references to + /// and from it. + void remove(unsigned n) { + Node *N = node(n); + for (Node::iterator NI = N->begin(), NE = N->end(); NI != NE; ++NI) { + Node::iterator Iter = node(NI->To)->find(n, TreeRoot); + do { + node(NI->To)->Relations.erase(Iter); + Iter = node(NI->To)->find(n, TreeRoot); + } while (Iter != node(NI->To)->end()); } + N->Relations.clear(); } #ifndef NDEBUG @@ -628,19 +889,12 @@ namespace { } void dump(std::ostream &os) { - std::set VisitedNodes; - for (NodeMapType::const_iterator I = NodeMap.begin(), E = NodeMap.end(); - I != E; ++I) { - Node *N = node(I->index); - os << *I->V << " == " << I->index - << "(" << I->Subtree->getDFSNumIn() << ")\n"; - if (VisitedNodes.insert(N).second) { - os << I->index << ". "; - if (!N->getValue()) os << "(deleted node)\n"; - else N->dump(os); + for (unsigned i = 1; i <= Nodes.size(); ++i) { + os << i << " = {"; + node(i)->dump(os); + os << "}\n"; } } - } #endif }; @@ -649,93 +903,127 @@ namespace { /// ValueRanges tracks the known integer ranges and anti-ranges of the nodes /// in the InequalityGraph. class VISIBILITY_HIDDEN ValueRanges { + ValueNumbering &VN; + TargetData *TD; - /// A ScopedRange ties an InequalityGraph node with a ConstantRange under - /// the scope of a rooted subtree in the dominator tree. class VISIBILITY_HIDDEN ScopedRange { - public: - ScopedRange(Value *V, ConstantRange CR, ETNode *ST) - : V(V), CR(CR), Subtree(ST) {} + typedef std::vector > + RangeListType; + RangeListType RangeList; - Value *V; - ConstantRange CR; - ETNode *Subtree; + static bool swo(const std::pair &LHS, + const std::pair &RHS) { + return *LHS.first < *RHS.first; + } - bool operator<(const ScopedRange &range) const { - if (V != range.V) return V < range.V; - else return OrderByDominance()(Subtree, range.Subtree); + public: +#ifndef NDEBUG + virtual ~ScopedRange() {} + virtual void dump() const { + dump(*cerr.stream()); } - bool operator<(const Value *value) const { - return V < value; + void dump(std::ostream &os) const { + os << "{"; + for (const_iterator I = begin(), E = end(); I != E; ++I) { + os << &I->second << " (" << I->first->getDFSNumIn() << "), "; + } + os << "}"; } - }; +#endif - TargetData *TD; + typedef RangeListType::iterator iterator; + typedef RangeListType::const_iterator const_iterator; - std::vector Ranges; - typedef std::vector::iterator iterator; + iterator begin() { return RangeList.begin(); } + iterator end() { return RangeList.end(); } + const_iterator begin() const { return RangeList.begin(); } + const_iterator end() const { return RangeList.end(); } + + iterator find(DomTreeDFS::Node *Subtree) { + iterator E = end(); + iterator I = std::lower_bound(begin(), E, + std::make_pair(Subtree, empty), swo); - // XXX: this is a copy of the code in InequalityGraph::Node. Perhaps a - // intrusive domtree-scoped container is in order? + while (I != E && !I->first->dominates(Subtree)) ++I; + return I; + } - iterator begin() { return Ranges.begin(); } - iterator end() { return Ranges.end(); } + const_iterator find(DomTreeDFS::Node *Subtree) const { + const_iterator E = end(); + const_iterator I = std::lower_bound(begin(), E, + std::make_pair(Subtree, empty), swo); - iterator find(Value *V, ETNode *Subtree) { - iterator E = end(); - for (iterator I = std::lower_bound(begin(), E, V); - I != E && I->V == V; ++I) { - if (Subtree->DominatedBy(I->Subtree)) - return I; + while (I != E && !I->first->dominates(Subtree)) ++I; + return I; } - return E; - } - void update(Value *V, ConstantRange CR, ETNode *Subtree) { - assert(!CR.isEmptySet() && "Empty ConstantRange!"); + void update(const ConstantRange &CR, DomTreeDFS::Node *Subtree) { + assert(!CR.isEmptySet() && "Empty ConstantRange."); + assert(!CR.isSingleElement() && "Refusing to store single element."); + + iterator E = end(); + iterator I = + std::lower_bound(begin(), E, std::make_pair(Subtree, empty), swo); + + if (I != end() && I->first == Subtree) { + ConstantRange CR2 = I->second.maximalIntersectWith(CR); + assert(!CR2.isEmptySet() && !CR2.isSingleElement() && + "Invalid union of ranges."); + I->second = CR2; + } else + RangeList.insert(I, std::make_pair(Subtree, CR)); + } + }; + + std::vector Ranges; + + void update(unsigned n, const ConstantRange &CR, DomTreeDFS::Node *Subtree){ if (CR.isFullSet()) return; + if (Ranges.size() < n) Ranges.resize(n); + Ranges[n-1].update(CR, Subtree); + } - iterator I = find(V, Subtree); - if (I == end()) { - ScopedRange range(V, CR, Subtree); - iterator Insert = std::lower_bound(begin(), end(), range); - Ranges.insert(Insert, range); - } else { - CR = CR.intersectWith(I->CR); - assert(!CR.isEmptySet() && "Empty intersection of ConstantRanges!"); - - if (CR != I->CR) { - if (Subtree != I->Subtree) { - assert(Subtree->DominatedBy(I->Subtree) && - "Find returned subtree that doesn't apply."); - - ScopedRange range(V, CR, Subtree); - iterator Insert = std::lower_bound(begin(), end(), range); - Ranges.insert(Insert, range); // invalidates I - I = find(V, Subtree); - } + /// create - Creates a ConstantRange that matches the given LatticeVal + /// relation with a given integer. + ConstantRange create(LatticeVal LV, const ConstantRange &CR) { + assert(!CR.isEmptySet() && "Can't deal with empty set."); - // Also, we have to tighten any edge that Subtree dominates. - for (iterator B = begin(); I->V == V; --I) { - if (I->Subtree->DominatedBy(Subtree)) { - I->CR = CR.intersectWith(I->CR); - assert(!I->CR.isEmptySet() && - "Empty intersection of ConstantRanges!"); - } - if (I == B) break; - } - } + if (LV == NE) + return makeConstantRange(ICmpInst::ICMP_NE, CR); + + unsigned LV_s = LV & (SGT_BIT|SLT_BIT); + unsigned LV_u = LV & (UGT_BIT|ULT_BIT); + bool hasEQ = LV & EQ_BIT; + + ConstantRange Range(CR.getBitWidth()); + + if (LV_s == SGT_BIT) { + Range = Range.maximalIntersectWith(makeConstantRange( + hasEQ ? ICmpInst::ICMP_SGE : ICmpInst::ICMP_SGT, CR)); + } else if (LV_s == SLT_BIT) { + Range = Range.maximalIntersectWith(makeConstantRange( + hasEQ ? ICmpInst::ICMP_SLE : ICmpInst::ICMP_SLT, CR)); + } + + if (LV_u == UGT_BIT) { + Range = Range.maximalIntersectWith(makeConstantRange( + hasEQ ? ICmpInst::ICMP_UGE : ICmpInst::ICMP_UGT, CR)); + } else if (LV_u == ULT_BIT) { + Range = Range.maximalIntersectWith(makeConstantRange( + hasEQ ? ICmpInst::ICMP_ULE : ICmpInst::ICMP_ULT, CR)); } + + return Range; } - /// range - Creates a ConstantRange representing the set of all values - /// that match the ICmpInst::Predicate with any of the values in CR. - ConstantRange range(ICmpInst::Predicate ICmpOpcode, - const ConstantRange &CR) { + /// makeConstantRange - Creates a ConstantRange representing the set of all + /// value that match the ICmpInst::Predicate with any of the values in CR. + ConstantRange makeConstantRange(ICmpInst::Predicate ICmpOpcode, + const ConstantRange &CR) { uint32_t W = CR.getBitWidth(); switch (ICmpOpcode) { - default: assert(!"Invalid ICmp opcode to range()"); + default: assert(!"Invalid ICmp opcode to makeConstantRange()"); case ICmpInst::ICMP_EQ: return ConstantRange(CR.getLower(), CR.getUpper()); case ICmpInst::ICMP_NE: @@ -747,87 +1035,85 @@ namespace { case ICmpInst::ICMP_SLT: return ConstantRange(APInt::getSignedMinValue(W), CR.getSignedMax()); case ICmpInst::ICMP_ULE: { - APInt UMax = CR.getUnsignedMax(); - if (UMax == APInt::getMaxValue(W)) + APInt UMax(CR.getUnsignedMax()); + if (UMax.isMaxValue()) return ConstantRange(W); return ConstantRange(APInt::getMinValue(W), UMax + 1); } case ICmpInst::ICMP_SLE: { - APInt SMax = CR.getSignedMax(); - if (SMax == APInt::getSignedMaxValue(W) || - SMax + 1 == APInt::getSignedMaxValue(W)) + APInt SMax(CR.getSignedMax()); + if (SMax.isMaxSignedValue() || (SMax+1).isMaxSignedValue()) return ConstantRange(W); return ConstantRange(APInt::getSignedMinValue(W), SMax + 1); } case ICmpInst::ICMP_UGT: - return ConstantRange(CR.getUnsignedMin() + 1, - APInt::getMaxValue(W) + 1); + return ConstantRange(CR.getUnsignedMin() + 1, APInt::getNullValue(W)); case ICmpInst::ICMP_SGT: return ConstantRange(CR.getSignedMin() + 1, - APInt::getSignedMaxValue(W) + 1); + APInt::getSignedMinValue(W)); case ICmpInst::ICMP_UGE: { - APInt UMin = CR.getUnsignedMin(); - if (UMin == APInt::getMinValue(W)) + APInt UMin(CR.getUnsignedMin()); + if (UMin.isMinValue()) return ConstantRange(W); - return ConstantRange(UMin, APInt::getMaxValue(W) + 1); + return ConstantRange(UMin, APInt::getNullValue(W)); } case ICmpInst::ICMP_SGE: { - APInt SMin = CR.getSignedMin(); - if (SMin == APInt::getSignedMinValue(W)) + APInt SMin(CR.getSignedMin()); + if (SMin.isMinSignedValue()) return ConstantRange(W); - return ConstantRange(SMin, APInt::getSignedMaxValue(W) + 1); + return ConstantRange(SMin, APInt::getSignedMinValue(W)); } } } - /// create - Creates a ConstantRange that matches the given LatticeVal - /// relation with a given integer. - ConstantRange create(LatticeVal LV, const ConstantRange &CR) { - assert(!CR.isEmptySet() && "Can't deal with empty set."); +#ifndef NDEBUG + bool isCanonical(Value *V, DomTreeDFS::Node *Subtree) { + return V == VN.canonicalize(V, Subtree); + } +#endif - if (LV == NE) - return range(ICmpInst::ICMP_NE, CR); + public: - unsigned LV_s = LV & (SGT_BIT|SLT_BIT); - unsigned LV_u = LV & (UGT_BIT|ULT_BIT); - bool hasEQ = LV & EQ_BIT; + ValueRanges(ValueNumbering &VN, TargetData *TD) : VN(VN), TD(TD) {} - ConstantRange Range(CR.getBitWidth()); +#ifndef NDEBUG + virtual ~ValueRanges() {} - if (LV_s == SGT_BIT) { - Range = Range.intersectWith(range( - hasEQ ? ICmpInst::ICMP_SGE : ICmpInst::ICMP_SGT, CR)); - } else if (LV_s == SLT_BIT) { - Range = Range.intersectWith(range( - hasEQ ? ICmpInst::ICMP_SLE : ICmpInst::ICMP_SLT, CR)); + virtual void dump() const { + dump(*cerr.stream()); + } + + void dump(std::ostream &os) const { + for (unsigned i = 0, e = Ranges.size(); i != e; ++i) { + os << (i+1) << " = "; + Ranges[i].dump(os); + os << "\n"; } + } +#endif - if (LV_u == UGT_BIT) { - Range = Range.intersectWith(range( - hasEQ ? ICmpInst::ICMP_UGE : ICmpInst::ICMP_UGT, CR)); - } else if (LV_u == ULT_BIT) { - Range = Range.intersectWith(range( - hasEQ ? ICmpInst::ICMP_ULE : ICmpInst::ICMP_ULT, CR)); + /// range - looks up the ConstantRange associated with a value number. + ConstantRange range(unsigned n, DomTreeDFS::Node *Subtree) { + assert(VN.value(n)); // performs range checks + + if (n <= Ranges.size()) { + ScopedRange::iterator I = Ranges[n-1].find(Subtree); + if (I != Ranges[n-1].end()) return I->second; } - return Range; + Value *V = VN.value(n); + ConstantRange CR = range(V); + return CR; } - // rangeFromValue - converts a Value into a range. If the value is a - // constant it constructs the single element range, otherwise it performs - // a lookup. The width W must be retrieved from typeToWidth and may not - // be zero. - ConstantRange rangeFromValue(Value *V, ETNode *Subtree, uint32_t W) { - if (ConstantInt *C = dyn_cast(V)) { + /// range - determine a range from a Value without performing any lookups. + ConstantRange range(Value *V) const { + if (ConstantInt *C = dyn_cast(V)) return ConstantRange(C->getValue()); - } else if (isa(V)) { - return ConstantRange(APInt::getNullValue(W)); - } else { - iterator I = find(V, Subtree); - if (I != end()) - return I->CR; - } - return ConstantRange(W); + else if (isa(V)) + return ConstantRange(APInt::getNullValue(typeToWidth(V->getType()))); + else + return ConstantRange(typeToWidth(V->getType())); } // typeToWidth - returns the number of bits necessary to store a value of @@ -835,33 +1121,16 @@ namespace { uint32_t typeToWidth(const Type *Ty) const { if (TD) return TD->getTypeSizeInBits(Ty); - - if (const IntegerType *ITy = dyn_cast(Ty)) - return ITy->getBitWidth(); - - return 0; + else + return Ty->getPrimitiveSizeInBits(); } -#ifndef NDEBUG - bool isCanonical(Value *V, ETNode *Subtree, VRPSolver *VRP); -#endif - - public: - - explicit ValueRanges(TargetData *TD) : TD(TD) {} - - bool isRelatedBy(Value *V1, Value *V2, ETNode *Subtree, LatticeVal LV) { - uint32_t W = typeToWidth(V1->getType()); - if (!W) return false; - - ConstantRange CR1 = rangeFromValue(V1, Subtree, W); - ConstantRange CR2 = rangeFromValue(V2, Subtree, W); - - // True iff all values in CR1 are LV to all values in CR2. + static bool isRelatedBy(const ConstantRange &CR1, const ConstantRange &CR2, + LatticeVal LV) { switch (LV) { default: assert(!"Impossible lattice value!"); case NE: - return CR1.intersectWith(CR2).isEmptySet(); + return CR1.maximalIntersectWith(CR2).isEmptySet(); case ULT: return CR1.getUnsignedMax().ult(CR2.getUnsignedMin()); case ULE: @@ -905,23 +1174,29 @@ namespace { } } - void addToWorklist(Value *V, Constant *C, ICmpInst::Predicate Pred, - VRPSolver *VRP); + bool isRelatedBy(unsigned n1, unsigned n2, DomTreeDFS::Node *Subtree, + LatticeVal LV) { + ConstantRange CR1 = range(n1, Subtree); + ConstantRange CR2 = range(n2, Subtree); - void mergeInto(Value **I, unsigned n, Value *New, ETNode *Subtree, - VRPSolver *VRP) { - assert(isCanonical(New, Subtree, VRP) && "Best choice not canonical?"); + // True iff all values in CR1 are LV to all values in CR2. + return isRelatedBy(CR1, CR2, LV); + } - uint32_t W = typeToWidth(New->getType()); - if (!W) return; + void addToWorklist(Value *V, Constant *C, ICmpInst::Predicate Pred, + VRPSolver *VRP); + void markBlock(VRPSolver *VRP); - ConstantRange CR_New = rangeFromValue(New, Subtree, W); + void mergeInto(Value **I, unsigned n, unsigned New, + DomTreeDFS::Node *Subtree, VRPSolver *VRP) { + ConstantRange CR_New = range(New, Subtree); ConstantRange Merged = CR_New; for (; n != 0; ++I, --n) { - ConstantRange CR_Kill = rangeFromValue(*I, Subtree, W); + unsigned i = VN.valueNumber(*I, Subtree); + ConstantRange CR_Kill = i ? range(i, Subtree) : range(*I); if (CR_Kill.isFullSet()) continue; - Merged = Merged.intersectWith(CR_Kill); + Merged = Merged.maximalIntersectWith(CR_Kill); } if (Merged.isFullSet() || Merged == CR_New) return; @@ -929,11 +1204,16 @@ namespace { applyRange(New, Merged, Subtree, VRP); } - void applyRange(Value *V, const ConstantRange &CR, ETNode *Subtree, - VRPSolver *VRP) { - assert(isCanonical(V, Subtree, VRP) && "Value not canonical."); + void applyRange(unsigned n, const ConstantRange &CR, + DomTreeDFS::Node *Subtree, VRPSolver *VRP) { + ConstantRange Merged = CR.maximalIntersectWith(range(n, Subtree)); + if (Merged.isEmptySet()) { + markBlock(VRP); + return; + } - if (const APInt *I = CR.getSingleElement()) { + if (const APInt *I = Merged.getSingleElement()) { + Value *V = VN.value(n); // XXX: redesign worklist. const Type *Ty = V->getType(); if (Ty->isInteger()) { addToWorklist(V, ConstantInt::get(*I), ICmpInst::ICMP_EQ, VRP); @@ -941,42 +1221,91 @@ namespace { } else if (const PointerType *PTy = dyn_cast(Ty)) { assert(*I == 0 && "Pointer is null but not zero?"); addToWorklist(V, ConstantPointerNull::get(PTy), - ICmpInst::ICMP_EQ, VRP); + ICmpInst::ICMP_EQ, VRP); return; } } - update(V, CR, Subtree); + update(n, Merged, Subtree); } - void addInequality(Value *V1, Value *V2, ETNode *Subtree, LatticeVal LV, - VRPSolver *VRP) { - assert(!isRelatedBy(V1, V2, Subtree, LV) && "Asked to do useless work."); + void addNotEquals(unsigned n1, unsigned n2, DomTreeDFS::Node *Subtree, + VRPSolver *VRP) { + ConstantRange CR1 = range(n1, Subtree); + ConstantRange CR2 = range(n2, Subtree); + + uint32_t W = CR1.getBitWidth(); + + if (const APInt *I = CR1.getSingleElement()) { + if (CR2.isFullSet()) { + ConstantRange NewCR2(CR1.getUpper(), CR1.getLower()); + applyRange(n2, NewCR2, Subtree, VRP); + } else if (*I == CR2.getLower()) { + APInt NewLower(CR2.getLower() + 1), + NewUpper(CR2.getUpper()); + if (NewLower == NewUpper) + NewLower = NewUpper = APInt::getMinValue(W); + + ConstantRange NewCR2(NewLower, NewUpper); + applyRange(n2, NewCR2, Subtree, VRP); + } else if (*I == CR2.getUpper() - 1) { + APInt NewLower(CR2.getLower()), + NewUpper(CR2.getUpper() - 1); + if (NewLower == NewUpper) + NewLower = NewUpper = APInt::getMinValue(W); + + ConstantRange NewCR2(NewLower, NewUpper); + applyRange(n2, NewCR2, Subtree, VRP); + } + } - assert(isCanonical(V1, Subtree, VRP) && "Value not canonical."); - assert(isCanonical(V2, Subtree, VRP) && "Value not canonical."); + if (const APInt *I = CR2.getSingleElement()) { + if (CR1.isFullSet()) { + ConstantRange NewCR1(CR2.getUpper(), CR2.getLower()); + applyRange(n1, NewCR1, Subtree, VRP); + } else if (*I == CR1.getLower()) { + APInt NewLower(CR1.getLower() + 1), + NewUpper(CR1.getUpper()); + if (NewLower == NewUpper) + NewLower = NewUpper = APInt::getMinValue(W); + + ConstantRange NewCR1(NewLower, NewUpper); + applyRange(n1, NewCR1, Subtree, VRP); + } else if (*I == CR1.getUpper() - 1) { + APInt NewLower(CR1.getLower()), + NewUpper(CR1.getUpper() - 1); + if (NewLower == NewUpper) + NewLower = NewUpper = APInt::getMinValue(W); + + ConstantRange NewCR1(NewLower, NewUpper); + applyRange(n1, NewCR1, Subtree, VRP); + } + } + } - if (LV == NE) return; // we can't represent those. - // XXX: except in the case where isSingleElement and equal to either - // Lower or Upper. That's probably not profitable. (Type::Int1Ty?) + void addInequality(unsigned n1, unsigned n2, DomTreeDFS::Node *Subtree, + LatticeVal LV, VRPSolver *VRP) { + assert(!isRelatedBy(n1, n2, Subtree, LV) && "Asked to do useless work."); - uint32_t W = typeToWidth(V1->getType()); - if (!W) return; + if (LV == NE) { + addNotEquals(n1, n2, Subtree, VRP); + return; + } - ConstantRange CR1 = rangeFromValue(V1, Subtree, W); - ConstantRange CR2 = rangeFromValue(V2, Subtree, W); + ConstantRange CR1 = range(n1, Subtree); + ConstantRange CR2 = range(n2, Subtree); if (!CR1.isSingleElement()) { - ConstantRange NewCR1 = CR1.intersectWith(create(LV, CR2)); + ConstantRange NewCR1 = CR1.maximalIntersectWith(create(LV, CR2)); if (NewCR1 != CR1) - applyRange(V1, NewCR1, Subtree, VRP); + applyRange(n1, NewCR1, Subtree, VRP); } if (!CR2.isSingleElement()) { - ConstantRange NewCR2 = CR2.intersectWith(create(reversePredicate(LV), - CR1)); + ConstantRange NewCR2 = CR2.maximalIntersectWith( + create(reversePredicate(LV), CR1)); if (NewCR2 != CR2) - applyRange(V2, NewCR2, Subtree, VRP); + applyRange(n2, NewCR2, Subtree, VRP); } } }; @@ -1047,78 +1376,63 @@ namespace { Value *LHS, *RHS; ICmpInst::Predicate Op; - BasicBlock *ContextBB; + BasicBlock *ContextBB; // XXX use a DomTreeDFS::Node instead Instruction *ContextInst; }; std::deque WorkList; + ValueNumbering &VN; InequalityGraph &IG; UnreachableBlocks &UB; ValueRanges &VR; - - ETForest *Forest; - ETNode *Top; + DomTreeDFS *DTDFS; + DomTreeDFS::Node *Top; BasicBlock *TopBB; Instruction *TopInst; bool &modified; typedef InequalityGraph::Node Node; - /// IdomI - Determines whether one Instruction dominates another. - bool IdomI(Instruction *I1, Instruction *I2) const { - BasicBlock *BB1 = I1->getParent(), - *BB2 = I2->getParent(); - if (BB1 == BB2) { - if (isa(I1)) return false; - if (isa(I2)) return true; - if (isa(I1) && !isa(I2)) return true; - if (!isa(I1) && isa(I2)) return false; - - for (BasicBlock::const_iterator I = BB1->begin(), E = BB1->end(); - I != E; ++I) { - if (&*I == I1) return true; - if (&*I == I2) return false; + // below - true if the Instruction is dominated by the current context + // block or instruction + bool below(Instruction *I) { + BasicBlock *BB = I->getParent(); + if (TopInst && TopInst->getParent() == BB) { + if (isa(TopInst)) return false; + if (isa(I)) return true; + if ( isa(TopInst) && !isa(I)) return true; + if (!isa(TopInst) && isa(I)) return false; + + for (BasicBlock::const_iterator Iter = BB->begin(), E = BB->end(); + Iter != E; ++Iter) { + if (&*Iter == TopInst) return true; + else if (&*Iter == I) return false; } assert(!"Instructions not found in parent BasicBlock?"); } else { - return Forest->properlyDominates(BB1, BB2); + DomTreeDFS::Node *Node = DTDFS->getNodeForBlock(BB); + if (!Node) return false; + return Top->dominates(Node); } - return false; + return false; // Not reached } - /// Returns true if V1 is a better canonical value than V2. - bool compare(Value *V1, Value *V2) const { - if (isa(V1)) - return !isa(V2); - else if (isa(V2)) - return false; - else if (isa(V1)) - return !isa(V2); - else if (isa(V2)) - return false; + // aboveOrBelow - true if the Instruction either dominates or is dominated + // by the current context block or instruction + bool aboveOrBelow(Instruction *I) { + BasicBlock *BB = I->getParent(); + DomTreeDFS::Node *Node = DTDFS->getNodeForBlock(BB); + if (!Node) return false; - Instruction *I1 = dyn_cast(V1); - Instruction *I2 = dyn_cast(V2); - - if (!I1 || !I2) - return V1->getNumUses() < V2->getNumUses(); - - return IdomI(I1, I2); - } - - // below - true if the Instruction is dominated by the current context - // block or instruction - bool below(Instruction *I) { - if (TopInst) - return IdomI(TopInst, I); - else { - ETNode *Node = Forest->getNodeForBlock(I->getParent()); - return Node->DominatedBy(Top); - } + return Top == Node || Top->dominates(Node) || Node->dominates(Top); } bool makeEqual(Value *V1, Value *V2) { DOUT << "makeEqual(" << *V1 << ", " << *V2 << ")\n"; + DOUT << "context is "; + if (TopInst) DOUT << "I: " << *TopInst << "\n"; + else DOUT << "BB: " << TopBB->getName() + << "(" << Top->getDFSNumIn() << ")\n"; assert(V1->getType() == V2->getType() && "Can't make two values with different types equal."); @@ -1128,17 +1442,17 @@ namespace { if (isa(V1) && isa(V2)) return false; - unsigned n1 = IG.getNode(V1, Top), n2 = IG.getNode(V2, Top); + unsigned n1 = VN.valueNumber(V1, Top), n2 = VN.valueNumber(V2, Top); if (n1 && n2) { if (n1 == n2) return true; if (IG.isRelatedBy(n1, n2, Top, NE)) return false; } - if (n1) assert(V1 == IG.node(n1)->getValue() && "Value isn't canonical."); - if (n2) assert(V2 == IG.node(n2)->getValue() && "Value isn't canonical."); + if (n1) assert(V1 == VN.value(n1) && "Value isn't canonical."); + if (n2) assert(V2 == VN.value(n2) && "Value isn't canonical."); - assert(!compare(V2, V1) && "Please order parameters to makeEqual."); + assert(!VN.compare(V2, V1) && "Please order parameters to makeEqual."); assert(!isa(V2) && "Tried to remove a constant."); @@ -1151,19 +1465,18 @@ namespace { // be EQ and that's invalid. What we're doing is looking for any nodes // %z such that %x <= %z and %y >= %z, and vice versa. - Node *N1 = IG.node(n1); - Node *N2 = IG.node(n2); - Node::iterator end = N2->end(); + Node::iterator end = IG.node(n2)->end(); // Find the intersection between N1 and N2 which is dominated by // Top. If we find %x where N1 <= %x <= N2 (or >=) then add %x to // Remove. - for (Node::iterator I = N1->begin(), E = N1->end(); I != E; ++I) { + for (Node::iterator I = IG.node(n1)->begin(), E = IG.node(n1)->end(); + I != E; ++I) { if (!(I->LV & EQ_BIT) || !Top->DominatedBy(I->Subtree)) continue; unsigned ILV_s = I->LV & (SLT_BIT|SGT_BIT); unsigned ILV_u = I->LV & (ULT_BIT|UGT_BIT); - Node::iterator NI = N2->find(I->To, Top); + Node::iterator NI = IG.node(n2)->find(I->To, Top); if (NI != end) { LatticeVal NILV = reversePredicate(NI->LV); unsigned NILV_s = NILV & (SLT_BIT|SGT_BIT); @@ -1182,8 +1495,8 @@ namespace { for (SetVector::iterator I = Remove.begin()+1 /* skip n2 */, E = Remove.end(); I != E; ++I) { unsigned n = *I; - Value *V = IG.node(n)->getValue(); - if (compare(V, V1)) { + Value *V = VN.value(n); + if (VN.compare(V, V1)) { V1 = V; n1 = n; DontRemove = I; @@ -1197,7 +1510,7 @@ namespace { } // We'd like to allow makeEqual on two values to perform a simple - // substitution without every creating nodes in the IG whenever possible. + // substitution without creating nodes in the IG whenever possible. // // The first iteration through this loop operates on V2 before going // through the Remove list and operating on those too. If all of the @@ -1205,18 +1518,18 @@ namespace { bool mergeIGNode = false; unsigned i = 0; for (Value *R = V2; i == 0 || i < Remove.size(); ++i) { - if (i) R = IG.node(Remove[i])->getValue(); // skip n2. + if (i) R = VN.value(Remove[i]); // skip n2. // Try to replace the whole instruction. If we can, we're done. Instruction *I2 = dyn_cast(R); if (I2 && below(I2)) { std::vector ToNotify; - for (Value::use_iterator UI = R->use_begin(), UE = R->use_end(); + for (Value::use_iterator UI = I2->use_begin(), UE = I2->use_end(); UI != UE;) { Use &TheUse = UI.getUse(); ++UI; - if (Instruction *I = dyn_cast(TheUse.getUser())) - ToNotify.push_back(I); + Instruction *I = cast(TheUse.getUser()); + ToNotify.push_back(I); } DOUT << "Simply removing " << *I2 @@ -1263,32 +1576,33 @@ namespace { if (!isa(V1)) { if (Remove.empty()) { - VR.mergeInto(&V2, 1, V1, Top, this); + VR.mergeInto(&V2, 1, VN.getOrInsertVN(V1, Top), Top, this); } else { std::vector RemoveVals; RemoveVals.reserve(Remove.size()); for (SetVector::iterator I = Remove.begin(), E = Remove.end(); I != E; ++I) { - Value *V = IG.node(*I)->getValue(); + Value *V = VN.value(*I); if (!V->use_empty()) RemoveVals.push_back(V); } - VR.mergeInto(&RemoveVals[0], RemoveVals.size(), V1, Top, this); + VR.mergeInto(&RemoveVals[0], RemoveVals.size(), + VN.getOrInsertVN(V1, Top), Top, this); } } if (mergeIGNode) { // Create N1. - if (!n1) n1 = IG.newNode(V1); + if (!n1) n1 = VN.getOrInsertVN(V1, Top); + IG.node(n1); // Ensure that IG.Nodes won't get resized // Migrate relationships from removed nodes to N1. - Node *N1 = IG.node(n1); for (SetVector::iterator I = Remove.begin(), E = Remove.end(); I != E; ++I) { unsigned n = *I; - Node *N = IG.node(n); - for (Node::iterator NI = N->begin(), NE = N->end(); NI != NE; ++NI) { + for (Node::iterator NI = IG.node(n)->begin(), NE = IG.node(n)->end(); + NI != NE; ++NI) { if (NI->Subtree->DominatedBy(Top)) { if (NI->To == n1) { assert((NI->LV & EQ_BIT) && "Node inequal to itself."); @@ -1298,18 +1612,18 @@ namespace { continue; IG.node(NI->To)->update(n1, reversePredicate(NI->LV), Top); - N1->update(NI->To, NI->LV, Top); + IG.node(n1)->update(NI->To, NI->LV, Top); } } } // Point V2 (and all items in Remove) to N1. if (!n2) - IG.addEquality(n1, V2, Top); + VN.addEquality(n1, V2, Top); else { for (SetVector::iterator I = Remove.begin(), E = Remove.end(); I != E; ++I) { - IG.addEquality(n1, IG.node(*I)->getValue(), Top); + VN.addEquality(n1, VN.value(*I), Top); } } @@ -1317,11 +1631,10 @@ namespace { // Even when Remove is empty, we still want to process V2. i = 0; for (Value *R = V2; i == 0 || i < Remove.size(); ++i) { - if (i) R = IG.node(Remove[i])->getValue(); // skip n2. + if (i) R = VN.value(Remove[i]); // skip n2. if (Instruction *I2 = dyn_cast(R)) { - if (below(I2) || - Top->DominatedBy(Forest->getNodeForBlock(I2->getParent()))) + if (aboveOrBelow(I2)) defToOps(I2); } for (Value::use_iterator UI = V2->use_begin(), UE = V2->use_end(); @@ -1329,8 +1642,7 @@ namespace { Use &TheUse = UI.getUse(); ++UI; if (Instruction *I = dyn_cast(TheUse.getUser())) { - if (below(I) || - Top->DominatedBy(Forest->getNodeForBlock(I->getParent()))) + if (aboveOrBelow(I)) opsToDef(I); } } @@ -1345,11 +1657,9 @@ namespace { ++UI; Value *V = TheUse.getUser(); if (!V->use_empty()) { - if (Instruction *Inst = dyn_cast(V)) { - if (below(Inst) || - Top->DominatedBy(Forest->getNodeForBlock(Inst->getParent()))) - opsToDef(Inst); - } + Instruction *Inst = cast(V); + if (aboveOrBelow(Inst)) + opsToDef(Inst); } } } @@ -1388,28 +1698,37 @@ namespace { } public: - VRPSolver(InequalityGraph &IG, UnreachableBlocks &UB, ValueRanges &VR, - ETForest *Forest, bool &modified, BasicBlock *TopBB) - : IG(IG), + VRPSolver(ValueNumbering &VN, InequalityGraph &IG, UnreachableBlocks &UB, + ValueRanges &VR, DomTreeDFS *DTDFS, bool &modified, + BasicBlock *TopBB) + : VN(VN), + IG(IG), UB(UB), VR(VR), - Forest(Forest), - Top(Forest->getNodeForBlock(TopBB)), + DTDFS(DTDFS), + Top(DTDFS->getNodeForBlock(TopBB)), TopBB(TopBB), TopInst(NULL), - modified(modified) {} + modified(modified) + { + assert(Top && "VRPSolver created for unreachable basic block."); + } - VRPSolver(InequalityGraph &IG, UnreachableBlocks &UB, ValueRanges &VR, - ETForest *Forest, bool &modified, Instruction *TopInst) - : IG(IG), + VRPSolver(ValueNumbering &VN, InequalityGraph &IG, UnreachableBlocks &UB, + ValueRanges &VR, DomTreeDFS *DTDFS, bool &modified, + Instruction *TopInst) + : VN(VN), + IG(IG), UB(UB), VR(VR), - Forest(Forest), + DTDFS(DTDFS), + Top(DTDFS->getNodeForBlock(TopInst->getParent())), + TopBB(TopInst->getParent()), TopInst(TopInst), modified(modified) { - TopBB = TopInst->getParent(); - Top = Forest->getNodeForBlock(TopBB); + assert(Top && "VRPSolver created for unreachable basic block."); + assert(Top->getBlock() == TopInst->getParent() && "Context mismatch."); } bool isRelatedBy(Value *V1, Value *V2, ICmpInst::Predicate Pred) const { @@ -1418,19 +1737,33 @@ namespace { return ConstantExpr::getCompare(Pred, C1, C2) == ConstantInt::getTrue(); - if (unsigned n1 = IG.getNode(V1, Top)) - if (unsigned n2 = IG.getNode(V2, Top)) { - if (n1 == n2) return Pred == ICmpInst::ICMP_EQ || - Pred == ICmpInst::ICMP_ULE || - Pred == ICmpInst::ICMP_UGE || - Pred == ICmpInst::ICMP_SLE || - Pred == ICmpInst::ICMP_SGE; - if (Pred == ICmpInst::ICMP_EQ) return false; - if (IG.isRelatedBy(n1, n2, Top, cmpInstToLattice(Pred))) return true; - } + unsigned n1 = VN.valueNumber(V1, Top); + unsigned n2 = VN.valueNumber(V2, Top); + + if (n1 && n2) { + if (n1 == n2) return Pred == ICmpInst::ICMP_EQ || + Pred == ICmpInst::ICMP_ULE || + Pred == ICmpInst::ICMP_UGE || + Pred == ICmpInst::ICMP_SLE || + Pred == ICmpInst::ICMP_SGE; + if (Pred == ICmpInst::ICMP_EQ) return false; + if (IG.isRelatedBy(n1, n2, Top, cmpInstToLattice(Pred))) return true; + if (VR.isRelatedBy(n1, n2, Top, cmpInstToLattice(Pred))) return true; + } + + if ((n1 && !n2 && isa(V2)) || + (n2 && !n1 && isa(V1))) { + ConstantRange CR1 = n1 ? VR.range(n1, Top) : VR.range(V1); + ConstantRange CR2 = n2 ? VR.range(n2, Top) : VR.range(V2); + if (Pred == ICmpInst::ICMP_EQ) + return CR1.isSingleElement() && + CR1.getSingleElement() == CR2.getSingleElement(); + + return VR.isRelatedBy(CR1, CR2, cmpInstToLattice(Pred)); + } if (Pred == ICmpInst::ICMP_EQ) return V1 == V2; - return VR.isRelatedBy(V1, V2, Top, cmpInstToLattice(Pred)); + return false; } /// add - adds a new property to the work queue @@ -1438,7 +1771,7 @@ namespace { Instruction *I = NULL) { DOUT << "adding " << *V1 << " " << Pred << " " << *V2; if (I) DOUT << " context: " << *I; - else DOUT << " default context"; + else DOUT << " default context (" << Top->getDFSNumIn() << ")"; DOUT << "\n"; assert(V1->getType() == V2->getType() && @@ -1454,14 +1787,14 @@ namespace { /// new about, find any new relationships between its operands. void defToOps(Instruction *I) { Instruction *NewContext = below(I) ? I : TopInst; - Value *Canonical = IG.canonicalize(I, Top); + Value *Canonical = VN.canonicalize(I, Top); if (BinaryOperator *BO = dyn_cast(I)) { const Type *Ty = BO->getType(); assert(!Ty->isFPOrFPVector() && "Float in work queue!"); - Value *Op0 = IG.canonicalize(BO->getOperand(0), Top); - Value *Op1 = IG.canonicalize(BO->getOperand(1), Top); + Value *Op0 = VN.canonicalize(BO->getOperand(0), Top); + Value *Op1 = VN.canonicalize(BO->getOperand(1), Top); // TODO: "and i32 -1, %x" EQ %y then %x EQ %y. @@ -1530,11 +1863,11 @@ namespace { Value *True = SI->getTrueValue(); Value *False = SI->getFalseValue(); if (isRelatedBy(True, False, ICmpInst::ICMP_NE)) { - if (Canonical == IG.canonicalize(True, Top) || + if (Canonical == VN.canonicalize(True, Top) || isRelatedBy(Canonical, False, ICmpInst::ICMP_NE)) add(SI->getCondition(), ConstantInt::getTrue(), ICmpInst::ICMP_EQ, NewContext); - else if (Canonical == IG.canonicalize(False, Top) || + else if (Canonical == VN.canonicalize(False, Top) || isRelatedBy(Canonical, True, ICmpInst::ICMP_NE)) add(SI->getCondition(), ConstantInt::getFalse(), ICmpInst::ICMP_EQ, NewContext); @@ -1542,7 +1875,7 @@ namespace { } else if (GetElementPtrInst *GEPI = dyn_cast(I)) { for (GetElementPtrInst::op_iterator OI = GEPI->idx_begin(), OE = GEPI->idx_end(); OI != OE; ++OI) { - ConstantInt *Op = dyn_cast(IG.canonicalize(*OI, Top)); + ConstantInt *Op = dyn_cast(VN.canonicalize(*OI, Top)); if (!Op || !Op->isZero()) return; } // TODO: The GEPI indices are all zero. Copy from definition to operand, @@ -1553,8 +1886,29 @@ namespace { add(Ptr, Constant::getNullValue(Ptr->getType()), ICmpInst::ICMP_NE, NewContext); } + } else if (CastInst *CI = dyn_cast(I)) { + const Type *SrcTy = CI->getSrcTy(); + + unsigned ci = VN.getOrInsertVN(CI, Top); + uint32_t W = VR.typeToWidth(SrcTy); + if (!W) return; + ConstantRange CR = VR.range(ci, Top); + + if (CR.isFullSet()) return; + + switch (CI->getOpcode()) { + default: break; + case Instruction::ZExt: + case Instruction::SExt: + VR.applyRange(VN.getOrInsertVN(CI->getOperand(0), Top), + CR.truncate(W), Top, this); + break; + case Instruction::BitCast: + VR.applyRange(VN.getOrInsertVN(CI->getOperand(0), Top), + CR, Top, this); + break; + } } - // TODO: CastInst "%a = cast ... %b" where %a is EQ or NE a constant. } /// opsToDef - A new relationship was discovered involving one of this @@ -1564,8 +1918,8 @@ namespace { Instruction *NewContext = below(I) ? I : TopInst; if (BinaryOperator *BO = dyn_cast(I)) { - Value *Op0 = IG.canonicalize(BO->getOperand(0), Top); - Value *Op1 = IG.canonicalize(BO->getOperand(1), Top); + Value *Op0 = VN.canonicalize(BO->getOperand(0), Top); + Value *Op1 = VN.canonicalize(BO->getOperand(1), Top); if (ConstantInt *CI0 = dyn_cast(Op0)) if (ConstantInt *CI1 = dyn_cast(Op1)) { @@ -1584,26 +1938,81 @@ namespace { assert(!Ty->isFPOrFPVector() && "Float in work queue!"); Constant *Zero = Constant::getNullValue(Ty); - Constant *AllOnes = ConstantInt::getAllOnesValue(Ty); + Constant *One = ConstantInt::get(Ty, 1); + ConstantInt *AllOnes = ConstantInt::getAllOnesValue(Ty); switch (Opcode) { default: break; case Instruction::LShr: case Instruction::AShr: case Instruction::Shl: + if (Op1 == Zero) { + add(BO, Op0, ICmpInst::ICMP_EQ, NewContext); + return; + } + break; case Instruction::Sub: if (Op1 == Zero) { add(BO, Op0, ICmpInst::ICMP_EQ, NewContext); return; } + if (ConstantInt *CI0 = dyn_cast(Op0)) { + unsigned n_ci0 = VN.getOrInsertVN(Op1, Top); + ConstantRange CR = VR.range(n_ci0, Top); + if (!CR.isFullSet()) { + CR.subtract(CI0->getValue()); + unsigned n_bo = VN.getOrInsertVN(BO, Top); + VR.applyRange(n_bo, CR, Top, this); + return; + } + } + if (ConstantInt *CI1 = dyn_cast(Op1)) { + unsigned n_ci1 = VN.getOrInsertVN(Op0, Top); + ConstantRange CR = VR.range(n_ci1, Top); + if (!CR.isFullSet()) { + CR.subtract(CI1->getValue()); + unsigned n_bo = VN.getOrInsertVN(BO, Top); + VR.applyRange(n_bo, CR, Top, this); + return; + } + } break; case Instruction::Or: if (Op0 == AllOnes || Op1 == AllOnes) { add(BO, AllOnes, ICmpInst::ICMP_EQ, NewContext); return; - } // fall-through - case Instruction::Xor: + } + if (Op0 == Zero) { + add(BO, Op1, ICmpInst::ICMP_EQ, NewContext); + return; + } else if (Op1 == Zero) { + add(BO, Op0, ICmpInst::ICMP_EQ, NewContext); + return; + } + break; case Instruction::Add: + if (ConstantInt *CI0 = dyn_cast(Op0)) { + unsigned n_ci0 = VN.getOrInsertVN(Op1, Top); + ConstantRange CR = VR.range(n_ci0, Top); + if (!CR.isFullSet()) { + CR.subtract(-CI0->getValue()); + unsigned n_bo = VN.getOrInsertVN(BO, Top); + VR.applyRange(n_bo, CR, Top, this); + return; + } + } + if (ConstantInt *CI1 = dyn_cast(Op1)) { + unsigned n_ci1 = VN.getOrInsertVN(Op0, Top); + ConstantRange CR = VR.range(n_ci1, Top); + if (!CR.isFullSet()) { + CR.subtract(-CI1->getValue()); + unsigned n_bo = VN.getOrInsertVN(BO, Top); + VR.applyRange(n_bo, CR, Top, this); + return; + } + } + // fall-through + case Instruction::Xor: if (Op0 == Zero) { add(BO, Op1, ICmpInst::ICMP_EQ, NewContext); return; @@ -1620,22 +2029,33 @@ namespace { add(BO, Op0, ICmpInst::ICMP_EQ, NewContext); return; } - // fall-through + if (Op0 == Zero || Op1 == Zero) { + add(BO, Zero, ICmpInst::ICMP_EQ, NewContext); + return; + } + break; case Instruction::Mul: if (Op0 == Zero || Op1 == Zero) { add(BO, Zero, ICmpInst::ICMP_EQ, NewContext); return; } + if (Op0 == One) { + add(BO, Op1, ICmpInst::ICMP_EQ, NewContext); + return; + } else if (Op1 == One) { + add(BO, Op0, ICmpInst::ICMP_EQ, NewContext); + return; + } break; } // "%x = add i32 %y, %z" and %x EQ %y then %z EQ 0 // "%x = add i32 %y, %z" and %x EQ %z then %y EQ 0 // "%x = shl i32 %y, %z" and %x EQ %y and %y NE 0 then %z EQ 0 - // "%x = udiv i32 %y, %z" and %x EQ %y then %z EQ 1 + // "%x = udiv i32 %y, %z" and %x EQ %y and %y NE 0 then %z EQ 1 Value *Known = Op0, *Unknown = Op1, - *TheBO = IG.canonicalize(BO, Top); + *TheBO = VN.canonicalize(BO, Top); if (Known != TheBO) std::swap(Known, Unknown); if (Known == TheBO) { switch (Opcode) { @@ -1646,7 +2066,7 @@ namespace { if (!isRelatedBy(Known, Zero, ICmpInst::ICMP_NE)) break; // otherwise, fall-through. case Instruction::Sub: - if (Unknown == Op1) break; + if (Unknown == Op0) break; // otherwise, fall-through. case Instruction::Xor: case Instruction::Add: @@ -1655,10 +2075,8 @@ namespace { case Instruction::UDiv: case Instruction::SDiv: if (Unknown == Op1) break; - if (isRelatedBy(Known, Zero, ICmpInst::ICMP_NE)) { - Constant *One = ConstantInt::get(Ty, 1); + if (isRelatedBy(Known, Zero, ICmpInst::ICMP_NE)) add(Unknown, One, ICmpInst::ICMP_EQ, NewContext); - } break; } } @@ -1670,15 +2088,14 @@ namespace { // "%a = icmp ult i32 %b, %c" and %b u>= %c then %a EQ false // etc. - Value *Op0 = IG.canonicalize(IC->getOperand(0), Top); - Value *Op1 = IG.canonicalize(IC->getOperand(1), Top); + Value *Op0 = VN.canonicalize(IC->getOperand(0), Top); + Value *Op1 = VN.canonicalize(IC->getOperand(1), Top); ICmpInst::Predicate Pred = IC->getPredicate(); - if (isRelatedBy(Op0, Op1, Pred)) { + if (isRelatedBy(Op0, Op1, Pred)) add(IC, ConstantInt::getTrue(), ICmpInst::ICMP_EQ, NewContext); - } else if (isRelatedBy(Op0, Op1, ICmpInst::getInversePredicate(Pred))) { + else if (isRelatedBy(Op0, Op1, ICmpInst::getInversePredicate(Pred))) add(IC, ConstantInt::getFalse(), ICmpInst::ICMP_EQ, NewContext); - } } else if (SelectInst *SI = dyn_cast(I)) { if (I->getType()->isFPOrFPVector()) return; @@ -1688,30 +2105,55 @@ namespace { // %x EQ false then %a EQ %c // %b EQ %c then %a EQ %b - Value *Canonical = IG.canonicalize(SI->getCondition(), Top); + Value *Canonical = VN.canonicalize(SI->getCondition(), Top); if (Canonical == ConstantInt::getTrue()) { add(SI, SI->getTrueValue(), ICmpInst::ICMP_EQ, NewContext); } else if (Canonical == ConstantInt::getFalse()) { add(SI, SI->getFalseValue(), ICmpInst::ICMP_EQ, NewContext); - } else if (IG.canonicalize(SI->getTrueValue(), Top) == - IG.canonicalize(SI->getFalseValue(), Top)) { + } else if (VN.canonicalize(SI->getTrueValue(), Top) == + VN.canonicalize(SI->getFalseValue(), Top)) { add(SI, SI->getTrueValue(), ICmpInst::ICMP_EQ, NewContext); } } else if (CastInst *CI = dyn_cast(I)) { - const Type *Ty = CI->getDestTy(); - if (Ty->isFPOrFPVector()) return; + const Type *DestTy = CI->getDestTy(); + if (DestTy->isFPOrFPVector()) return; + + Value *Op = VN.canonicalize(CI->getOperand(0), Top); + Instruction::CastOps Opcode = CI->getOpcode(); - if (Constant *C = dyn_cast( - IG.canonicalize(CI->getOperand(0), Top))) { - add(CI, ConstantExpr::getCast(CI->getOpcode(), C, Ty), + if (Constant *C = dyn_cast(Op)) { + add(CI, ConstantExpr::getCast(Opcode, C, DestTy), ICmpInst::ICMP_EQ, NewContext); } - // TODO: "%a = cast ... %b" where %b is NE/LT/GT a constant. + uint32_t W = VR.typeToWidth(DestTy); + unsigned ci = VN.getOrInsertVN(CI, Top); + ConstantRange CR = VR.range(VN.getOrInsertVN(Op, Top), Top); + + if (!CR.isFullSet()) { + switch (Opcode) { + default: break; + case Instruction::ZExt: + VR.applyRange(ci, CR.zeroExtend(W), Top, this); + break; + case Instruction::SExt: + VR.applyRange(ci, CR.signExtend(W), Top, this); + break; + case Instruction::Trunc: { + ConstantRange Result = CR.truncate(W); + if (!Result.isFullSet()) + VR.applyRange(ci, Result, Top, this); + } break; + case Instruction::BitCast: + VR.applyRange(ci, CR, Top, this); + break; + // TODO: other casts? + } + } } else if (GetElementPtrInst *GEPI = dyn_cast(I)) { for (GetElementPtrInst::op_iterator OI = GEPI->idx_begin(), OE = GEPI->idx_end(); OI != OE; ++OI) { - ConstantInt *Op = dyn_cast(IG.canonicalize(*OI, Top)); + ConstantInt *Op = dyn_cast(VN.canonicalize(*OI, Top)); if (!Op || !Op->isZero()) return; } // TODO: The GEPI indices are all zero. Copy from operand to definition, @@ -1734,20 +2176,22 @@ namespace { Operation &O = WorkList.front(); TopInst = O.ContextInst; TopBB = O.ContextBB; - Top = Forest->getNodeForBlock(TopBB); + Top = DTDFS->getNodeForBlock(TopBB); // XXX move this into Context - O.LHS = IG.canonicalize(O.LHS, Top); - O.RHS = IG.canonicalize(O.RHS, Top); + O.LHS = VN.canonicalize(O.LHS, Top); + O.RHS = VN.canonicalize(O.RHS, Top); - assert(O.LHS == IG.canonicalize(O.LHS, Top) && "Canonicalize isn't."); - assert(O.RHS == IG.canonicalize(O.RHS, Top) && "Canonicalize isn't."); + assert(O.LHS == VN.canonicalize(O.LHS, Top) && "Canonicalize isn't."); + assert(O.RHS == VN.canonicalize(O.RHS, Top) && "Canonicalize isn't."); DOUT << "solving " << *O.LHS << " " << O.Op << " " << *O.RHS; if (O.ContextInst) DOUT << " context inst: " << *O.ContextInst; else DOUT << " context block: " << O.ContextBB->getName(); DOUT << "\n"; + DEBUG(VN.dump()); DEBUG(IG.dump()); + DEBUG(VR.dump()); // If they're both Constant, skip it. Check for contradiction and mark // the BB as unreachable if so. @@ -1762,7 +2206,7 @@ namespace { } } - if (compare(O.LHS, O.RHS)) { + if (VN.compare(O.LHS, O.RHS)) { std::swap(O.LHS, O.RHS); O.Op = ICmpInst::getSwappedPredicate(O.Op); } @@ -1784,10 +2228,10 @@ namespace { continue; } - unsigned n1 = IG.getNode(O.LHS, Top); - unsigned n2 = IG.getNode(O.RHS, Top); + unsigned n1 = VN.getOrInsertVN(O.LHS, Top); + unsigned n2 = VN.getOrInsertVN(O.RHS, Top); - if (n1 && n1 == n2) { + if (n1 == n2) { if (O.Op != ICmpInst::ICMP_UGE && O.Op != ICmpInst::ICMP_ULE && O.Op != ICmpInst::ICMP_SGE && O.Op != ICmpInst::ICMP_SLE) UB.mark(TopBB); @@ -1796,23 +2240,19 @@ namespace { continue; } - if (VR.isRelatedBy(O.LHS, O.RHS, Top, LV) || - (n1 && n2 && IG.isRelatedBy(n1, n2, Top, LV))) { + if (VR.isRelatedBy(n1, n2, Top, LV) || + IG.isRelatedBy(n1, n2, Top, LV)) { WorkList.pop_front(); continue; } - VR.addInequality(O.LHS, O.RHS, Top, LV, this); + VR.addInequality(n1, n2, Top, LV, this); if ((!isa(O.RHS) && !isa(O.LHS)) || - LV == NE) { - if (!n1) n1 = IG.newNode(O.LHS); - if (!n2) n2 = IG.newNode(O.RHS); + LV == NE) IG.addInequality(n1, n2, Top, LV); - } if (Instruction *I1 = dyn_cast(O.LHS)) { - if (below(I1) || - Top->DominatedBy(Forest->getNodeForBlock(I1->getParent()))) + if (aboveOrBelow(I1)) defToOps(I1); } if (isa(O.LHS) || isa(O.LHS)) { @@ -1820,16 +2260,13 @@ namespace { UE = O.LHS->use_end(); UI != UE;) { Use &TheUse = UI.getUse(); ++UI; - if (Instruction *I = dyn_cast(TheUse.getUser())) { - if (below(I) || - Top->DominatedBy(Forest->getNodeForBlock(I->getParent()))) - opsToDef(I); - } + Instruction *I = cast(TheUse.getUser()); + if (aboveOrBelow(I)) + opsToDef(I); } } if (Instruction *I2 = dyn_cast(O.RHS)) { - if (below(I2) || - Top->DominatedBy(Forest->getNodeForBlock(I2->getParent()))) + if (aboveOrBelow(I2)) defToOps(I2); } if (isa(O.RHS) || isa(O.RHS)) { @@ -1837,12 +2274,9 @@ namespace { UE = O.RHS->use_end(); UI != UE;) { Use &TheUse = UI.getUse(); ++UI; - if (Instruction *I = dyn_cast(TheUse.getUser())) { - if (below(I) || - Top->DominatedBy(Forest->getNodeForBlock(I->getParent()))) - - opsToDef(I); - } + Instruction *I = cast(TheUse.getUser()); + if (aboveOrBelow(I)) + opsToDef(I); } } } @@ -1857,56 +2291,58 @@ namespace { VRP->add(V, C, Pred, VRP->TopInst); } -#ifndef NDEBUG - bool ValueRanges::isCanonical(Value *V, ETNode *Subtree, VRPSolver *VRP) { - return V == VRP->IG.canonicalize(V, Subtree); + void ValueRanges::markBlock(VRPSolver *VRP) { + VRP->UB.mark(VRP->TopBB); } -#endif /// PredicateSimplifier - This class is a simplifier that replaces /// 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 { - DominatorTree *DT; - ETForest *Forest; + DomTreeDFS *DTDFS; bool modified; + ValueNumbering *VN; InequalityGraph *IG; UnreachableBlocks UB; ValueRanges *VR; - std::vector WorkList; + std::vector WorkList; public: + static char ID; // Pass identification, replacement for typeid + PredicateSimplifier() : FunctionPass(&ID) {} + bool runOnFunction(Function &F); virtual void getAnalysisUsage(AnalysisUsage &AU) const { AU.addRequiredID(BreakCriticalEdgesID); AU.addRequired(); - AU.addRequired(); AU.addRequired(); AU.addPreserved(); } private: - /// Forwards - Adds new properties into PropertySet and uses them to + /// Forwards - Adds new properties to VRPSolver and uses them to /// simplify instructions. Because new properties sometimes apply to /// a transition from one BasicBlock to another, this will use the /// PredicateSimplifier::proceedToSuccessor(s) interface to enter the - /// basic block with the new PropertySet. + /// basic block. /// @brief Performs abstract execution of the program. class VISIBILITY_HIDDEN Forwards : public InstVisitor { friend class InstVisitor; PredicateSimplifier *PS; - DominatorTree::Node *DTNode; + DomTreeDFS::Node *DTNode; public: + ValueNumbering &VN; InequalityGraph &IG; UnreachableBlocks &UB; ValueRanges &VR; - Forwards(PredicateSimplifier *PS, DominatorTree::Node *DTNode) - : PS(PS), DTNode(DTNode), IG(*PS->IG), UB(PS->UB), VR(*PS->VR) {} + Forwards(PredicateSimplifier *PS, DomTreeDFS::Node *DTNode) + : PS(PS), DTNode(DTNode), VN(*PS->VN), IG(*PS->IG), UB(PS->UB), + VR(*PS->VR) {} void visitTerminatorInst(TerminatorInst &TI); void visitBranchInst(BranchInst &BI); @@ -1926,52 +2362,56 @@ namespace { // Used by terminator instructions to proceed from the current basic // block to the next. Verifies that "current" dominates "next", // then calls visitBasicBlock. - void proceedToSuccessors(DominatorTree::Node *Current) { - for (DominatorTree::Node::iterator I = Current->begin(), + void proceedToSuccessors(DomTreeDFS::Node *Current) { + for (DomTreeDFS::Node::iterator I = Current->begin(), E = Current->end(); I != E; ++I) { WorkList.push_back(*I); } } - void proceedToSuccessor(DominatorTree::Node *Next) { + void proceedToSuccessor(DomTreeDFS::Node *Next) { WorkList.push_back(Next); } // Visits each instruction in the basic block. - void visitBasicBlock(DominatorTree::Node *Node) { + void visitBasicBlock(DomTreeDFS::Node *Node) { BasicBlock *BB = Node->getBlock(); - ETNode *ET = Forest->getNodeForBlock(BB); DOUT << "Entering Basic Block: " << BB->getName() - << " (" << ET->getDFSNumIn() << ")\n"; + << " (" << Node->getDFSNumIn() << ")\n"; for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E;) { - visitInstruction(I++, Node, ET); + visitInstruction(I++, Node); } } - // Tries to simplify each Instruction and add new properties to - // the PropertySet. - void visitInstruction(Instruction *I, DominatorTree::Node *DT, ETNode *ET) { + // Tries to simplify each Instruction and add new properties. + void visitInstruction(Instruction *I, DomTreeDFS::Node *DT) { DOUT << "Considering instruction " << *I << "\n"; + DEBUG(VN->dump()); DEBUG(IG->dump()); + DEBUG(VR->dump()); // Sometimes instructions are killed in earlier analysis. if (isInstructionTriviallyDead(I)) { ++NumSimple; modified = true; - IG->remove(I); + if (unsigned n = VN->valueNumber(I, DTDFS->getRootNode())) + if (VN->value(n) == I) IG->remove(n); + VN->remove(I); I->eraseFromParent(); return; } #ifndef NDEBUG // Try to replace the whole instruction. - Value *V = IG->canonicalize(I, ET); + Value *V = VN->canonicalize(I, DT); assert(V == I && "Late instruction canonicalization."); if (V != I) { modified = true; ++NumInstruction; DOUT << "Removing " << *I << ", replacing with " << *V << "\n"; - IG->remove(I); + if (unsigned n = VN->valueNumber(I, DTDFS->getRootNode())) + if (VN->value(n) == I) IG->remove(n); + VN->remove(I); I->replaceAllUsesWith(V); I->eraseFromParent(); return; @@ -1980,7 +2420,7 @@ namespace { // Try to substitute operands. for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) { Value *Oper = I->getOperand(i); - Value *V = IG->canonicalize(Oper, ET); + Value *V = VN->canonicalize(Oper, DT); assert(V == Oper && "Late operand canonicalization."); if (V != Oper) { modified = true; @@ -2001,29 +2441,29 @@ namespace { }; bool PredicateSimplifier::runOnFunction(Function &F) { - DT = &getAnalysis(); - Forest = &getAnalysis(); - + DominatorTree *DT = &getAnalysis(); + DTDFS = new DomTreeDFS(DT); TargetData *TD = &getAnalysis(); - Forest->updateDFSNumbers(); // XXX: should only act when numbers are out of date - DOUT << "Entering Function: " << F.getName() << "\n"; modified = false; - BasicBlock *RootBlock = &F.getEntryBlock(); - IG = new InequalityGraph(Forest->getNodeForBlock(RootBlock)); - VR = new ValueRanges(TD); - WorkList.push_back(DT->getRootNode()); + DomTreeDFS::Node *Root = DTDFS->getRootNode(); + VN = new ValueNumbering(DTDFS); + IG = new InequalityGraph(*VN, Root); + VR = new ValueRanges(*VN, TD); + WorkList.push_back(Root); do { - DominatorTree::Node *DTNode = WorkList.back(); + DomTreeDFS::Node *DTNode = WorkList.back(); WorkList.pop_back(); if (!UB.isDead(DTNode->getBlock())) visitBasicBlock(DTNode); } while (!WorkList.empty()); + delete DTDFS; delete VR; delete IG; + delete VN; modified |= UB.kill(); @@ -2049,24 +2489,28 @@ namespace { return; } - for (DominatorTree::Node::iterator I = DTNode->begin(), E = DTNode->end(); + for (DomTreeDFS::Node::iterator I = DTNode->begin(), E = DTNode->end(); I != E; ++I) { BasicBlock *Dest = (*I)->getBlock(); DOUT << "Branch thinking about %" << Dest->getName() - << "(" << PS->Forest->getNodeForBlock(Dest)->getDFSNumIn() << ")\n"; + << "(" << PS->DTDFS->getNodeForBlock(Dest)->getDFSNumIn() << ")\n"; if (Dest == TrueDest) { DOUT << "(" << DTNode->getBlock()->getName() << ") true set:\n"; - VRPSolver VRP(IG, UB, VR, PS->Forest, PS->modified, Dest); + VRPSolver VRP(VN, IG, UB, VR, PS->DTDFS, PS->modified, Dest); VRP.add(ConstantInt::getTrue(), Condition, ICmpInst::ICMP_EQ); VRP.solve(); + DEBUG(VN.dump()); DEBUG(IG.dump()); + DEBUG(VR.dump()); } else if (Dest == FalseDest) { DOUT << "(" << DTNode->getBlock()->getName() << ") false set:\n"; - VRPSolver VRP(IG, UB, VR, PS->Forest, PS->modified, Dest); + VRPSolver VRP(VN, IG, UB, VR, PS->DTDFS, PS->modified, Dest); VRP.add(ConstantInt::getFalse(), Condition, ICmpInst::ICMP_EQ); VRP.solve(); + DEBUG(VN.dump()); DEBUG(IG.dump()); + DEBUG(VR.dump()); } PS->proceedToSuccessor(*I); @@ -2079,13 +2523,13 @@ namespace { // Set the EQProperty in each of the cases BBs, and the NEProperties // in the default BB. - for (DominatorTree::Node::iterator I = DTNode->begin(), E = DTNode->end(); + for (DomTreeDFS::Node::iterator I = DTNode->begin(), E = DTNode->end(); I != E; ++I) { BasicBlock *BB = (*I)->getBlock(); DOUT << "Switch thinking about BB %" << BB->getName() - << "(" << PS->Forest->getNodeForBlock(BB)->getDFSNumIn() << ")\n"; + << "(" << PS->DTDFS->getNodeForBlock(BB)->getDFSNumIn() << ")\n"; - VRPSolver VRP(IG, UB, VR, PS->Forest, PS->modified, BB); + VRPSolver VRP(VN, IG, UB, VR, PS->DTDFS, PS->modified, BB); if (BB == SI.getDefaultDest()) { for (unsigned i = 1, e = SI.getNumCases(); i < e; ++i) if (SI.getSuccessor(i) != BB) @@ -2100,17 +2544,17 @@ namespace { } void PredicateSimplifier::Forwards::visitAllocaInst(AllocaInst &AI) { - VRPSolver VRP(IG, UB, VR, PS->Forest, PS->modified, &AI); + VRPSolver VRP(VN, IG, UB, VR, PS->DTDFS, PS->modified, &AI); VRP.add(Constant::getNullValue(AI.getType()), &AI, ICmpInst::ICMP_NE); VRP.solve(); } void PredicateSimplifier::Forwards::visitLoadInst(LoadInst &LI) { Value *Ptr = LI.getPointerOperand(); - // avoid "load uint* null" -> null NE null. + // avoid "load i8* null" -> null NE null. if (isa(Ptr)) return; - VRPSolver VRP(IG, UB, VR, PS->Forest, PS->modified, &LI); + VRPSolver VRP(VN, IG, UB, VR, PS->DTDFS, PS->modified, &LI); VRP.add(Constant::getNullValue(Ptr->getType()), Ptr, ICmpInst::ICMP_NE); VRP.solve(); } @@ -2119,30 +2563,27 @@ namespace { Value *Ptr = SI.getPointerOperand(); if (isa(Ptr)) return; - VRPSolver VRP(IG, UB, VR, PS->Forest, PS->modified, &SI); + VRPSolver VRP(VN, IG, UB, VR, PS->DTDFS, PS->modified, &SI); VRP.add(Constant::getNullValue(Ptr->getType()), Ptr, ICmpInst::ICMP_NE); VRP.solve(); } void PredicateSimplifier::Forwards::visitSExtInst(SExtInst &SI) { - VRPSolver VRP(IG, UB, VR, PS->Forest, PS->modified, &SI); + VRPSolver VRP(VN, IG, UB, VR, PS->DTDFS, PS->modified, &SI); uint32_t SrcBitWidth = cast(SI.getSrcTy())->getBitWidth(); uint32_t DstBitWidth = cast(SI.getDestTy())->getBitWidth(); - APInt Min(APInt::getSignedMinValue(SrcBitWidth)); - APInt Max(APInt::getSignedMaxValue(SrcBitWidth)); - Min.sext(DstBitWidth); - Max.sext(DstBitWidth); + APInt Min(APInt::getHighBitsSet(DstBitWidth, DstBitWidth-SrcBitWidth+1)); + APInt Max(APInt::getLowBitsSet(DstBitWidth, SrcBitWidth-1)); VRP.add(ConstantInt::get(Min), &SI, ICmpInst::ICMP_SLE); VRP.add(ConstantInt::get(Max), &SI, ICmpInst::ICMP_SGE); VRP.solve(); } void PredicateSimplifier::Forwards::visitZExtInst(ZExtInst &ZI) { - VRPSolver VRP(IG, UB, VR, PS->Forest, PS->modified, &ZI); + VRPSolver VRP(VN, IG, UB, VR, PS->DTDFS, PS->modified, &ZI); uint32_t SrcBitWidth = cast(ZI.getSrcTy())->getBitWidth(); uint32_t DstBitWidth = cast(ZI.getDestTy())->getBitWidth(); - APInt Max(APInt::getMaxValue(SrcBitWidth)); - Max.zext(DstBitWidth); + APInt Max(APInt::getLowBitsSet(DstBitWidth, SrcBitWidth)); VRP.add(ConstantInt::get(Max), &ZI, ICmpInst::ICMP_UGE); VRP.solve(); } @@ -2157,7 +2598,7 @@ namespace { case Instruction::UDiv: case Instruction::SDiv: { Value *Divisor = BO.getOperand(1); - VRPSolver VRP(IG, UB, VR, PS->Forest, PS->modified, &BO); + VRPSolver VRP(VN, IG, UB, VR, PS->DTDFS, PS->modified, &BO); VRP.add(Constant::getNullValue(Divisor->getType()), Divisor, ICmpInst::ICMP_NE); VRP.solve(); @@ -2168,34 +2609,34 @@ namespace { switch (ops) { default: break; case Instruction::Shl: { - VRPSolver VRP(IG, UB, VR, PS->Forest, PS->modified, &BO); + VRPSolver VRP(VN, IG, UB, VR, PS->DTDFS, PS->modified, &BO); VRP.add(&BO, BO.getOperand(0), ICmpInst::ICMP_UGE); VRP.solve(); } break; case Instruction::AShr: { - VRPSolver VRP(IG, UB, VR, PS->Forest, PS->modified, &BO); + VRPSolver VRP(VN, IG, UB, VR, PS->DTDFS, PS->modified, &BO); VRP.add(&BO, BO.getOperand(0), ICmpInst::ICMP_SLE); VRP.solve(); } break; case Instruction::LShr: case Instruction::UDiv: { - VRPSolver VRP(IG, UB, VR, PS->Forest, PS->modified, &BO); + VRPSolver VRP(VN, IG, UB, VR, PS->DTDFS, PS->modified, &BO); VRP.add(&BO, BO.getOperand(0), ICmpInst::ICMP_ULE); VRP.solve(); } break; case Instruction::URem: { - VRPSolver VRP(IG, UB, VR, PS->Forest, PS->modified, &BO); + VRPSolver VRP(VN, IG, UB, VR, PS->DTDFS, PS->modified, &BO); VRP.add(&BO, BO.getOperand(1), ICmpInst::ICMP_ULE); VRP.solve(); } break; case Instruction::And: { - VRPSolver VRP(IG, UB, VR, PS->Forest, PS->modified, &BO); + VRPSolver VRP(VN, IG, UB, VR, PS->DTDFS, PS->modified, &BO); VRP.add(&BO, BO.getOperand(0), ICmpInst::ICMP_ULE); VRP.add(&BO, BO.getOperand(1), ICmpInst::ICMP_ULE); VRP.solve(); } break; case Instruction::Or: { - VRPSolver VRP(IG, UB, VR, PS->Forest, PS->modified, &BO); + VRPSolver VRP(VN, IG, UB, VR, PS->DTDFS, PS->modified, &BO); VRP.add(&BO, BO.getOperand(0), ICmpInst::ICMP_UGE); VRP.add(&BO, BO.getOperand(1), ICmpInst::ICMP_UGE); VRP.solve(); @@ -2221,7 +2662,7 @@ namespace { case ICmpInst::ICMP_SGE: Pred = ICmpInst::ICMP_SGT; break; } if (Pred != IC.getPredicate()) { - VRPSolver VRP(IG, UB, VR, PS->Forest, PS->modified, &IC); + VRPSolver VRP(VN, IG, UB, VR, PS->DTDFS, PS->modified, &IC); if (VRP.isRelatedBy(IC.getOperand(1), IC.getOperand(0), ICmpInst::ICMP_NE)) { ++NumSnuggle; @@ -2239,26 +2680,29 @@ namespace { case ICmpInst::ICMP_SLT: case ICmpInst::ICMP_ULT: if (Op1->getValue() != 0) - NextVal = cast(ConstantExpr::getSub( - Op1, ConstantInt::get(Op1->getType(), 1))); + NextVal = ConstantInt::get(Op1->getValue()-1); break; case ICmpInst::ICMP_SGT: case ICmpInst::ICMP_UGT: if (!Op1->getValue().isAllOnesValue()) - NextVal = cast(ConstantExpr::getAdd( - Op1, ConstantInt::get(Op1->getType(), 1))); + NextVal = ConstantInt::get(Op1->getValue()+1); break; - } + if (NextVal) { - VRPSolver VRP(IG, UB, VR, PS->Forest, PS->modified, &IC); + VRPSolver VRP(VN, IG, UB, VR, PS->DTDFS, PS->modified, &IC); if (VRP.isRelatedBy(IC.getOperand(0), NextVal, ICmpInst::getInversePredicate(Pred))) { - ICmpInst *NewIC = new ICmpInst(ICmpInst::ICMP_EQ, IC.getOperand(0), - NextVal, "", &IC); + ICmpInst *NewIC = new ICmpInst(&IC, ICmpInst::ICMP_EQ, + IC.getOperand(0), NextVal, ""); NewIC->takeName(&IC); IC.replaceAllUsesWith(NewIC); - IG.remove(&IC); // XXX: prove this isn't necessary + + // XXX: prove this isn't necessary + if (unsigned n = VN.valueNumber(&IC, PS->DTDFS->getRootNode())) + if (VN.value(n) == &IC) IG.remove(n); + VN.remove(&IC); + IC.eraseFromParent(); ++NumSnuggle; PS->modified = true; @@ -2266,11 +2710,12 @@ namespace { } } } - - RegisterPass X("predsimplify", - "Predicate Simplifier"); } +char PredicateSimplifier::ID = 0; +static RegisterPass +X("predsimplify", "Predicate Simplifier"); + FunctionPass *llvm::createPredicateSimplifierPass() { return new PredicateSimplifier(); }