[PATCH] D139310: InstCombine: Fold fneg (copysign x, y) -> copysign x, (fneg y)

Matt Arsenault via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Dec 5 05:11:05 PST 2022


arsenm created this revision.
arsenm added reviewers: sepavloff, kpn, andrew.w.kaylor, jcranmer-intel, nlopes.
Herald added a subscriber: hiraditya.
Herald added a project: All.
arsenm requested review of this revision.
Herald added a subscriber: wdng.
Herald added a project: LLVM.

https://reviews.llvm.org/D139310

Files:
  llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
  llvm/test/Transforms/InstCombine/copysign-fneg-fabs.ll


Index: llvm/test/Transforms/InstCombine/copysign-fneg-fabs.ll
===================================================================
--- llvm/test/Transforms/InstCombine/copysign-fneg-fabs.ll
+++ llvm/test/Transforms/InstCombine/copysign-fneg-fabs.ll
@@ -68,9 +68,9 @@
 
 define half @fneg_copysign(half %x, half %y) {
 ; CHECK-LABEL: @fneg_copysign(
-; CHECK-NEXT:    [[COPYSIGN:%.*]] = call half @llvm.copysign.f16(half [[X:%.*]], half [[Y:%.*]])
-; CHECK-NEXT:    [[FNEG_COPYSIGN:%.*]] = fneg half [[COPYSIGN]]
-; CHECK-NEXT:    ret half [[FNEG_COPYSIGN]]
+; CHECK-NEXT:    [[TMP1:%.*]] = fneg half [[Y:%.*]]
+; CHECK-NEXT:    [[TMP2:%.*]] = call half @llvm.copysign.f16(half [[X:%.*]], half [[TMP1]])
+; CHECK-NEXT:    ret half [[TMP2]]
 ;
   %copysign = call half @llvm.copysign.f16(half %x, half %y)
   %fneg.copysign = fneg half %copysign
@@ -102,9 +102,9 @@
 
 define <2 x half> @fneg_copysign_vector(<2 x half> %x, <2 x half> %y) {
 ; CHECK-LABEL: @fneg_copysign_vector(
-; CHECK-NEXT:    [[COPYSIGN:%.*]] = call <2 x half> @llvm.copysign.v2f16(<2 x half> [[X:%.*]], <2 x half> [[Y:%.*]])
-; CHECK-NEXT:    [[FNEG_COPYSIGN:%.*]] = fneg <2 x half> [[COPYSIGN]]
-; CHECK-NEXT:    ret <2 x half> [[FNEG_COPYSIGN]]
+; CHECK-NEXT:    [[TMP1:%.*]] = fneg <2 x half> [[Y:%.*]]
+; CHECK-NEXT:    [[TMP2:%.*]] = call <2 x half> @llvm.copysign.v2f16(<2 x half> [[X:%.*]], <2 x half> [[TMP1]])
+; CHECK-NEXT:    ret <2 x half> [[TMP2]]
 ;
   %copysign = call <2 x half> @llvm.copysign.v2f16(<2 x half> %x, <2 x half> %y)
   %fneg.copysign = fneg <2 x half> %copysign
@@ -135,9 +135,9 @@
 
 define half @fneg_copysign_flags(half %x, half %y) {
 ; CHECK-LABEL: @fneg_copysign_flags(
-; CHECK-NEXT:    [[COPYSIGN:%.*]] = call nnan nsz half @llvm.copysign.f16(half [[X:%.*]], half [[Y:%.*]])
-; CHECK-NEXT:    [[FNEG_COPYSIGN:%.*]] = fneg ninf nsz half [[COPYSIGN]]
-; CHECK-NEXT:    ret half [[FNEG_COPYSIGN]]
+; CHECK-NEXT:    [[TMP1:%.*]] = fneg nsz half [[Y:%.*]]
+; CHECK-NEXT:    [[TMP2:%.*]] = call nsz half @llvm.copysign.f16(half [[X:%.*]], half [[TMP1]])
+; CHECK-NEXT:    ret half [[TMP2]]
 ;
   %copysign = call nnan nsz half @llvm.copysign.f16(half %x, half %y)
   %fneg.copysign = fneg ninf nsz half %copysign
@@ -159,9 +159,9 @@
 ; Make sure we don't break things by polluting copysign with nsz
 define half @fneg_nsz_copysign(half %x, half %y) {
 ; CHECK-LABEL: @fneg_nsz_copysign(
-; CHECK-NEXT:    [[COPYSIGN:%.*]] = call half @llvm.copysign.f16(half [[X:%.*]], half [[Y:%.*]])
-; CHECK-NEXT:    [[FNEG_COPYSIGN:%.*]] = fneg nsz half [[COPYSIGN]]
-; CHECK-NEXT:    ret half [[FNEG_COPYSIGN]]
+; CHECK-NEXT:    [[TMP1:%.*]] = fneg half [[Y:%.*]]
+; CHECK-NEXT:    [[TMP2:%.*]] = call half @llvm.copysign.f16(half [[X:%.*]], half [[TMP1]])
+; CHECK-NEXT:    ret half [[TMP2]]
 ;
   %copysign = call half @llvm.copysign.f16(half %x, half %y)
   %fneg.copysign = fneg nsz half %copysign
Index: llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
===================================================================
--- llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
+++ llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
@@ -2404,9 +2404,13 @@
   if (Instruction *R = hoistFNegAboveFMulFDiv(I, Builder))
     return R;
 
+  Value *OneUse;
+  if (!match(Op, m_OneUse(m_Value(OneUse))))
+    return nullptr;
+
   // Try to eliminate fneg if at least 1 arm of the select is negated.
   Value *Cond;
-  if (match(Op, m_OneUse(m_Select(m_Value(Cond), m_Value(X), m_Value(Y))))) {
+  if (match(OneUse, m_Select(m_Value(Cond), m_Value(X), m_Value(Y)))) {
     // Unlike most transforms, this one is not safe to propagate nsz unless
     // it is present on the original select. (We are conservatively intersecting
     // the nsz flags from the select and root fneg instruction.)
@@ -2434,6 +2438,21 @@
     }
   }
 
+  // fneg (copysign x, y) -> copysign x, (fneg y)
+  if (match(OneUse, m_CopySign(m_Value(X), m_Value(Y)))) {
+    // The source copysign has an additional value input, so we can't propagate
+    // flags the copysign doesn't also have.
+    FastMathFlags FMF = I.getFastMathFlags();
+    FMF &= cast<FPMathOperator>(OneUse)->getFastMathFlags();
+
+    IRBuilder<>::FastMathFlagGuard FMFGuard(Builder);
+    Builder.setFastMathFlags(FMF);
+
+    Value *NegY = Builder.CreateFNeg(Y);
+    Value *NewCopySign = Builder.CreateCopySign(X, NegY);
+    return replaceInstUsesWith(I, NewCopySign);
+  }
+
   return nullptr;
 }
 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D139310.480060.patch
Type: text/x-patch
Size: 4449 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20221205/c97ec79b/attachment.bin>


More information about the llvm-commits mailing list