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

Nick Lewycky nicholas at mxc.ca
Sat Sep 2 12:40:53 PDT 2006



Changes in directory llvm/lib/Transforms/Scalar:

PredicateSimplifier.cpp updated: 1.4 -> 1.5
---
Log message:

Improve handling of SelectInst.
Reorder operations to remove duplicated work.
Fix to leave floating-point types out of the optimization.
Add tests to predsimplify.ll for SwitchInst and SelectInst handling.


---
Diffs of the changes:  (+44 -31)

 PredicateSimplifier.cpp |   75 ++++++++++++++++++++++++++++--------------------
 1 files changed, 44 insertions(+), 31 deletions(-)


Index: llvm/lib/Transforms/Scalar/PredicateSimplifier.cpp
diff -u llvm/lib/Transforms/Scalar/PredicateSimplifier.cpp:1.4 llvm/lib/Transforms/Scalar/PredicateSimplifier.cpp:1.5
--- llvm/lib/Transforms/Scalar/PredicateSimplifier.cpp:1.4	Thu Aug 31 22:26:35 2006
+++ llvm/lib/Transforms/Scalar/PredicateSimplifier.cpp	Sat Sep  2 14:40:37 2006
@@ -28,9 +28,6 @@
 //
 //===------------------------------------------------------------------===//
 
-// TODO:
-// * Check handling of NAN in floating point types
-
 #define DEBUG_TYPE "predsimplify"
 #include "llvm/Transforms/Scalar.h"
 #include "llvm/Constants.h"
@@ -112,14 +109,22 @@
     }
 
     void addEqual(Value *V1, Value *V2) {
+      // If %x = 0. and %y = -0., seteq %x, %y is true, but
+      // copysign(%x) is not the same as copysign(%y).
+      if (V2->getType()->isFloatingPoint()) return;
+
       order(V1, V2);
       if (isa<Constant>(V2)) return; // refuse to set false == true.
 
+      DEBUG(std::cerr << "equal: " << *V1 << " and " << *V2 << "\n");
       union_find.unionSets(V1, V2);
       addImpliedProperties(EQ, V1, V2);
     }
 
     void addNotEqual(Value *V1, Value *V2) {
+      // If %x = NAN then seteq %x, %x is false.
+      if (V2->getType()->isFloatingPoint()) return;
+
       DEBUG(std::cerr << "not equal: " << *V1 << " and " << *V2 << "\n");
       if (findProperty(NE, V1, V2) != Properties.end())
         return; // found.
@@ -180,15 +185,9 @@
     struct Property {
       Property(Ops opcode, Value *v1, Value *v2)
         : Opcode(opcode), V1(v1), V2(v2)
-      { assert(opcode != EQ && "Equality belongs in the synonym set,"
+      { assert(opcode != EQ && "Equality belongs in the synonym set, "
                "not a property."); }
 
-      bool operator<(const Property &rhs) const {
-        if (Opcode != rhs.Opcode) return Opcode < rhs.Opcode;
-        if (V1 != rhs.V1) return V1 < rhs.V1;
-        return V2 < rhs.V2;
-      }
-
       Ops Opcode;
       Value *V1, *V2;
     };
@@ -208,7 +207,7 @@
       }
     }
 
-    // Finds the properties implied by a synonym and adds them too.
+    // Finds the properties implied by a equivalence and adds them too.
     // Example: ("seteq %a, %b", true,  EQ) --> (%a, %b, EQ)
     //          ("seteq %a, %b", false, EQ) --> (%a, %b, NE)
     void addImpliedProperties(Ops Opcode, Value *V1, Value *V2) {
@@ -267,13 +266,25 @@
         default:
           break;
         }
+      } else if (SelectInst *SI = dyn_cast<SelectInst>(V2)) {
+        if (Opcode != EQ && Opcode != NE) return;
+
+        ConstantBool *True  = (Opcode==EQ) ? ConstantBool::True
+                                           : ConstantBool::False,
+                     *False = (Opcode==EQ) ? ConstantBool::False
+                                           : ConstantBool::True;
+
+        if (V1 == SI->getTrueValue())
+          addEqual(SI->getCondition(), True);
+        else if (V1 == SI->getFalseValue())
+          addEqual(SI->getCondition(), False);
+        else if (Opcode == EQ)
+          assert("Result of select not equal to either value.");
       }
     }
 
-    std::map<Value *, unsigned> SynonymMap;
-    std::vector<Value *> Synonyms;
-
   public:
+#ifdef DEBUG
     void debug(std::ostream &os) const {
       for (EquivalenceClasses<Value*>::iterator I = union_find.begin(),
            E = union_find.end(); I != E; ++I) {
@@ -284,6 +295,7 @@
         std::cerr << "\n--\n";
       }
     }
+#endif
 
     std::vector<Property> Properties;
   };
@@ -351,13 +363,13 @@
 
 // resolve catches cases addProperty won't because it wasn't used as a
 // condition in the branch, and that visit won't, because the instruction
-// was defined outside of the range that the properties apply to.
+// was defined outside of the scope that the properties apply to.
 Value *PredicateSimplifier::resolve(SetCondInst *SCI,
                                     const PropertySet &KP) {
   // Attempt to resolve the SetCondInst to a boolean.
 
-  Value *SCI0 = SCI->getOperand(0),
-        *SCI1 = SCI->getOperand(1);
+  Value *SCI0 = resolve(SCI->getOperand(0), KP),
+        *SCI1 = resolve(SCI->getOperand(1), KP);
   PropertySet::ConstPropertyIterator NE =
                    KP.findProperty(PropertySet::NE, SCI0, SCI1);
 
@@ -378,9 +390,6 @@
     }
   }
 
-  SCI0 = KP.canonicalize(SCI0);
-  SCI1 = KP.canonicalize(SCI1);
-
   ConstantIntegral *CI1 = dyn_cast<ConstantIntegral>(SCI0),
                    *CI2 = dyn_cast<ConstantIntegral>(SCI1);
 
@@ -445,6 +454,8 @@
 
   V = KP.canonicalize(V);
 
+  DEBUG(std::cerr << "peering into " << *V << "\n");
+
   if (BinaryOperator *BO = dyn_cast<BinaryOperator>(V))
     return resolve(BO, KP);
   else if (SelectInst *SI = dyn_cast<SelectInst>(V))
@@ -466,8 +477,19 @@
   DEBUG(std::cerr << "Considering instruction " << *I << "\n");
   DEBUG(KnownProperties.debug(std::cerr));
 
-  // Substitute values known to be equal.
-  for (unsigned i = 0, E = I->getNumOperands(); i != E; ++i) {
+  // Try to replace whole instruction.
+  Value *V = resolve(I, KnownProperties);
+  assert(V && "resolve not supposed to return NULL.");
+  if (V != I) {
+    modified = true;
+    ++NumInstruction;
+    I->replaceAllUsesWith(V);
+    I->eraseFromParent();
+    return;
+  }
+
+  // Try to substitute operands.
+  for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) {
     Value *Oper = I->getOperand(i);
     Value *V = resolve(Oper, KnownProperties);
     assert(V && "resolve not supposed to return NULL.");
@@ -480,15 +502,6 @@
     }
   }
 
-  Value *V = resolve(I, KnownProperties);
-  assert(V && "resolve not supposed to return NULL.");
-  if (V != I) {
-    modified = true;
-    ++NumInstruction;
-    I->replaceAllUsesWith(V);
-    I->eraseFromParent();
-  }
-
   if (TerminatorInst *TI = dyn_cast<TerminatorInst>(I))
     visit(TI, DTNode, KnownProperties);
   else if (LoadInst *LI = dyn_cast<LoadInst>(I))






More information about the llvm-commits mailing list