Skip to content

Commit e772618

Browse files
committed
[InstCombine] fold fdiv with exp/exp2 divisor (PR49147)
Follow-up to: D96648 / b40fde0 ...for the special-case base calls. From the earlier commit: This is unusual in the general (non-reciprocal) case because we need an extra instruction, but that should be better for general FP reassociation and codegen. We conservatively check for "arcp" FMF here as we do with existing fdiv folds, but it is not strictly necessary to have that.
1 parent fbca27b commit e772618

File tree

2 files changed

+24
-11
lines changed

2 files changed

+24
-11
lines changed

llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1326,8 +1326,9 @@ Instruction *InstCombinerImpl::visitFDiv(BinaryOperator &I) {
13261326
if (match(Op1, m_FDiv(m_SpecificFP(1.0), m_Value(Y))))
13271327
return BinaryOperator::CreateFMulFMF(Y, Op0, &I);
13281328

1329-
// Negate the exponent of pow to fold division-by-pow() into multiply:
1329+
// Negate the exponent of pow/exp to fold division-by-pow() into multiply:
13301330
// Z / pow(X, Y) --> Z * pow(X, -Y)
1331+
// Z / exp{2}(Y) --> Z * exp{2}(-Y)
13311332
// In the general case, this creates an extra instruction, but fmul allows
13321333
// for better canonicalization and optimization than fdiv.
13331334
if (match(Op1,
@@ -1336,6 +1337,16 @@ Instruction *InstCombinerImpl::visitFDiv(BinaryOperator &I) {
13361337
Value *Pow = Builder.CreateBinaryIntrinsic(Intrinsic::pow, X, NegY, &I);
13371338
return BinaryOperator::CreateFMulFMF(Op0, Pow, &I);
13381339
}
1340+
if (match(Op1, m_OneUse(m_Intrinsic<Intrinsic::exp>(m_Value(Y))))) {
1341+
Value *NegY = Builder.CreateFNegFMF(Y, &I);
1342+
Value *Pow = Builder.CreateUnaryIntrinsic(Intrinsic::exp, NegY, &I);
1343+
return BinaryOperator::CreateFMulFMF(Op0, Pow, &I);
1344+
}
1345+
if (match(Op1, m_OneUse(m_Intrinsic<Intrinsic::exp2>(m_Value(Y))))) {
1346+
Value *NegY = Builder.CreateFNegFMF(Y, &I);
1347+
Value *Pow = Builder.CreateUnaryIntrinsic(Intrinsic::exp2, NegY, &I);
1348+
return BinaryOperator::CreateFMulFMF(Op0, Pow, &I);
1349+
}
13391350
}
13401351

13411352
if (I.hasAllowReassoc() && Op0->hasOneUse() && Op1->hasOneUse()) {

llvm/test/Transforms/InstCombine/fdiv.ll

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -731,8 +731,9 @@ define <2 x half> @pow_recip(<2 x half> %x, <2 x half> %y) {
731731

732732
define float @exp_divisor(float %y, float %z) {
733733
; CHECK-LABEL: @exp_divisor(
734-
; CHECK-NEXT: [[P:%.*]] = call float @llvm.exp.f32(float [[Y:%.*]])
735-
; CHECK-NEXT: [[R:%.*]] = fdiv reassoc arcp float [[Z:%.*]], [[P]]
734+
; CHECK-NEXT: [[TMP1:%.*]] = fneg reassoc arcp float [[Y:%.*]]
735+
; CHECK-NEXT: [[TMP2:%.*]] = call reassoc arcp float @llvm.exp.f32(float [[TMP1]])
736+
; CHECK-NEXT: [[R:%.*]] = fmul reassoc arcp float [[TMP2]], [[Z:%.*]]
736737
; CHECK-NEXT: ret float [[R]]
737738
;
738739
%p = call float @llvm.exp.f32(float %y)
@@ -785,9 +786,9 @@ define float @exp_divisor_not_enough_fmf2(float %y, float %z) {
785786

786787
define <2 x half> @exp_recip(<2 x half> %x, <2 x half> %y) {
787788
; CHECK-LABEL: @exp_recip(
788-
; CHECK-NEXT: [[P:%.*]] = call <2 x half> @llvm.exp.v2f16(<2 x half> [[Y:%.*]])
789-
; CHECK-NEXT: [[R:%.*]] = fdiv reassoc ninf arcp <2 x half> <half 0xH3C00, half 0xH3C00>, [[P]]
790-
; CHECK-NEXT: ret <2 x half> [[R]]
789+
; CHECK-NEXT: [[TMP1:%.*]] = fneg reassoc ninf arcp <2 x half> [[Y:%.*]]
790+
; CHECK-NEXT: [[TMP2:%.*]] = call reassoc ninf arcp <2 x half> @llvm.exp.v2f16(<2 x half> [[TMP1]])
791+
; CHECK-NEXT: ret <2 x half> [[TMP2]]
791792
;
792793
%p = call <2 x half> @llvm.exp.v2f16(<2 x half> %y)
793794
%r = fdiv reassoc arcp ninf <2 x half> <half 1.0, half 1.0>, %p
@@ -796,8 +797,9 @@ define <2 x half> @exp_recip(<2 x half> %x, <2 x half> %y) {
796797

797798
define float @exp2_divisor(float %y, float %z) {
798799
; CHECK-LABEL: @exp2_divisor(
799-
; CHECK-NEXT: [[P:%.*]] = call float @llvm.exp2.f32(float [[Y:%.*]])
800-
; CHECK-NEXT: [[R:%.*]] = fdiv reassoc arcp float [[Z:%.*]], [[P]]
800+
; CHECK-NEXT: [[TMP1:%.*]] = fneg reassoc arcp float [[Y:%.*]]
801+
; CHECK-NEXT: [[TMP2:%.*]] = call reassoc arcp float @llvm.exp2.f32(float [[TMP1]])
802+
; CHECK-NEXT: [[R:%.*]] = fmul reassoc arcp float [[TMP2]], [[Z:%.*]]
801803
; CHECK-NEXT: ret float [[R]]
802804
;
803805
%p = call float @llvm.exp2.f32(float %y)
@@ -850,9 +852,9 @@ define float @exp2_divisor_not_enough_fmf2(float %y, float %z) {
850852

851853
define <2 x half> @exp2_recip(<2 x half> %x, <2 x half> %y) {
852854
; CHECK-LABEL: @exp2_recip(
853-
; CHECK-NEXT: [[P:%.*]] = call <2 x half> @llvm.exp2.v2f16(<2 x half> [[Y:%.*]])
854-
; CHECK-NEXT: [[R:%.*]] = fdiv reassoc ninf arcp <2 x half> <half 0xH3C00, half 0xH3C00>, [[P]]
855-
; CHECK-NEXT: ret <2 x half> [[R]]
855+
; CHECK-NEXT: [[TMP1:%.*]] = fneg reassoc ninf arcp <2 x half> [[Y:%.*]]
856+
; CHECK-NEXT: [[TMP2:%.*]] = call reassoc ninf arcp <2 x half> @llvm.exp2.v2f16(<2 x half> [[TMP1]])
857+
; CHECK-NEXT: ret <2 x half> [[TMP2]]
856858
;
857859
%p = call <2 x half> @llvm.exp2.v2f16(<2 x half> %y)
858860
%r = fdiv reassoc arcp ninf <2 x half> <half 1.0, half 1.0>, %p

0 commit comments

Comments
 (0)