Skip to content

Commit f7f5d34

Browse files
committed
InstCombine: Fold fneg (ldexp x, n) -> ldexp (fneg x), n
https://reviews.llvm.org/D156579
1 parent 5e6a204 commit f7f5d34

File tree

3 files changed

+55
-35
lines changed

3 files changed

+55
-35
lines changed

llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2557,17 +2557,35 @@ static Instruction *foldFNegIntoConstant(Instruction &I, const DataLayout &DL) {
25572557
return nullptr;
25582558
}
25592559

2560-
static Instruction *hoistFNegAboveFMulFDiv(Value *FNegOp,
2561-
Instruction &FMFSource,
2562-
InstCombiner::BuilderTy &Builder) {
2560+
Instruction *InstCombinerImpl::hoistFNegAboveFMulFDiv(Value *FNegOp,
2561+
Instruction &FMFSource) {
25632562
Value *X, *Y;
2564-
if (match(FNegOp, m_FMul(m_Value(X), m_Value(Y))))
2565-
return BinaryOperator::CreateFMulFMF(Builder.CreateFNegFMF(X, &FMFSource),
2566-
Y, &FMFSource);
2563+
if (match(FNegOp, m_FMul(m_Value(X), m_Value(Y)))) {
2564+
return cast<Instruction>(Builder.CreateFMulFMF(
2565+
Builder.CreateFNegFMF(X, &FMFSource), Y, &FMFSource));
2566+
}
2567+
2568+
if (match(FNegOp, m_FDiv(m_Value(X), m_Value(Y)))) {
2569+
return cast<Instruction>(Builder.CreateFDivFMF(
2570+
Builder.CreateFNegFMF(X, &FMFSource), Y, &FMFSource));
2571+
}
2572+
2573+
if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(FNegOp)) {
2574+
// Make sure to preserve flags and metadata on the call.
2575+
if (II->getIntrinsicID() == Intrinsic::ldexp) {
2576+
FastMathFlags FMF = FMFSource.getFastMathFlags();
2577+
FMF |= II->getFastMathFlags();
25672578

2568-
if (match(FNegOp, m_FDiv(m_Value(X), m_Value(Y))))
2569-
return BinaryOperator::CreateFDivFMF(Builder.CreateFNegFMF(X, &FMFSource),
2570-
Y, &FMFSource);
2579+
IRBuilder<>::FastMathFlagGuard FMFGuard(Builder);
2580+
Builder.setFastMathFlags(FMF);
2581+
2582+
CallInst *New = Builder.CreateCall(
2583+
II->getCalledFunction(),
2584+
{Builder.CreateFNeg(II->getArgOperand(0)), II->getArgOperand(1)});
2585+
New->copyMetadata(*II);
2586+
return New;
2587+
}
2588+
}
25712589

25722590
return nullptr;
25732591
}
@@ -2593,8 +2611,8 @@ Instruction *InstCombinerImpl::visitFNeg(UnaryOperator &I) {
25932611
if (!match(Op, m_OneUse(m_Value(OneUse))))
25942612
return nullptr;
25952613

2596-
if (Instruction *R = hoistFNegAboveFMulFDiv(OneUse, I, Builder))
2597-
return R;
2614+
if (Instruction *R = hoistFNegAboveFMulFDiv(OneUse, I))
2615+
return replaceInstUsesWith(I, R);
25982616

25992617
// Try to eliminate fneg if at least 1 arm of the select is negated.
26002618
Value *Cond;

llvm/lib/Transforms/InstCombine/InstCombineInternal.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,8 @@ class LLVM_LIBRARY_VISIBILITY InstCombinerImpl final
392392
Instruction *foldAndOrOfSelectUsingImpliedCond(Value *Op, SelectInst &SI,
393393
bool IsAnd);
394394

395+
Instruction *hoistFNegAboveFMulFDiv(Value *FNegOp, Instruction &FMFSource);
396+
395397
public:
396398
/// Create and insert the idiom we use to indicate a block is unreachable
397399
/// without having to rewrite the CFG from within InstCombine.

llvm/test/Transforms/InstCombine/fneg.ll

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -834,8 +834,8 @@ define float @select_fneg_use3(float %x, float %y, i1 %b) {
834834

835835
define float @fneg_ldexp(float %x, i32 %n) {
836836
; CHECK-LABEL: @fneg_ldexp(
837-
; CHECK-NEXT: [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X:%.*]], i32 [[N:%.*]])
838-
; CHECK-NEXT: [[NEG:%.*]] = fneg float [[LDEXP]]
837+
; CHECK-NEXT: [[TMP1:%.*]] = fneg float [[X:%.*]]
838+
; CHECK-NEXT: [[NEG:%.*]] = call float @llvm.ldexp.f32.i32(float [[TMP1]], i32 [[N:%.*]])
839839
; CHECK-NEXT: ret float [[NEG]]
840840
;
841841
%ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 %n)
@@ -845,8 +845,8 @@ define float @fneg_ldexp(float %x, i32 %n) {
845845

846846
define float @fsub_fneg_ldexp(float %x, i32 %n) {
847847
; CHECK-LABEL: @fsub_fneg_ldexp(
848-
; CHECK-NEXT: [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X:%.*]], i32 [[N:%.*]])
849-
; CHECK-NEXT: [[NEG:%.*]] = fneg float [[LDEXP]]
848+
; CHECK-NEXT: [[TMP1:%.*]] = fneg float [[X:%.*]]
849+
; CHECK-NEXT: [[NEG:%.*]] = call float @llvm.ldexp.f32.i32(float [[TMP1]], i32 [[N:%.*]])
850850
; CHECK-NEXT: ret float [[NEG]]
851851
;
852852
%ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 %n)
@@ -856,8 +856,8 @@ define float @fsub_fneg_ldexp(float %x, i32 %n) {
856856

857857
define float @fsub_fneg_ldexp_nsz(float %x, i32 %n) {
858858
; CHECK-LABEL: @fsub_fneg_ldexp_nsz(
859-
; CHECK-NEXT: [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X:%.*]], i32 [[N:%.*]])
860-
; CHECK-NEXT: [[NEG:%.*]] = fneg nsz float [[LDEXP]]
859+
; CHECK-NEXT: [[TMP1:%.*]] = fneg nsz float [[X:%.*]]
860+
; CHECK-NEXT: [[NEG:%.*]] = call nsz float @llvm.ldexp.f32.i32(float [[TMP1]], i32 [[N:%.*]])
861861
; CHECK-NEXT: ret float [[NEG]]
862862
;
863863
%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) {
867867

868868
define float @fsub_fneg_ldexp_p0_nsz(float %x, i32 %n) {
869869
; CHECK-LABEL: @fsub_fneg_ldexp_p0_nsz(
870-
; CHECK-NEXT: [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X:%.*]], i32 [[N:%.*]])
871-
; CHECK-NEXT: [[NEG:%.*]] = fneg nsz float [[LDEXP]]
870+
; CHECK-NEXT: [[TMP1:%.*]] = fneg nsz float [[X:%.*]]
871+
; CHECK-NEXT: [[NEG:%.*]] = call nsz float @llvm.ldexp.f32.i32(float [[TMP1]], i32 [[N:%.*]])
872872
; CHECK-NEXT: ret float [[NEG]]
873873
;
874874
%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) {
889889

890890
define <2 x float> @fneg_ldexp_vector(<2 x float> %x, <2 x i32> %n) {
891891
; CHECK-LABEL: @fneg_ldexp_vector(
892-
; CHECK-NEXT: [[LDEXP:%.*]] = call <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> [[X:%.*]], <2 x i32> [[N:%.*]])
893-
; CHECK-NEXT: [[NEG:%.*]] = fneg <2 x float> [[LDEXP]]
892+
; CHECK-NEXT: [[TMP1:%.*]] = fneg <2 x float> [[X:%.*]]
893+
; CHECK-NEXT: [[NEG:%.*]] = call <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> [[TMP1]], <2 x i32> [[N:%.*]])
894894
; CHECK-NEXT: ret <2 x float> [[NEG]]
895895
;
896896
%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) {
913913

914914
define float @fneg_ldexp_fmf_ldexp(float %x, i32 %n) {
915915
; CHECK-LABEL: @fneg_ldexp_fmf_ldexp(
916-
; CHECK-NEXT: [[LDEXP:%.*]] = call nnan float @llvm.ldexp.f32.i32(float [[X:%.*]], i32 [[N:%.*]])
917-
; CHECK-NEXT: [[NEG:%.*]] = fneg float [[LDEXP]]
916+
; CHECK-NEXT: [[TMP1:%.*]] = fneg nnan float [[X:%.*]]
917+
; CHECK-NEXT: [[NEG:%.*]] = call nnan float @llvm.ldexp.f32.i32(float [[TMP1]], i32 [[N:%.*]])
918918
; CHECK-NEXT: ret float [[NEG]]
919919
;
920920
%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) {
924924

925925
define float @fneg_ldexp_fmf_neg(float %x, i32 %n) {
926926
; CHECK-LABEL: @fneg_ldexp_fmf_neg(
927-
; CHECK-NEXT: [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X:%.*]], i32 [[N:%.*]])
928-
; CHECK-NEXT: [[NEG:%.*]] = fneg nnan float [[LDEXP]]
927+
; CHECK-NEXT: [[TMP1:%.*]] = fneg nnan float [[X:%.*]]
928+
; CHECK-NEXT: [[NEG:%.*]] = call nnan float @llvm.ldexp.f32.i32(float [[TMP1]], i32 [[N:%.*]])
929929
; CHECK-NEXT: ret float [[NEG]]
930930
;
931931
%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) {
935935

936936
define float @fneg_ldexp_fmf(float %x, i32 %n) {
937937
; CHECK-LABEL: @fneg_ldexp_fmf(
938-
; CHECK-NEXT: [[LDEXP:%.*]] = call ninf float @llvm.ldexp.f32.i32(float [[X:%.*]], i32 [[N:%.*]])
939-
; CHECK-NEXT: [[NEG:%.*]] = fneg nnan float [[LDEXP]]
938+
; CHECK-NEXT: [[TMP1:%.*]] = fneg nnan ninf float [[X:%.*]]
939+
; CHECK-NEXT: [[NEG:%.*]] = call nnan ninf float @llvm.ldexp.f32.i32(float [[TMP1]], i32 [[N:%.*]])
940940
; CHECK-NEXT: ret float [[NEG]]
941941
;
942942
%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) {
946946

947947
define float @fneg_ldexp_contract0(float %x, i32 %n) {
948948
; CHECK-LABEL: @fneg_ldexp_contract0(
949-
; CHECK-NEXT: [[LDEXP:%.*]] = call contract float @llvm.ldexp.f32.i32(float [[X:%.*]], i32 [[N:%.*]])
950-
; CHECK-NEXT: [[NEG:%.*]] = fneg float [[LDEXP]]
949+
; CHECK-NEXT: [[TMP1:%.*]] = fneg contract float [[X:%.*]]
950+
; CHECK-NEXT: [[NEG:%.*]] = call contract float @llvm.ldexp.f32.i32(float [[TMP1]], i32 [[N:%.*]])
951951
; CHECK-NEXT: ret float [[NEG]]
952952
;
953953
%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) {
957957

958958
define float @fneg_ldexp_contract1(float %x, i32 %n) {
959959
; CHECK-LABEL: @fneg_ldexp_contract1(
960-
; CHECK-NEXT: [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X:%.*]], i32 [[N:%.*]])
961-
; CHECK-NEXT: [[NEG:%.*]] = fneg contract float [[LDEXP]]
960+
; CHECK-NEXT: [[TMP1:%.*]] = fneg contract float [[X:%.*]]
961+
; CHECK-NEXT: [[NEG:%.*]] = call contract float @llvm.ldexp.f32.i32(float [[TMP1]], i32 [[N:%.*]])
962962
; CHECK-NEXT: ret float [[NEG]]
963963
;
964964
%ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 %n)
@@ -968,8 +968,8 @@ define float @fneg_ldexp_contract1(float %x, i32 %n) {
968968

969969
define float @fneg_ldexp_contract(float %x, i32 %n) {
970970
; CHECK-LABEL: @fneg_ldexp_contract(
971-
; CHECK-NEXT: [[LDEXP:%.*]] = call contract float @llvm.ldexp.f32.i32(float [[X:%.*]], i32 [[N:%.*]])
972-
; CHECK-NEXT: [[NEG:%.*]] = fneg contract float [[LDEXP]]
971+
; CHECK-NEXT: [[TMP1:%.*]] = fneg contract float [[X:%.*]]
972+
; CHECK-NEXT: [[NEG:%.*]] = call contract float @llvm.ldexp.f32.i32(float [[TMP1]], i32 [[N:%.*]])
973973
; CHECK-NEXT: ret float [[NEG]]
974974
;
975975
%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) {
979979

980980
define float @fneg_ldexp_metadata(float %x, i32 %n) {
981981
; CHECK-LABEL: @fneg_ldexp_metadata(
982-
; CHECK-NEXT: [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X:%.*]], i32 [[N:%.*]]), !arst !0
983-
; CHECK-NEXT: [[NEG:%.*]] = fneg float [[LDEXP]]
982+
; CHECK-NEXT: [[TMP1:%.*]] = fneg float [[X:%.*]]
983+
; CHECK-NEXT: [[NEG:%.*]] = call float @llvm.ldexp.f32.i32(float [[TMP1]], i32 [[N:%.*]]), !arst !0
984984
; CHECK-NEXT: ret float [[NEG]]
985985
;
986986
%ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 %n), !arst !0

0 commit comments

Comments
 (0)