From 29a05b6a715a289a01562ced8e468a0c719b112b Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Thu, 5 Jul 2007 03:15:00 +0000 Subject: [PATCH] Break "variable canonicalization" out of InequalityGraph and into its own class "ValueNumbering". git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@37881 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Scalar/PredicateSimplifier.cpp | 554 +++++++++--------- 1 file changed, 286 insertions(+), 268 deletions(-) diff --git a/lib/Transforms/Scalar/PredicateSimplifier.cpp b/lib/Transforms/Scalar/PredicateSimplifier.cpp index 91a3344f989..6b5af293dc0 100644 --- a/lib/Transforms/Scalar/PredicateSimplifier.cpp +++ b/lib/Transforms/Scalar/PredicateSimplifier.cpp @@ -148,7 +148,7 @@ namespace { unsigned spread = DFSout - DFSin; unsigned N_spread = N.DFSout - N.DFSin; if (spread == N_spread) return DFSin < N.DFSin; - else return DFSout - DFSin < N.DFSout - N.DFSin; + return spread < N_spread; } bool operator>(const Node &N) const { return N < *this; } @@ -215,7 +215,7 @@ namespace { Node *getNodeForBlock(BasicBlock *BB) const { if (!NodeMap.count(BB)) return 0; - else return const_cast(this)->NodeMap[BB]; + return const_cast(this)->NodeMap[BB]; } bool dominates(Instruction *I1, Instruction *I2) { @@ -236,8 +236,7 @@ namespace { } else { Node *Node1 = getNodeForBlock(BB1), *Node2 = getNodeForBlock(BB2); - if (!Node1 || !Node2) return false; - return Node1->dominates(Node2); + return Node1 && Node2 && Node1->dominates(Node2); } } private: @@ -361,6 +360,163 @@ namespace { return Rev; } + /// ValueNumbering stores the scope-specific value numbers for a given Value. + class VISIBILITY_HIDDEN ValueNumbering { + 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; + } + }; + + typedef std::vector VNMapType; + VNMapType VNMap; + + std::vector Values; + + DomTreeDFS *DTDFS; + + public: + /// 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) { + 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; + } + + /// newVN - creates a new value number. Value V must not already have a + /// value number assigned. + unsigned newVN(Value *V) { + Values.push_back(V); + + VNPair pair = VNPair(V, Values.size(), DTDFS->getRootNode()); + assert(!std::binary_search(VNMap.begin(), VNMap.end(), pair) && + "Attempt to create a duplicate value number."); + VNMap.insert(std::lower_bound(VNMap.begin(), VNMap.end(), pair), 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(); + VNPair pair(V, 0, DTDFS->getRootNode()); + VNMapType::iterator J = std::upper_bound(B, VNMap.end(), pair); + VNMapType::iterator I = J; + + while (I != B && I->V == V) --I; + + VNMap.erase(I, J); + } + }; + /// The InequalityGraph stores the relationships between values. /// Each Value in the graph is assigned to a Node. Nodes are pointer /// comparable for equality. The caller is expected to maintain the logical @@ -369,12 +525,14 @@ namespace { /// The InequalityGraph class may invalidate Node*s after any mutator call. /// @brief The InequalityGraph stores the relationships between values. class VISIBILITY_HIDDEN InequalityGraph { + ValueNumbering &VN; DomTreeDFS::Node *TreeRoot; InequalityGraph(); // DO NOT IMPLEMENT InequalityGraph(InequalityGraph &); // DO NOT IMPLEMENT public: - explicit InequalityGraph(DomTreeDFS::Node *TreeRoot) : TreeRoot(TreeRoot){} + InequalityGraph(ValueNumbering &VN, DomTreeDFS::Node *TreeRoot) + : VN(VN), TreeRoot(TreeRoot) {} class Node; @@ -393,7 +551,7 @@ namespace { bool operator<(const Edge &edge) const { if (To != edge.To) return To < edge.To; - else return *Subtree < *edge.Subtree; + return *Subtree < *edge.Subtree; } bool operator<(unsigned to) const { @@ -419,8 +577,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); } @@ -429,33 +585,29 @@ 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() << ")"; + if (NI != NE) os << ", "; } } + public: #endif - public: iterator begin() { return Relations.begin(); } iterator end() { return Relations.end(); } const_iterator begin() const { return Relations.begin(); } @@ -481,11 +633,6 @@ 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. @@ -525,31 +672,6 @@ namespace { }; private: - struct VISIBILITY_HIDDEN NodeMapEdge { - Value *V; - unsigned index; - DomTreeDFS::Node *Subtree; - - NodeMapEdge(Value *V, unsigned index, DomTreeDFS::Node *Subtree) - : V(V), index(index), Subtree(Subtree) {} - - bool operator==(const NodeMapEdge &RHS) const { - return V == RHS.V && - Subtree == RHS.Subtree; - } - - bool operator<(const NodeMapEdge &RHS) const { - if (V != RHS.V) return V < RHS.V; - else return *Subtree < *RHS.Subtree; - } - - bool operator<(Value *RHS) const { - return V < RHS; - } - }; - - typedef std::vector NodeMapType; - NodeMapType NodeMap; std::vector Nodes; @@ -563,53 +685,15 @@ namespace { return &Nodes[index-1]; } - /// Returns the node currently representing Value V, or zero if no such - /// node exists. - unsigned getNode(Value *V, DomTreeDFS::Node *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, DomTreeDFS::Node *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) { - assert(!isa(V) && "BBs may not be nodes."); + assert((isa(V) || isa(V) || isa(V)) && + "Bad Value for node."); assert(V->getType() != Type::VoidTy && "Void node?"); - 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, DomTreeDFS::Node *Subtree) { - if (isa(V)) return V; - - if (unsigned n = getNode(V, Subtree)) - return node(n)->getValue(); - else - return V; + unsigned n = VN.newVN(V); + if (Nodes.size() < n) Nodes.resize(n); + return n; } /// isRelatedBy - true iff n1 op n2 @@ -627,53 +711,6 @@ 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, DomTreeDFS::Node *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, DomTreeDFS::Node *Subtree, @@ -776,28 +813,18 @@ namespace { 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 @@ -807,19 +834,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 }; @@ -842,7 +862,7 @@ namespace { bool operator<(const ScopedRange &range) const { if (V != range.V) return V < range.V; - else return *Subtree < *range.Subtree; + return *Subtree < *range.Subtree; } bool operator<(const Value *value) const { @@ -1303,6 +1323,7 @@ namespace { }; std::deque WorkList; + ValueNumbering &VN; InequalityGraph &IG; UnreachableBlocks &UB; ValueRanges &VR; @@ -1314,26 +1335,6 @@ namespace { typedef InequalityGraph::Node Node; - /// 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); - } - // below - true if the Instruction is dominated by the current context // block or instruction bool below(Instruction *I) { @@ -1382,17 +1383,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."); @@ -1436,8 +1437,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; @@ -1459,7 +1460,7 @@ 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); @@ -1524,7 +1525,7 @@ namespace { 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); } @@ -1559,11 +1560,11 @@ namespace { // 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); } } @@ -1571,7 +1572,7 @@ 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 (aboveOrBelow(I2)) @@ -1639,9 +1640,11 @@ namespace { } public: - VRPSolver(InequalityGraph &IG, UnreachableBlocks &UB, ValueRanges &VR, - DomTreeDFS *DTDFS, 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), DTDFS(DTDFS), @@ -1653,9 +1656,11 @@ namespace { assert(Top && "VRPSolver created for unreachable basic block."); } - VRPSolver(InequalityGraph &IG, UnreachableBlocks &UB, ValueRanges &VR, - DomTreeDFS *DTDFS, 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), DTDFS(DTDFS), @@ -1674,8 +1679,8 @@ namespace { return ConstantExpr::getCompare(Pred, C1, C2) == ConstantInt::getTrue(); - if (unsigned n1 = IG.getNode(V1, Top)) - if (unsigned n2 = IG.getNode(V2, Top)) { + if (unsigned n1 = VN.valueNumber(V1, Top)) + if (unsigned n2 = VN.valueNumber(V2, Top)) { if (n1 == n2) return Pred == ICmpInst::ICMP_EQ || Pred == ICmpInst::ICMP_ULE || Pred == ICmpInst::ICMP_UGE || @@ -1710,14 +1715,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. @@ -1786,11 +1791,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); @@ -1798,7 +1803,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, @@ -1812,7 +1817,7 @@ namespace { } else if (CastInst *CI = dyn_cast(I)) { const Type *SrcTy = CI->getSrcTy(); - Value *TheCI = IG.canonicalize(CI, Top); + Value *TheCI = VN.canonicalize(CI, Top); uint32_t W = VR.typeToWidth(SrcTy); if (!W) return; ConstantRange CR = VR.rangeFromValue(TheCI, Top, W); @@ -1823,11 +1828,11 @@ namespace { default: break; case Instruction::ZExt: case Instruction::SExt: - VR.applyRange(IG.canonicalize(CI->getOperand(0), Top), + VR.applyRange(VN.canonicalize(CI->getOperand(0), Top), CR.truncate(W), Top, this); break; case Instruction::BitCast: - VR.applyRange(IG.canonicalize(CI->getOperand(0), Top), + VR.applyRange(VN.canonicalize(CI->getOperand(0), Top), CR, Top, this); break; } @@ -1841,8 +1846,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)) { @@ -1912,7 +1917,7 @@ namespace { // "%x = udiv i32 %y, %z" and %x EQ %y 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) { @@ -1947,8 +1952,8 @@ 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)) { @@ -1965,20 +1970,20 @@ 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 *DestTy = CI->getDestTy(); if (DestTy->isFPOrFPVector()) return; - Value *Op = IG.canonicalize(CI->getOperand(0), Top); + Value *Op = VN.canonicalize(CI->getOperand(0), Top); Instruction::CastOps Opcode = CI->getOpcode(); if (Constant *C = dyn_cast(Op)) { @@ -1987,7 +1992,7 @@ namespace { } uint32_t W = VR.typeToWidth(DestTy); - Value *TheCI = IG.canonicalize(CI, Top); + Value *TheCI = VN.canonicalize(CI, Top); ConstantRange CR = VR.rangeFromValue(Op, Top, W); if (!CR.isFullSet()) { @@ -2013,7 +2018,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 operand to definition, @@ -2038,11 +2043,11 @@ namespace { TopBB = O.ContextBB; 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; @@ -2064,7 +2069,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); } @@ -2086,8 +2091,8 @@ namespace { continue; } - unsigned n1 = IG.getNode(O.LHS, Top); - unsigned n2 = IG.getNode(O.RHS, Top); + unsigned n1 = VN.valueNumber(O.LHS, Top); + unsigned n2 = VN.valueNumber(O.RHS, Top); if (n1 && n1 == n2) { if (O.Op != ICmpInst::ICMP_UGE && O.Op != ICmpInst::ICMP_ULE && @@ -2161,7 +2166,7 @@ namespace { #ifndef NDEBUG bool ValueRanges::isCanonical(Value *V, DomTreeDFS::Node *Subtree, VRPSolver *VRP) { - return V == VRP->IG.canonicalize(V, Subtree); + return V == VRP->VN.canonicalize(V, Subtree); } #endif @@ -2172,6 +2177,7 @@ namespace { class VISIBILITY_HIDDEN PredicateSimplifier : public FunctionPass { DomTreeDFS *DTDFS; bool modified; + ValueNumbering *VN; InequalityGraph *IG; UnreachableBlocks UB; ValueRanges *VR; @@ -2204,12 +2210,14 @@ namespace { DomTreeDFS::Node *DTNode; public: + ValueNumbering &VN; InequalityGraph &IG; UnreachableBlocks &UB; ValueRanges &VR; Forwards(PredicateSimplifier *PS, DomTreeDFS::Node *DTNode) - : PS(PS), DTNode(DTNode), IG(*PS->IG), UB(PS->UB), VR(*PS->VR) {} + : PS(PS), DTNode(DTNode), VN(*PS->VN), IG(*PS->IG), UB(PS->UB), + VR(*PS->VR) {} void visitTerminatorInst(TerminatorInst &TI); void visitBranchInst(BranchInst &BI); @@ -2260,20 +2268,24 @@ namespace { 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, DT); + 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; @@ -2282,7 +2294,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, DT); + Value *V = VN->canonicalize(Oper, DT); assert(V == Oper && "Late operand canonicalization."); if (V != Oper) { modified = true; @@ -2311,7 +2323,8 @@ namespace { modified = false; DomTreeDFS::Node *Root = DTDFS->getRootNode(); - IG = new InequalityGraph(Root); + VN = new ValueNumbering(DTDFS); + IG = new InequalityGraph(*VN, Root); VR = new ValueRanges(TD); WorkList.push_back(Root); @@ -2357,13 +2370,13 @@ namespace { if (Dest == TrueDest) { DOUT << "(" << DTNode->getBlock()->getName() << ") true set:\n"; - VRPSolver VRP(IG, UB, VR, PS->DTDFS, 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(IG.dump()); } else if (Dest == FalseDest) { DOUT << "(" << DTNode->getBlock()->getName() << ") false set:\n"; - VRPSolver VRP(IG, UB, VR, PS->DTDFS, 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(IG.dump()); @@ -2385,7 +2398,7 @@ namespace { DOUT << "Switch thinking about BB %" << BB->getName() << "(" << PS->DTDFS->getNodeForBlock(BB)->getDFSNumIn() << ")\n"; - VRPSolver VRP(IG, UB, VR, PS->DTDFS, 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) @@ -2400,7 +2413,7 @@ namespace { } void PredicateSimplifier::Forwards::visitAllocaInst(AllocaInst &AI) { - VRPSolver VRP(IG, UB, VR, PS->DTDFS, 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(); } @@ -2410,7 +2423,7 @@ namespace { // avoid "load uint* null" -> null NE null. if (isa(Ptr)) return; - VRPSolver VRP(IG, UB, VR, PS->DTDFS, 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(); } @@ -2419,13 +2432,13 @@ namespace { Value *Ptr = SI.getPointerOperand(); if (isa(Ptr)) return; - VRPSolver VRP(IG, UB, VR, PS->DTDFS, 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->DTDFS, 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::getHighBitsSet(DstBitWidth, DstBitWidth-SrcBitWidth+1)); @@ -2436,7 +2449,7 @@ namespace { } void PredicateSimplifier::Forwards::visitZExtInst(ZExtInst &ZI) { - VRPSolver VRP(IG, UB, VR, PS->DTDFS, 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::getLowBitsSet(DstBitWidth, SrcBitWidth)); @@ -2454,7 +2467,7 @@ namespace { case Instruction::UDiv: case Instruction::SDiv: { Value *Divisor = BO.getOperand(1); - VRPSolver VRP(IG, UB, VR, PS->DTDFS, 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(); @@ -2465,34 +2478,34 @@ namespace { switch (ops) { default: break; case Instruction::Shl: { - VRPSolver VRP(IG, UB, VR, PS->DTDFS, 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->DTDFS, 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->DTDFS, 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->DTDFS, 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->DTDFS, 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->DTDFS, 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(); @@ -2518,7 +2531,7 @@ namespace { case ICmpInst::ICMP_SGE: Pred = ICmpInst::ICMP_SGT; break; } if (Pred != IC.getPredicate()) { - VRPSolver VRP(IG, UB, VR, PS->DTDFS, 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; @@ -2546,14 +2559,19 @@ namespace { } if (NextVal) { - VRPSolver VRP(IG, UB, VR, PS->DTDFS, 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); 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;