[llvm] r360075 - [InstCombine] sink FP negation of operands through select

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Mon May 6 13:34:06 PDT 2019


Author: spatel
Date: Mon May  6 13:34:05 2019
New Revision: 360075

URL: http://llvm.org/viewvc/llvm-project?rev=360075&view=rev
Log:
[InstCombine] sink FP negation of operands through select

We don't always get this:

Cond ? -X : -Y --> -(Cond ? X : Y)

...even with the legacy IR form of fneg in the case with extra uses,
and we miss matching with the newer 'fneg' instruction because we
are expecting binops through the rest of the path.

Differential Revision: https://reviews.llvm.org/D61604

Modified:
    llvm/trunk/lib/Transforms/InstCombine/InstCombineSelect.cpp
    llvm/trunk/test/Transforms/InstCombine/fneg.ll

Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineSelect.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineSelect.cpp?rev=360075&r1=360074&r2=360075&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineSelect.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineSelect.cpp Mon May  6 13:34:05 2019
@@ -333,6 +333,18 @@ Instruction *InstCombiner::foldSelectOpO
                             TI->getType());
   }
 
+  // Cond ? -X : -Y --> -(Cond ? X : Y)
+  Value *X, *Y;
+  if (match(TI, m_FNeg(m_Value(X))) && match(FI, m_FNeg(m_Value(Y))) &&
+      (TI->hasOneUse() || FI->hasOneUse())) {
+    Value *NewSel = Builder.CreateSelect(Cond, X, Y, SI.getName() + ".v", &SI);
+    // TODO: Remove the hack for the binop form when the unary op is optimized
+    //       properly with all IR passes.
+    if (TI->getOpcode() != Instruction::FNeg)
+      return BinaryOperator::CreateFNegFMF(NewSel, cast<BinaryOperator>(TI));
+    return UnaryOperator::CreateFNeg(NewSel);
+  }
+
   // Only handle binary operators (including two-operand getelementptr) with
   // one-use here. As with the cast case above, it may be possible to relax the
   // one-use constraint, but that needs be examined carefully since it may not

Modified: llvm/trunk/test/Transforms/InstCombine/fneg.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/fneg.ll?rev=360075&r1=360074&r2=360075&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/fneg.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/fneg.ll Mon May  6 13:34:05 2019
@@ -161,9 +161,8 @@ define <4 x double> @fdiv_op0_constant_f
 
 define <2 x double> @fneg_fneg_sel(<2 x double> %x, <2 x double> %y, i1 %cond) {
 ; CHECK-LABEL: @fneg_fneg_sel(
-; CHECK-NEXT:    [[N1:%.*]] = fneg <2 x double> [[X:%.*]]
-; CHECK-NEXT:    [[N2:%.*]] = fneg <2 x double> [[Y:%.*]]
-; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[COND:%.*]], <2 x double> [[N1]], <2 x double> [[N2]]
+; CHECK-NEXT:    [[SEL_V:%.*]] = select i1 [[COND:%.*]], <2 x double> [[X:%.*]], <2 x double> [[Y:%.*]]
+; CHECK-NEXT:    [[SEL:%.*]] = fneg <2 x double> [[SEL_V]]
 ; CHECK-NEXT:    ret <2 x double> [[SEL]]
 ;
   %n1 = fneg <2 x double> %x
@@ -178,8 +177,8 @@ define float @fneg_fneg_sel_extra_use1(f
 ; CHECK-LABEL: @fneg_fneg_sel_extra_use1(
 ; CHECK-NEXT:    [[N1:%.*]] = fneg float [[X:%.*]]
 ; CHECK-NEXT:    call void @use(float [[N1]])
-; CHECK-NEXT:    [[N2:%.*]] = fneg float [[Y:%.*]]
-; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[COND:%.*]], float [[N1]], float [[N2]]
+; CHECK-NEXT:    [[SEL_V:%.*]] = select i1 [[COND:%.*]], float [[X]], float [[Y:%.*]]
+; CHECK-NEXT:    [[SEL:%.*]] = fneg float [[SEL_V]]
 ; CHECK-NEXT:    ret float [[SEL]]
 ;
   %n1 = fneg float %x
@@ -191,10 +190,10 @@ define float @fneg_fneg_sel_extra_use1(f
 
 define float @fneg_fneg_sel_extra_use2(float %x, float %y, i1 %cond) {
 ; CHECK-LABEL: @fneg_fneg_sel_extra_use2(
-; CHECK-NEXT:    [[N1:%.*]] = fneg float [[X:%.*]]
 ; CHECK-NEXT:    [[N2:%.*]] = fneg float [[Y:%.*]]
 ; CHECK-NEXT:    call void @use(float [[N2]])
-; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[COND:%.*]], float [[N1]], float [[N2]]
+; CHECK-NEXT:    [[SEL_V:%.*]] = select i1 [[COND:%.*]], float [[X:%.*]], float [[Y]]
+; CHECK-NEXT:    [[SEL:%.*]] = fneg float [[SEL_V]]
 ; CHECK-NEXT:    ret float [[SEL]]
 ;
   %n1 = fneg float %x
@@ -210,8 +209,8 @@ define float @fsub_fsub_sel_extra_use1(f
 ; CHECK-LABEL: @fsub_fsub_sel_extra_use1(
 ; CHECK-NEXT:    [[N1:%.*]] = fsub float -0.000000e+00, [[X:%.*]]
 ; CHECK-NEXT:    call void @use(float [[N1]])
-; CHECK-NEXT:    [[N2:%.*]] = fsub float -0.000000e+00, [[Y:%.*]]
-; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[COND:%.*]], float [[N1]], float [[N2]]
+; CHECK-NEXT:    [[SEL_V:%.*]] = select i1 [[COND:%.*]], float [[X]], float [[Y:%.*]]
+; CHECK-NEXT:    [[SEL:%.*]] = fsub float -0.000000e+00, [[SEL_V]]
 ; CHECK-NEXT:    ret float [[SEL]]
 ;
   %n1 = fsub float -0.0, %x




More information about the llvm-commits mailing list