[llvm-commits] [llvm] r96955 - in /llvm/trunk: lib/Transforms/InstCombine/InstCombineSelect.cpp test/Transforms/InstCombine/fcmp-select.ll

Dan Gohman gohman at apple.com
Tue Feb 23 09:17:57 PST 2010


Author: djg
Date: Tue Feb 23 11:17:57 2010
New Revision: 96955

URL: http://llvm.org/viewvc/llvm-project?rev=96955&view=rev
Log:
Don't do (X != Y) ? X : Y  -> X for floating-point values; it doesn't
handle NaN properly.

Do (X une Y) ? X : Y  -> X if one of X and Y is not zero.

Added:
    llvm/trunk/test/Transforms/InstCombine/fcmp-select.ll
Modified:
    llvm/trunk/lib/Transforms/InstCombine/InstCombineSelect.cpp

Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineSelect.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineSelect.cpp?rev=96955&r1=96954&r2=96955&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineSelect.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineSelect.cpp Tue Feb 23 11:17:57 2010
@@ -539,9 +539,18 @@
              !CFPf->getValueAPF().isZero()))
         return ReplaceInstUsesWith(SI, FalseVal);
       }
-      // Transform (X != Y) ? X : Y  -> X
-      if (FCI->getPredicate() == FCmpInst::FCMP_ONE)
+      // Transform (X une Y) ? X : Y  -> X
+      if (FCI->getPredicate() == FCmpInst::FCMP_UNE) {
+        // This is not safe in general for floating point:  
+        // consider X== -0, Y== +0.
+        // It becomes safe if either operand is a nonzero constant.
+        ConstantFP *CFPt, *CFPf;
+        if (((CFPt = dyn_cast<ConstantFP>(TrueVal)) &&
+              !CFPt->getValueAPF().isZero()) ||
+            ((CFPf = dyn_cast<ConstantFP>(FalseVal)) &&
+             !CFPf->getValueAPF().isZero()))
         return ReplaceInstUsesWith(SI, TrueVal);
+      }
       // NOTE: if we wanted to, this is where to detect MIN/MAX
 
     } else if (FCI->getOperand(0) == FalseVal && FCI->getOperand(1) == TrueVal){
@@ -557,9 +566,18 @@
              !CFPf->getValueAPF().isZero()))
           return ReplaceInstUsesWith(SI, FalseVal);
       }
-      // Transform (X != Y) ? Y : X  -> Y
-      if (FCI->getPredicate() == FCmpInst::FCMP_ONE)
-        return ReplaceInstUsesWith(SI, TrueVal);
+      // Transform (X une Y) ? Y : X  -> Y
+      if (FCI->getPredicate() == FCmpInst::FCMP_UNE) {
+        // This is not safe in general for floating point:  
+        // consider X== -0, Y== +0.
+        // It becomes safe if either operand is a nonzero constant.
+        ConstantFP *CFPt, *CFPf;
+        if (((CFPt = dyn_cast<ConstantFP>(TrueVal)) &&
+              !CFPt->getValueAPF().isZero()) ||
+            ((CFPf = dyn_cast<ConstantFP>(FalseVal)) &&
+             !CFPf->getValueAPF().isZero()))
+          return ReplaceInstUsesWith(SI, TrueVal);
+      }
       // NOTE: if we wanted to, this is where to detect MIN/MAX
     }
     // NOTE: if we wanted to, this is where to detect ABS

Added: llvm/trunk/test/Transforms/InstCombine/fcmp-select.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/fcmp-select.ll?rev=96955&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/fcmp-select.ll (added)
+++ llvm/trunk/test/Transforms/InstCombine/fcmp-select.ll Tue Feb 23 11:17:57 2010
@@ -0,0 +1,53 @@
+; RUN: opt < %s -instcombine -S | FileCheck %s
+
+; x != y ? x : y -> x if it's the right kind of != and at least
+; one of x and y is not negative zero.
+
+; CHECK: f0
+; CHECK: ret double %x
+define double @f0(double %x) nounwind readnone {
+entry:
+  %cmp = fcmp une double %x, -1.0
+  %cond = select i1 %cmp, double %x, double -1.0
+  ret double %cond
+}
+; CHECK: f1
+; CHECK: ret double -1.000000e+00
+define double @f1(double %x) nounwind readnone {
+entry:
+  %cmp = fcmp une double %x, -1.0
+  %cond = select i1 %cmp, double -1.0, double %x
+  ret double %cond
+}
+; CHECK: f2
+; CHECK: ret double %cond
+define double @f2(double %x, double %y) nounwind readnone {
+entry:
+  %cmp = fcmp une double %x, %y
+  %cond = select i1 %cmp, double %x, double %y
+  ret double %cond
+}
+; CHECK: f3
+; CHECK: ret double %cond
+define double @f3(double %x, double %y) nounwind readnone {
+entry:
+  %cmp = fcmp une double %x, %y
+  %cond = select i1 %cmp, double %y, double %x
+  ret double %cond
+}
+; CHECK: f4
+; CHECK: ret double %cond
+define double @f4(double %x) nounwind readnone {
+entry:
+  %cmp = fcmp one double %x, -1.0
+  %cond = select i1 %cmp, double %x, double -1.0
+  ret double %cond
+}
+; CHECK: f5
+; CHECK: ret double %cond
+define double @f5(double %x) nounwind readnone {
+entry:
+  %cmp = fcmp one double %x, -1.0
+  %cond = select i1 %cmp, double -1.0, double %x
+  ret double %cond
+}





More information about the llvm-commits mailing list