[llvm-commits] [llvm] r53220 - in /llvm/trunk: lib/VMCore/ConstantFold.cpp test/Transforms/ConstProp/2008-07-07-VectorCompare.ll

Chris Lattner sabre at nondot.org
Mon Jul 7 22:46:40 PDT 2008


Author: lattner
Date: Tue Jul  8 00:46:34 2008
New Revision: 53220

URL: http://llvm.org/viewvc/llvm-project?rev=53220&view=rev
Log:
Fix three bugs:

1) evaluate [v]fcmp true/false with undefs to true or false instead
   of undef.
2) fix vector comparisons with undef to return a vector result instead 
   of i1
3) fix vector comparisons with evaluatable results to return vector
   true/false instead of i1 true/false (PR2529)

Added:
    llvm/trunk/test/Transforms/ConstProp/2008-07-07-VectorCompare.ll
Modified:
    llvm/trunk/lib/VMCore/ConstantFold.cpp

Modified: llvm/trunk/lib/VMCore/ConstantFold.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/ConstantFold.cpp?rev=53220&r1=53219&r2=53220&view=diff

==============================================================================
--- llvm/trunk/lib/VMCore/ConstantFold.cpp (original)
+++ llvm/trunk/lib/VMCore/ConstantFold.cpp Tue Jul  8 00:46:34 2008
@@ -1238,10 +1238,30 @@
 Constant *llvm::ConstantFoldCompareInstruction(unsigned short pred, 
                                                const Constant *C1, 
                                                const Constant *C2) {
-
+  // Fold FCMP_FALSE/FCMP_TRUE unconditionally.
+  if (pred == FCmpInst::FCMP_FALSE) {
+    if (const VectorType *VT = dyn_cast<VectorType>(C1->getType()))
+      return Constant::getNullValue(VectorType::getInteger(VT));
+    else
+      return ConstantInt::getFalse();
+  }
+  
+  if (pred == FCmpInst::FCMP_TRUE) {
+    if (const VectorType *VT = dyn_cast<VectorType>(C1->getType()))
+      return Constant::getAllOnesValue(VectorType::getInteger(VT));
+    else
+      return ConstantInt::getTrue();
+  }
+      
   // Handle some degenerate cases first
-  if (isa<UndefValue>(C1) || isa<UndefValue>(C2))
+  if (isa<UndefValue>(C1) || isa<UndefValue>(C2)) {
+    // vicmp/vfcmp -> [vector] undef
+    if (const VectorType *VTy = dyn_cast<VectorType>(C1->getType()))
+      return UndefValue::get(VectorType::getInteger(VTy));
+    
+    // icmp/fcmp -> i1 undef
     return UndefValue::get(Type::Int1Ty);
+  }
 
   // No compile-time operations on this type yet.
   if (C1->getType() == Type::PPC_FP128Ty)
@@ -1355,6 +1375,7 @@
   }
 
   if (C1->getType()->isFloatingPoint()) {
+    int Result = -1;
     switch (evaluateFCmpRelation(C1, C2)) {
     default: assert(0 && "Unknown relation!");
     case FCmpInst::FCMP_UNO:
@@ -1370,44 +1391,57 @@
     case FCmpInst::BAD_FCMP_PREDICATE:
       break; // Couldn't determine anything about these constants.
     case FCmpInst::FCMP_OEQ: // We know that C1 == C2
-      return ConstantInt::get(Type::Int1Ty,
-          pred == FCmpInst::FCMP_UEQ || pred == FCmpInst::FCMP_OEQ ||
-          pred == FCmpInst::FCMP_ULE || pred == FCmpInst::FCMP_OLE ||
-          pred == FCmpInst::FCMP_UGE || pred == FCmpInst::FCMP_OGE);
+      Result = (pred == FCmpInst::FCMP_UEQ || pred == FCmpInst::FCMP_OEQ ||
+                pred == FCmpInst::FCMP_ULE || pred == FCmpInst::FCMP_OLE ||
+                pred == FCmpInst::FCMP_UGE || pred == FCmpInst::FCMP_OGE);
+      break;
     case FCmpInst::FCMP_OLT: // We know that C1 < C2
-      return ConstantInt::get(Type::Int1Ty,
-          pred == FCmpInst::FCMP_UNE || pred == FCmpInst::FCMP_ONE ||
-          pred == FCmpInst::FCMP_ULT || pred == FCmpInst::FCMP_OLT ||
-          pred == FCmpInst::FCMP_ULE || pred == FCmpInst::FCMP_OLE);
+      Result = (pred == FCmpInst::FCMP_UNE || pred == FCmpInst::FCMP_ONE ||
+                pred == FCmpInst::FCMP_ULT || pred == FCmpInst::FCMP_OLT ||
+                pred == FCmpInst::FCMP_ULE || pred == FCmpInst::FCMP_OLE);
+      break;
     case FCmpInst::FCMP_OGT: // We know that C1 > C2
-      return ConstantInt::get(Type::Int1Ty,
-          pred == FCmpInst::FCMP_UNE || pred == FCmpInst::FCMP_ONE ||
-          pred == FCmpInst::FCMP_UGT || pred == FCmpInst::FCMP_OGT ||
-          pred == FCmpInst::FCMP_UGE || pred == FCmpInst::FCMP_OGE);
+      Result = (pred == FCmpInst::FCMP_UNE || pred == FCmpInst::FCMP_ONE ||
+                pred == FCmpInst::FCMP_UGT || pred == FCmpInst::FCMP_OGT ||
+                pred == FCmpInst::FCMP_UGE || pred == FCmpInst::FCMP_OGE);
+      break;
     case FCmpInst::FCMP_OLE: // We know that C1 <= C2
       // We can only partially decide this relation.
       if (pred == FCmpInst::FCMP_UGT || pred == FCmpInst::FCMP_OGT) 
-        return ConstantInt::getFalse();
-      if (pred == FCmpInst::FCMP_ULT || pred == FCmpInst::FCMP_OLT) 
-        return ConstantInt::getTrue();
+        Result = 0;
+      else if (pred == FCmpInst::FCMP_ULT || pred == FCmpInst::FCMP_OLT) 
+        Result = 1;
       break;
     case FCmpInst::FCMP_OGE: // We known that C1 >= C2
       // We can only partially decide this relation.
       if (pred == FCmpInst::FCMP_ULT || pred == FCmpInst::FCMP_OLT) 
-        return ConstantInt::getFalse();
-      if (pred == FCmpInst::FCMP_UGT || pred == FCmpInst::FCMP_OGT) 
-        return ConstantInt::getTrue();
+        Result = 0;
+      else if (pred == FCmpInst::FCMP_UGT || pred == FCmpInst::FCMP_OGT) 
+        Result = 1;
       break;
     case ICmpInst::ICMP_NE: // We know that C1 != C2
       // We can only partially decide this relation.
       if (pred == FCmpInst::FCMP_OEQ || pred == FCmpInst::FCMP_UEQ) 
-        return ConstantInt::getFalse();
-      if (pred == FCmpInst::FCMP_ONE || pred == FCmpInst::FCMP_UNE) 
-        return ConstantInt::getTrue();
+        Result = 0;
+      else if (pred == FCmpInst::FCMP_ONE || pred == FCmpInst::FCMP_UNE) 
+        Result = 1;
       break;
     }
+    
+    // If we evaluated the result, return it now.
+    if (Result != -1) {
+      if (const VectorType *VT = dyn_cast<VectorType>(C1->getType())) {
+        if (Result == 0)
+          return Constant::getNullValue(VectorType::getInteger(VT));
+        else
+          return Constant::getAllOnesValue(VectorType::getInteger(VT));
+      }
+      return ConstantInt::get(Type::Int1Ty, Result);
+    }
+    
   } else {
     // Evaluate the relation between the two constants, per the predicate.
+    int Result = -1;  // -1 = unknown, 0 = known false, 1 = known true.
     switch (evaluateICmpRelation(C1, C2, CmpInst::isSigned(pred))) {
     default: assert(0 && "Unknown relational!");
     case ICmpInst::BAD_ICMP_PREDICATE:
@@ -1415,69 +1449,80 @@
     case ICmpInst::ICMP_EQ:   // We know the constants are equal!
       // If we know the constants are equal, we can decide the result of this
       // computation precisely.
-      return ConstantInt::get(Type::Int1Ty, 
-                              pred == ICmpInst::ICMP_EQ  ||
-                              pred == ICmpInst::ICMP_ULE ||
-                              pred == ICmpInst::ICMP_SLE ||
-                              pred == ICmpInst::ICMP_UGE ||
-                              pred == ICmpInst::ICMP_SGE);
+      Result = (pred == ICmpInst::ICMP_EQ  ||
+                pred == ICmpInst::ICMP_ULE ||
+                pred == ICmpInst::ICMP_SLE ||
+                pred == ICmpInst::ICMP_UGE ||
+                pred == ICmpInst::ICMP_SGE);
+      break;
     case ICmpInst::ICMP_ULT:
       // If we know that C1 < C2, we can decide the result of this computation
       // precisely.
-      return ConstantInt::get(Type::Int1Ty, 
-                              pred == ICmpInst::ICMP_ULT ||
-                              pred == ICmpInst::ICMP_NE  ||
-                              pred == ICmpInst::ICMP_ULE);
+      Result = (pred == ICmpInst::ICMP_ULT ||
+                pred == ICmpInst::ICMP_NE  ||
+                pred == ICmpInst::ICMP_ULE);
+      break;
     case ICmpInst::ICMP_SLT:
       // If we know that C1 < C2, we can decide the result of this computation
       // precisely.
-      return ConstantInt::get(Type::Int1Ty,
-                              pred == ICmpInst::ICMP_SLT ||
-                              pred == ICmpInst::ICMP_NE  ||
-                              pred == ICmpInst::ICMP_SLE);
+      Result = (pred == ICmpInst::ICMP_SLT ||
+                pred == ICmpInst::ICMP_NE  ||
+                pred == ICmpInst::ICMP_SLE);
+      break;
     case ICmpInst::ICMP_UGT:
       // If we know that C1 > C2, we can decide the result of this computation
       // precisely.
-      return ConstantInt::get(Type::Int1Ty, 
-                              pred == ICmpInst::ICMP_UGT ||
-                              pred == ICmpInst::ICMP_NE  ||
-                              pred == ICmpInst::ICMP_UGE);
+      Result = (pred == ICmpInst::ICMP_UGT ||
+                pred == ICmpInst::ICMP_NE  ||
+                pred == ICmpInst::ICMP_UGE);
+      break;
     case ICmpInst::ICMP_SGT:
       // If we know that C1 > C2, we can decide the result of this computation
       // precisely.
-      return ConstantInt::get(Type::Int1Ty, 
-                              pred == ICmpInst::ICMP_SGT ||
-                              pred == ICmpInst::ICMP_NE  ||
-                              pred == ICmpInst::ICMP_SGE);
+      Result = (pred == ICmpInst::ICMP_SGT ||
+                pred == ICmpInst::ICMP_NE  ||
+                pred == ICmpInst::ICMP_SGE);
+      break;
     case ICmpInst::ICMP_ULE:
       // If we know that C1 <= C2, we can only partially decide this relation.
-      if (pred == ICmpInst::ICMP_UGT) return ConstantInt::getFalse();
-      if (pred == ICmpInst::ICMP_ULT) return ConstantInt::getTrue();
+      if (pred == ICmpInst::ICMP_UGT) Result = 0;
+      if (pred == ICmpInst::ICMP_ULT) Result = 1;
       break;
     case ICmpInst::ICMP_SLE:
       // If we know that C1 <= C2, we can only partially decide this relation.
-      if (pred == ICmpInst::ICMP_SGT) return ConstantInt::getFalse();
-      if (pred == ICmpInst::ICMP_SLT) return ConstantInt::getTrue();
+      if (pred == ICmpInst::ICMP_SGT) Result = 0;
+      if (pred == ICmpInst::ICMP_SLT) Result = 1;
       break;
 
     case ICmpInst::ICMP_UGE:
       // If we know that C1 >= C2, we can only partially decide this relation.
-      if (pred == ICmpInst::ICMP_ULT) return ConstantInt::getFalse();
-      if (pred == ICmpInst::ICMP_UGT) return ConstantInt::getTrue();
+      if (pred == ICmpInst::ICMP_ULT) Result = 0;
+      if (pred == ICmpInst::ICMP_UGT) Result = 1;
       break;
     case ICmpInst::ICMP_SGE:
       // If we know that C1 >= C2, we can only partially decide this relation.
-      if (pred == ICmpInst::ICMP_SLT) return ConstantInt::getFalse();
-      if (pred == ICmpInst::ICMP_SGT) return ConstantInt::getTrue();
+      if (pred == ICmpInst::ICMP_SLT) Result = 0;
+      if (pred == ICmpInst::ICMP_SGT) Result = 1;
       break;
 
     case ICmpInst::ICMP_NE:
       // If we know that C1 != C2, we can only partially decide this relation.
-      if (pred == ICmpInst::ICMP_EQ) return ConstantInt::getFalse();
-      if (pred == ICmpInst::ICMP_NE) return ConstantInt::getTrue();
+      if (pred == ICmpInst::ICMP_EQ) Result = 0;
+      if (pred == ICmpInst::ICMP_NE) Result = 1;
       break;
     }
-
+    
+    // If we evaluated the result, return it now.
+    if (Result != -1) {
+      if (const VectorType *VT = dyn_cast<VectorType>(C1->getType())) {
+        if (Result == 0)
+          return Constant::getNullValue(VT);
+        else
+          return Constant::getAllOnesValue(VT);
+      }
+      return ConstantInt::get(Type::Int1Ty, Result);
+    }
+    
     if (!isa<ConstantExpr>(C1) && isa<ConstantExpr>(C2)) {
       // If C2 is a constant expr and C1 isn't, flop them around and fold the
       // other way if possible.

Added: llvm/trunk/test/Transforms/ConstProp/2008-07-07-VectorCompare.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ConstProp/2008-07-07-VectorCompare.ll?rev=53220&view=auto

==============================================================================
--- llvm/trunk/test/Transforms/ConstProp/2008-07-07-VectorCompare.ll (added)
+++ llvm/trunk/test/Transforms/ConstProp/2008-07-07-VectorCompare.ll Tue Jul  8 00:46:34 2008
@@ -0,0 +1,14 @@
+; RUN: llvm-as < %s | opt -constprop | llvm-dis
+; PR2529
+define <4 x i32> @test1(i32 %argc, i8** %argv) {
+entry:  
+        %foo = vicmp slt <4 x i32> undef, <i32 14, i32 undef, i32 undef, i32 undef>
+        ret <4 x i32> %foo
+}
+
+define <4 x i32> @main(i32 %argc, i8** %argv) {
+entry:  
+        %foo = vicmp slt <4 x i32> <i32 undef, i32 undef, i32 undef, i32
+undef>, <i32 undef, i32 undef, i32 undef, i32 undef>
+        ret <4 x i32> %foo
+}





More information about the llvm-commits mailing list