[llvm-commits] CVS: llvm/lib/Transforms/Scalar/PredicateSimplifier.cpp

Nick Lewycky nicholas at mxc.ca
Wed Sep 20 10:04:18 PDT 2006



Changes in directory llvm/lib/Transforms/Scalar:

PredicateSimplifier.cpp updated: 1.11 -> 1.12
---
Log message:

Use a total ordering to compare instructions.
Fixes infinite loop in resolve().


---
Diffs of the changes:  (+101 -87)

 PredicateSimplifier.cpp |  188 +++++++++++++++++++++++++-----------------------
 1 files changed, 101 insertions(+), 87 deletions(-)


Index: llvm/lib/Transforms/Scalar/PredicateSimplifier.cpp
diff -u llvm/lib/Transforms/Scalar/PredicateSimplifier.cpp:1.11 llvm/lib/Transforms/Scalar/PredicateSimplifier.cpp:1.12
--- llvm/lib/Transforms/Scalar/PredicateSimplifier.cpp:1.11	Mon Sep 18 16:09:35 2006
+++ llvm/lib/Transforms/Scalar/PredicateSimplifier.cpp	Wed Sep 20 12:04:01 2006
@@ -49,60 +49,30 @@
   Statistic<>
   NumInstruction("predsimplify", "Number of instructions removed");
 
-  /// Returns true if V1 is a better choice than V2. Note that it is
-  /// not a total ordering.
-  struct compare {
-    bool operator()(Value *V1, Value *V2) const {
-      if (isa<Constant>(V1)) {
-        if (!isa<Constant>(V2)) {
-          return true;
-        }
-      } else if (isa<Argument>(V1)) {
-        if (!isa<Constant>(V2) && !isa<Argument>(V2)) {
-          return true;
-        }
-      }
-      if (User *U = dyn_cast<User>(V2)) {
-        for (User::const_op_iterator I = U->op_begin(), E = U->op_end();
-             I != E; ++I) {
-          if (*I == V1) {
-            return true;
-          }
-        }
-      }
-      return false;
-    }
-  };
-
-  /// Used for choosing the canonical Value in a synonym set.
-  /// Leaves the better choice in V1.
-  static void order(Value *&V1, Value *&V2) {
-    static compare c;
-    if (c(V2, V1))
-      std::swap(V1, V2);
-  }
+  class PropertySet;
 
   /// Similar to EquivalenceClasses, this stores the set of equivalent
-  /// types. Beyond EquivalenceClasses, it allows the user to specify
-  /// which element will act as leader through a StrictWeakOrdering
-  /// function.
-  template<typename ElemTy, typename StrictWeak>
+  /// types. Beyond EquivalenceClasses, it allows us to specify which
+  /// element will act as leader.
+  template<typename ElemTy>
   class VISIBILITY_HIDDEN Synonyms {
     std::map<ElemTy, unsigned> mapping;
     std::vector<ElemTy> leaders;
-    StrictWeak swo;
+    PropertySet *PS;
 
   public:
     typedef unsigned iterator;
     typedef const unsigned const_iterator;
 
+    Synonyms(PropertySet *PS) : PS(PS) {}
+
     // Inspection
 
     bool empty() const {
       return leaders.empty();
     }
 
-    unsigned countLeaders() const {
+    typename std::vector<ElemTy>::size_type countLeaders() const {
       return leaders.size();
     }
 
@@ -151,50 +121,8 @@
     /// Combine two sets referring to the same element, inserting the
     /// elements as needed. Returns a valid iterator iff two already
     /// existing disjoint synonym sets were combined. The iterator
-    /// points to the removed element.
-    iterator unionSets(ElemTy E1, ElemTy E2) {
-      if (swo(E2, E1)) std::swap(E1, E2);
-
-      iterator I1 = findLeader(E1),
-               I2 = findLeader(E2);
-
-      if (!I1 && !I2) { // neither entry is in yet
-        leaders.push_back(E1);
-        I1 = leaders.size();
-        mapping[E1] = I1;
-        mapping[E2] = I1;
-        return 0;
-      }
-
-      if (!I1 && I2) {
-        mapping[E1] = I2;
-        std::swap(getLeader(I2), E1);
-        return 0;
-      }
-
-      if (I1 && !I2) {
-        mapping[E2] = I1;
-        return 0;
-      }
-
-      if (I1 == I2) return 0;
-
-      // This is the case where we have two sets, [%a1, %a2, %a3] and
-      // [%p1, %p2, %p3] and someone says that %a2 == %p3. We need to
-      // combine the two synsets.
-
-      if (I1 > I2) --I1;
-
-      for (std::map<Value *, unsigned>::iterator I = mapping.begin(),
-           E = mapping.end(); I != E; ++I) {
-        if (I->second == I2) I->second = I1;
-        else if (I->second > I2) --I->second;
-      }
-
-      leaders.erase(leaders.begin() + I2 - 1);
-
-      return I2;
-    }
+    /// points to the no longer existing element.
+    iterator unionSets(ElemTy E1, ElemTy E2);
 
     /// Returns an iterator pointing to the synonym set containing
     /// element e. If none exists, a new one is created and returned.
@@ -212,13 +140,51 @@
   /// Represents the set of equivalent Value*s and provides insertion
   /// and fast lookup. Also stores the set of inequality relationships.
   class PropertySet {
+    /// Returns true if V1 is a better choice than V2. Note that it is
+    /// not a total ordering.
+    bool compare(Value *V1, Value *V2) const {
+      if (isa<Constant>(V1)) {
+        if (!isa<Constant>(V2)) {
+          return true;
+        }
+      } else if (isa<Argument>(V1)) {
+        if (!isa<Constant>(V2) && !isa<Argument>(V2)) {
+          return true;
+        }
+      }
+      if (Instruction *I1 = dyn_cast<Instruction>(V1)) {
+        if (Instruction *I2 = dyn_cast<Instruction>(V2)) {
+          BasicBlock *BB1 = I1->getParent(),
+                     *BB2 = I2->getParent();
+          if (BB1 == BB2) {
+            for (BasicBlock::const_iterator I = BB1->begin(), E = BB1->end();
+                 I != E; ++I) {
+              if (&*I == I1) return true;
+              if (&*I == I2) return false;
+            }
+            assert(0 && "Instructions not found in parent BasicBlock?");
+          } else
+            return DT->getNode(BB1)->properlyDominates(DT->getNode(BB2));
+        }
+      }
+      return false;
+    }
+
     struct Property;
   public:
-    class Synonyms<Value *, compare> union_find;
+    /// Choose the canonical Value in a synonym set.
+    /// Leaves the more canonical choice in V1.
+    void order(Value *&V1, Value *&V2) const {
+      if (compare(V2, V1)) std::swap(V1, V2);
+    }
+
+    PropertySet(DominatorTree *DT) : union_find(this), DT(DT) {}
+
+    class Synonyms<Value *> union_find;
 
     typedef std::vector<Property>::iterator       PropertyIterator;
     typedef std::vector<Property>::const_iterator ConstPropertyIterator;
-    typedef Synonyms<Value *, compare>::iterator  SynonymIterator;
+    typedef Synonyms<Value *>::iterator  SynonymIterator;
 
     enum Ops {
       EQ,
@@ -231,7 +197,7 @@
     }
 
     Value *lookup(Value *V) const {
-      Synonyms<Value *, compare>::iterator SI = union_find.findLeader(V);
+      SynonymIterator SI = union_find.findLeader(V);
       if (!SI) return NULL;
       return union_find.getLeader(SI);
     }
@@ -313,7 +279,7 @@
     // Represents Head OP [Tail1, Tail2, ...]
     // For example: %x != %a, %x != %b.
     struct VISIBILITY_HIDDEN Property {
-      typedef Synonyms<Value *, compare>::iterator Iter;
+      typedef SynonymIterator Iter;
 
       Property(Ops opcode, Iter i1, Iter i2)
         : Opcode(opcode), I1(i1), I2(i2)
@@ -421,6 +387,7 @@
       }
     }
 
+    DominatorTree *DT;
   public:
 #ifdef DEBUG
     void debug(std::ostream &os) const {
@@ -484,6 +451,52 @@
 
   RegisterPass<PredicateSimplifier> X("predsimplify",
                                       "Predicate Simplifier");
+
+  template <typename ElemTy>
+  typename Synonyms<ElemTy>::iterator
+  Synonyms<ElemTy>::unionSets(ElemTy E1, ElemTy E2) {
+    PS->order(E1, E2);
+
+    iterator I1 = findLeader(E1),
+             I2 = findLeader(E2);
+
+    if (!I1 && !I2) { // neither entry is in yet
+      leaders.push_back(E1);
+      I1 = leaders.size();
+      mapping[E1] = I1;
+      mapping[E2] = I1;
+      return 0;
+    }
+
+    if (!I1 && I2) {
+      mapping[E1] = I2;
+      std::swap(getLeader(I2), E1);
+      return 0;
+    }
+
+    if (I1 && !I2) {
+      mapping[E2] = I1;
+      return 0;
+    }
+
+    if (I1 == I2) return 0;
+
+    // This is the case where we have two sets, [%a1, %a2, %a3] and
+    // [%p1, %p2, %p3] and someone says that %a2 == %p3. We need to
+    // combine the two synsets.
+
+    if (I1 > I2) --I1;
+
+    for (std::map<Value *, unsigned>::iterator I = mapping.begin(),
+         E = mapping.end(); I != E; ++I) {
+      if (I->second == I2) I->second = I1;
+      else if (I->second > I2) --I->second;
+    }
+
+    leaders.erase(leaders.begin() + I2 - 1);
+
+    return I2;
+  }
 }
 
 FunctionPass *llvm::createPredicateSimplifierPass() {
@@ -494,7 +507,7 @@
   DT = &getAnalysis<DominatorTree>();
 
   modified = false;
-  PropertySet KnownProperties;
+  PropertySet KnownProperties(DT);
   visitBasicBlock(DT->getRootNode()->getBlock(), KnownProperties);
   return modified;
 }
@@ -614,6 +627,7 @@
   if (V != I) {
     modified = true;
     ++NumInstruction;
+    DEBUG(std::cerr << "Removing " << *I);
     I->replaceAllUsesWith(V);
     I->eraseFromParent();
     return;






More information about the llvm-commits mailing list