[llvm] r346169 - [InstSimplify] fold select (fcmp X, Y), X, Y

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Mon Nov 5 13:51:39 PST 2018


Author: spatel
Date: Mon Nov  5 13:51:39 2018
New Revision: 346169

URL: http://llvm.org/viewvc/llvm-project?rev=346169&view=rev
Log:
[InstSimplify] fold select (fcmp X, Y), X, Y

This is NFCI for InstCombine because it calls InstSimplify, 
so I left the tests for this transform there. As noted in
the code comment, we can allow this fold more often by using
FMF and/or value tracking.

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

Modified: llvm/trunk/lib/Analysis/InstructionSimplify.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/InstructionSimplify.cpp?rev=346169&r1=346168&r2=346169&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/InstructionSimplify.cpp (original)
+++ llvm/trunk/lib/Analysis/InstructionSimplify.cpp Mon Nov  5 13:51:39 2018
@@ -3874,6 +3874,34 @@ static Value *simplifySelectWithICmpCond
   return nullptr;
 }
 
+/// Try to simplify a select instruction when its condition operand is a
+/// floating-point comparison.
+static Value *simplifySelectWithFCmp(Value *Cond, Value *T, Value *F) {
+  FCmpInst::Predicate Pred;
+  if (!match(Cond, m_FCmp(Pred, m_Specific(T), m_Specific(F))) &&
+      !match(Cond, m_FCmp(Pred, m_Specific(F), m_Specific(T))))
+    return nullptr;
+
+  // TODO: The transform may not be valid with -0.0. An incomplete way of
+  // testing for that possibility is to check if at least one operand is a
+  // non-zero constant.
+  const APFloat *C;
+  if ((match(T, m_APFloat(C)) && C->isNonZero()) ||
+      (match(F, m_APFloat(C)) && C->isNonZero())) {
+    // (T == F) ? T : F --> F
+    // (F == T) ? T : F --> F
+    if (Pred == FCmpInst::FCMP_OEQ)
+      return F;
+
+    // (T != F) ? T : F --> T
+    // (F != T) ? T : F --> T
+    if (Pred == FCmpInst::FCMP_UNE)
+      return T;
+  }
+
+  return nullptr;
+}
+
 /// Given operands for a SelectInst, see if we can fold the result.
 /// If not, this returns null.
 static Value *SimplifySelectInst(Value *Cond, Value *TrueVal, Value *FalseVal,
@@ -3910,6 +3938,9 @@ static Value *SimplifySelectInst(Value *
           simplifySelectWithICmpCond(Cond, TrueVal, FalseVal, Q, MaxRecurse))
     return V;
 
+  if (Value *V = simplifySelectWithFCmp(Cond, TrueVal, FalseVal))
+    return V;
+
   if (Value *V = foldSelectWithBinaryOp(Cond, TrueVal, FalseVal))
     return V;
 

Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineSelect.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineSelect.cpp?rev=346169&r1=346168&r2=346169&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineSelect.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineSelect.cpp Mon Nov  5 13:51:39 2018
@@ -1660,31 +1660,6 @@ Instruction *InstCombiner::visitSelectIn
   // See if we are selecting two values based on a comparison of the two values.
   if (FCmpInst *FCI = dyn_cast<FCmpInst>(CondVal)) {
     if (FCI->getOperand(0) == TrueVal && FCI->getOperand(1) == FalseVal) {
-      // Transform (X == Y) ? X : Y  -> Y
-      if (FCI->getPredicate() == FCmpInst::FCMP_OEQ) {
-        // 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, FalseVal);
-      }
-      // 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);
-      }
-
       // Canonicalize to use ordered comparisons by swapping the select
       // operands.
       //
@@ -1703,31 +1678,6 @@ Instruction *InstCombiner::visitSelectIn
 
       // NOTE: if we wanted to, this is where to detect MIN/MAX
     } else if (FCI->getOperand(0) == FalseVal && FCI->getOperand(1) == TrueVal){
-      // Transform (X == Y) ? Y : X  -> X
-      if (FCI->getPredicate() == FCmpInst::FCMP_OEQ) {
-        // 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, FalseVal);
-      }
-      // 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);
-      }
-
       // Canonicalize to use ordered comparisons by swapping the select
       // operands.
       //

Modified: llvm/trunk/test/Transforms/InstSimplify/fcmp-select.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/fcmp-select.ll?rev=346169&r1=346168&r2=346169&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/fcmp-select.ll (original)
+++ llvm/trunk/test/Transforms/InstSimplify/fcmp-select.ll Mon Nov  5 13:51:39 2018
@@ -5,9 +5,7 @@
 
 define double @oeq(double %x) {
 ; CHECK-LABEL: @oeq(
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp oeq double [[X:%.*]], 4.200000e+01
-; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP]], double [[X]], double 4.200000e+01
-; CHECK-NEXT:    ret double [[COND]]
+; CHECK-NEXT:    ret double 4.200000e+01
 ;
   %cmp = fcmp oeq double %x, 42.0
   %cond = select i1 %cmp, double %x, double 42.0
@@ -18,9 +16,7 @@ define double @oeq(double %x) {
 
 define float @oeq_swapped(float %x) {
 ; CHECK-LABEL: @oeq_swapped(
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp oeq float [[X:%.*]], 4.200000e+01
-; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP]], float 4.200000e+01, float [[X]]
-; CHECK-NEXT:    ret float [[COND]]
+; CHECK-NEXT:    ret float [[X:%.*]]
 ;
   %cmp = fcmp oeq float %x, 42.0
   %cond = select i1 %cmp, float 42.0, float %x
@@ -34,9 +30,7 @@ define float @oeq_swapped(float %x) {
 
 define double @une(double %x) {
 ; CHECK-LABEL: @une(
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp une double [[X:%.*]], 4.200000e+01
-; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP]], double [[X]], double 4.200000e+01
-; CHECK-NEXT:    ret double [[COND]]
+; CHECK-NEXT:    ret double [[X:%.*]]
 ;
   %cmp = fcmp une double %x, 42.0
   %cond = select i1 %cmp, double %x, double 42.0
@@ -47,9 +41,7 @@ define double @une(double %x) {
 
 define double @une_swapped(double %x) {
 ; CHECK-LABEL: @une_swapped(
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp une double [[X:%.*]], 4.200000e+01
-; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP]], double 4.200000e+01, double [[X]]
-; CHECK-NEXT:    ret double [[COND]]
+; CHECK-NEXT:    ret double 4.200000e+01
 ;
   %cmp = fcmp une double %x, 42.0
   %cond = select i1 %cmp, double 42.0, double %x




More information about the llvm-commits mailing list