[llvm] f7f5d34 - InstCombine: Fold fneg (ldexp x, n) -> ldexp (fneg x), n

Matt Arsenault via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 11 16:16:32 PDT 2023


Author: Matt Arsenault
Date: 2023-08-11T19:16:20-04:00
New Revision: f7f5d348a315d96c907b57e6cafea4cbcb620340

URL: https://github.com/llvm/llvm-project/commit/f7f5d348a315d96c907b57e6cafea4cbcb620340
DIFF: https://github.com/llvm/llvm-project/commit/f7f5d348a315d96c907b57e6cafea4cbcb620340.diff

LOG: InstCombine: Fold fneg (ldexp x, n) -> ldexp (fneg x), n

https://reviews.llvm.org/D156579

Added: 
    

Modified: 
    llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
    llvm/lib/Transforms/InstCombine/InstCombineInternal.h
    llvm/test/Transforms/InstCombine/fneg.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
index ee5329d9bc68d8..c0afcc90d8337f 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
@@ -2557,17 +2557,35 @@ static Instruction *foldFNegIntoConstant(Instruction &I, const DataLayout &DL) {
   return nullptr;
 }
 
-static Instruction *hoistFNegAboveFMulFDiv(Value *FNegOp,
-                                           Instruction &FMFSource,
-                                           InstCombiner::BuilderTy &Builder) {
+Instruction *InstCombinerImpl::hoistFNegAboveFMulFDiv(Value *FNegOp,
+                                                      Instruction &FMFSource) {
   Value *X, *Y;
-  if (match(FNegOp, m_FMul(m_Value(X), m_Value(Y))))
-    return BinaryOperator::CreateFMulFMF(Builder.CreateFNegFMF(X, &FMFSource),
-                                         Y, &FMFSource);
+  if (match(FNegOp, m_FMul(m_Value(X), m_Value(Y)))) {
+    return cast<Instruction>(Builder.CreateFMulFMF(
+        Builder.CreateFNegFMF(X, &FMFSource), Y, &FMFSource));
+  }
+
+  if (match(FNegOp, m_FDiv(m_Value(X), m_Value(Y)))) {
+    return cast<Instruction>(Builder.CreateFDivFMF(
+        Builder.CreateFNegFMF(X, &FMFSource), Y, &FMFSource));
+  }
+
+  if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(FNegOp)) {
+    // Make sure to preserve flags and metadata on the call.
+    if (II->getIntrinsicID() == Intrinsic::ldexp) {
+      FastMathFlags FMF = FMFSource.getFastMathFlags();
+      FMF |= II->getFastMathFlags();
 
-  if (match(FNegOp, m_FDiv(m_Value(X), m_Value(Y))))
-    return BinaryOperator::CreateFDivFMF(Builder.CreateFNegFMF(X, &FMFSource),
-                                         Y, &FMFSource);
+      IRBuilder<>::FastMathFlagGuard FMFGuard(Builder);
+      Builder.setFastMathFlags(FMF);
+
+      CallInst *New = Builder.CreateCall(
+          II->getCalledFunction(),
+          {Builder.CreateFNeg(II->getArgOperand(0)), II->getArgOperand(1)});
+      New->copyMetadata(*II);
+      return New;
+    }
+  }
 
   return nullptr;
 }
@@ -2593,8 +2611,8 @@ Instruction *InstCombinerImpl::visitFNeg(UnaryOperator &I) {
   if (!match(Op, m_OneUse(m_Value(OneUse))))
     return nullptr;
 
-  if (Instruction *R = hoistFNegAboveFMulFDiv(OneUse, I, Builder))
-    return R;
+  if (Instruction *R = hoistFNegAboveFMulFDiv(OneUse, I))
+    return replaceInstUsesWith(I, R);
 
   // Try to eliminate fneg if at least 1 arm of the select is negated.
   Value *Cond;

diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
index 9d50e5b3a4ba44..7e9b916783a0e7 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
+++ b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
@@ -392,6 +392,8 @@ class LLVM_LIBRARY_VISIBILITY InstCombinerImpl final
   Instruction *foldAndOrOfSelectUsingImpliedCond(Value *Op, SelectInst &SI,
                                                  bool IsAnd);
 
+  Instruction *hoistFNegAboveFMulFDiv(Value *FNegOp, Instruction &FMFSource);
+
 public:
   /// Create and insert the idiom we use to indicate a block is unreachable
   /// without having to rewrite the CFG from within InstCombine.

diff  --git a/llvm/test/Transforms/InstCombine/fneg.ll b/llvm/test/Transforms/InstCombine/fneg.ll
index d9047ad53e814a..ed68ba50d36ee9 100644
--- a/llvm/test/Transforms/InstCombine/fneg.ll
+++ b/llvm/test/Transforms/InstCombine/fneg.ll
@@ -834,8 +834,8 @@ define float @select_fneg_use3(float %x, float %y, i1 %b) {
 
 define float @fneg_ldexp(float %x, i32 %n) {
 ; CHECK-LABEL: @fneg_ldexp(
-; CHECK-NEXT:    [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X:%.*]], i32 [[N:%.*]])
-; CHECK-NEXT:    [[NEG:%.*]] = fneg float [[LDEXP]]
+; CHECK-NEXT:    [[TMP1:%.*]] = fneg float [[X:%.*]]
+; CHECK-NEXT:    [[NEG:%.*]] = call float @llvm.ldexp.f32.i32(float [[TMP1]], i32 [[N:%.*]])
 ; CHECK-NEXT:    ret float [[NEG]]
 ;
   %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 %n)
@@ -845,8 +845,8 @@ define float @fneg_ldexp(float %x, i32 %n) {
 
 define float @fsub_fneg_ldexp(float %x, i32 %n) {
 ; CHECK-LABEL: @fsub_fneg_ldexp(
-; CHECK-NEXT:    [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X:%.*]], i32 [[N:%.*]])
-; CHECK-NEXT:    [[NEG:%.*]] = fneg float [[LDEXP]]
+; CHECK-NEXT:    [[TMP1:%.*]] = fneg float [[X:%.*]]
+; CHECK-NEXT:    [[NEG:%.*]] = call float @llvm.ldexp.f32.i32(float [[TMP1]], i32 [[N:%.*]])
 ; CHECK-NEXT:    ret float [[NEG]]
 ;
   %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 %n)
@@ -856,8 +856,8 @@ define float @fsub_fneg_ldexp(float %x, i32 %n) {
 
 define float @fsub_fneg_ldexp_nsz(float %x, i32 %n) {
 ; CHECK-LABEL: @fsub_fneg_ldexp_nsz(
-; CHECK-NEXT:    [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X:%.*]], i32 [[N:%.*]])
-; CHECK-NEXT:    [[NEG:%.*]] = fneg nsz float [[LDEXP]]
+; CHECK-NEXT:    [[TMP1:%.*]] = fneg nsz float [[X:%.*]]
+; CHECK-NEXT:    [[NEG:%.*]] = call nsz float @llvm.ldexp.f32.i32(float [[TMP1]], i32 [[N:%.*]])
 ; CHECK-NEXT:    ret float [[NEG]]
 ;
   %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 %n)
@@ -867,8 +867,8 @@ define float @fsub_fneg_ldexp_nsz(float %x, i32 %n) {
 
 define float @fsub_fneg_ldexp_p0_nsz(float %x, i32 %n) {
 ; CHECK-LABEL: @fsub_fneg_ldexp_p0_nsz(
-; CHECK-NEXT:    [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X:%.*]], i32 [[N:%.*]])
-; CHECK-NEXT:    [[NEG:%.*]] = fneg nsz float [[LDEXP]]
+; CHECK-NEXT:    [[TMP1:%.*]] = fneg nsz float [[X:%.*]]
+; CHECK-NEXT:    [[NEG:%.*]] = call nsz float @llvm.ldexp.f32.i32(float [[TMP1]], i32 [[N:%.*]])
 ; CHECK-NEXT:    ret float [[NEG]]
 ;
   %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 %n)
@@ -889,8 +889,8 @@ define float @fsub_fneg_ldexp_p0(float %x, i32 %n) {
 
 define <2 x float> @fneg_ldexp_vector(<2 x float> %x, <2 x i32> %n) {
 ; CHECK-LABEL: @fneg_ldexp_vector(
-; CHECK-NEXT:    [[LDEXP:%.*]] = call <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> [[X:%.*]], <2 x i32> [[N:%.*]])
-; CHECK-NEXT:    [[NEG:%.*]] = fneg <2 x float> [[LDEXP]]
+; CHECK-NEXT:    [[TMP1:%.*]] = fneg <2 x float> [[X:%.*]]
+; CHECK-NEXT:    [[NEG:%.*]] = call <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> [[TMP1]], <2 x i32> [[N:%.*]])
 ; CHECK-NEXT:    ret <2 x float> [[NEG]]
 ;
   %ldexp = call <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> %x, <2 x i32> %n)
@@ -913,8 +913,8 @@ define float @fneg_ldexp_multiuse(float %x, i32 %n, ptr %ptr) {
 
 define float @fneg_ldexp_fmf_ldexp(float %x, i32 %n) {
 ; CHECK-LABEL: @fneg_ldexp_fmf_ldexp(
-; CHECK-NEXT:    [[LDEXP:%.*]] = call nnan float @llvm.ldexp.f32.i32(float [[X:%.*]], i32 [[N:%.*]])
-; CHECK-NEXT:    [[NEG:%.*]] = fneg float [[LDEXP]]
+; CHECK-NEXT:    [[TMP1:%.*]] = fneg nnan float [[X:%.*]]
+; CHECK-NEXT:    [[NEG:%.*]] = call nnan float @llvm.ldexp.f32.i32(float [[TMP1]], i32 [[N:%.*]])
 ; CHECK-NEXT:    ret float [[NEG]]
 ;
   %ldexp = call nnan float @llvm.ldexp.f32.i32(float %x, i32 %n)
@@ -924,8 +924,8 @@ define float @fneg_ldexp_fmf_ldexp(float %x, i32 %n) {
 
 define float @fneg_ldexp_fmf_neg(float %x, i32 %n) {
 ; CHECK-LABEL: @fneg_ldexp_fmf_neg(
-; CHECK-NEXT:    [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X:%.*]], i32 [[N:%.*]])
-; CHECK-NEXT:    [[NEG:%.*]] = fneg nnan float [[LDEXP]]
+; CHECK-NEXT:    [[TMP1:%.*]] = fneg nnan float [[X:%.*]]
+; CHECK-NEXT:    [[NEG:%.*]] = call nnan float @llvm.ldexp.f32.i32(float [[TMP1]], i32 [[N:%.*]])
 ; CHECK-NEXT:    ret float [[NEG]]
 ;
   %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 %n)
@@ -935,8 +935,8 @@ define float @fneg_ldexp_fmf_neg(float %x, i32 %n) {
 
 define float @fneg_ldexp_fmf(float %x, i32 %n) {
 ; CHECK-LABEL: @fneg_ldexp_fmf(
-; CHECK-NEXT:    [[LDEXP:%.*]] = call ninf float @llvm.ldexp.f32.i32(float [[X:%.*]], i32 [[N:%.*]])
-; CHECK-NEXT:    [[NEG:%.*]] = fneg nnan float [[LDEXP]]
+; CHECK-NEXT:    [[TMP1:%.*]] = fneg nnan ninf float [[X:%.*]]
+; CHECK-NEXT:    [[NEG:%.*]] = call nnan ninf float @llvm.ldexp.f32.i32(float [[TMP1]], i32 [[N:%.*]])
 ; CHECK-NEXT:    ret float [[NEG]]
 ;
   %ldexp = call ninf float @llvm.ldexp.f32.i32(float %x, i32 %n)
@@ -946,8 +946,8 @@ define float @fneg_ldexp_fmf(float %x, i32 %n) {
 
 define float @fneg_ldexp_contract0(float %x, i32 %n) {
 ; CHECK-LABEL: @fneg_ldexp_contract0(
-; CHECK-NEXT:    [[LDEXP:%.*]] = call contract float @llvm.ldexp.f32.i32(float [[X:%.*]], i32 [[N:%.*]])
-; CHECK-NEXT:    [[NEG:%.*]] = fneg float [[LDEXP]]
+; CHECK-NEXT:    [[TMP1:%.*]] = fneg contract float [[X:%.*]]
+; CHECK-NEXT:    [[NEG:%.*]] = call contract float @llvm.ldexp.f32.i32(float [[TMP1]], i32 [[N:%.*]])
 ; CHECK-NEXT:    ret float [[NEG]]
 ;
   %ldexp = call contract float @llvm.ldexp.f32.i32(float %x, i32 %n)
@@ -957,8 +957,8 @@ define float @fneg_ldexp_contract0(float %x, i32 %n) {
 
 define float @fneg_ldexp_contract1(float %x, i32 %n) {
 ; CHECK-LABEL: @fneg_ldexp_contract1(
-; CHECK-NEXT:    [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X:%.*]], i32 [[N:%.*]])
-; CHECK-NEXT:    [[NEG:%.*]] = fneg contract float [[LDEXP]]
+; CHECK-NEXT:    [[TMP1:%.*]] = fneg contract float [[X:%.*]]
+; CHECK-NEXT:    [[NEG:%.*]] = call contract float @llvm.ldexp.f32.i32(float [[TMP1]], i32 [[N:%.*]])
 ; CHECK-NEXT:    ret float [[NEG]]
 ;
   %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 %n)
@@ -968,8 +968,8 @@ define float @fneg_ldexp_contract1(float %x, i32 %n) {
 
 define float @fneg_ldexp_contract(float %x, i32 %n) {
 ; CHECK-LABEL: @fneg_ldexp_contract(
-; CHECK-NEXT:    [[LDEXP:%.*]] = call contract float @llvm.ldexp.f32.i32(float [[X:%.*]], i32 [[N:%.*]])
-; CHECK-NEXT:    [[NEG:%.*]] = fneg contract float [[LDEXP]]
+; CHECK-NEXT:    [[TMP1:%.*]] = fneg contract float [[X:%.*]]
+; CHECK-NEXT:    [[NEG:%.*]] = call contract float @llvm.ldexp.f32.i32(float [[TMP1]], i32 [[N:%.*]])
 ; CHECK-NEXT:    ret float [[NEG]]
 ;
   %ldexp = call contract float @llvm.ldexp.f32.i32(float %x, i32 %n)
@@ -979,8 +979,8 @@ define float @fneg_ldexp_contract(float %x, i32 %n) {
 
 define float @fneg_ldexp_metadata(float %x, i32 %n) {
 ; CHECK-LABEL: @fneg_ldexp_metadata(
-; CHECK-NEXT:    [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X:%.*]], i32 [[N:%.*]]), !arst !0
-; CHECK-NEXT:    [[NEG:%.*]] = fneg float [[LDEXP]]
+; CHECK-NEXT:    [[TMP1:%.*]] = fneg float [[X:%.*]]
+; CHECK-NEXT:    [[NEG:%.*]] = call float @llvm.ldexp.f32.i32(float [[TMP1]], i32 [[N:%.*]]), !arst !0
 ; CHECK-NEXT:    ret float [[NEG]]
 ;
   %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 %n), !arst !0


        


More information about the llvm-commits mailing list