]> granicus.if.org Git - llvm/commitdiff
[InstCombine] sink FP negation of operands through select
authorSanjay Patel <spatel@rotateright.com>
Mon, 6 May 2019 20:34:05 +0000 (20:34 +0000)
committerSanjay Patel <spatel@rotateright.com>
Mon, 6 May 2019 20:34:05 +0000 (20:34 +0000)
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

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@360075 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/InstCombine/InstCombineSelect.cpp
test/Transforms/InstCombine/fneg.ll

index d0292b640fec1f8631b7d0ba7631d20c52f30a75..5a14726bee26f63e017c2480b5a6bb740a0e7fc0 100644 (file)
@@ -333,6 +333,18 @@ Instruction *InstCombiner::foldSelectOpOp(SelectInst &SI, Instruction *TI,
                             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
index 4a5f033629ddca367c86e75bff9e5fc93afd3925..9c4e72f5f068b064962d2411c74034d9eb443569 100644 (file)
@@ -161,9 +161,8 @@ define <4 x double> @fdiv_op0_constant_fneg_vec(<4 x double> %x) {
 
 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(float %x, float %y, i1 %cond) {
 ; 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(float %x, float %y, i1 %cond) {
 
 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(float %x, float %y, i1 %cond) {
 ; 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