summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIris Shi <0.0@owo.li>2025-06-21 15:30:42 +0800
committerIris Shi <0.0@owo.li>2025-06-21 15:30:42 +0800
commit0fc7ec0b45def5d03cb1822bc8672784b5f37fbe (patch)
treeb5c7280c76d6c215df7dc6fbba750270382a1c9c
parent265547e39bd6ade2f3c7cd262dacc5a80a0e4900 (diff)
[InstCombine] Fold `exp(exp(x)) / exp(x)` -> `exp(exp(x) - x)`users/el-ev/issue65608
-rw-r--r--llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp10
-rw-r--r--llvm/test/Transforms/InstCombine/fdiv-exp.ll12
2 files changed, 16 insertions, 6 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
index d7310b1c741c..dc79448b247e 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -2233,6 +2233,16 @@ Instruction *InstCombinerImpl::visitFDiv(BinaryOperator &I) {
if (Instruction *Mul = foldFDivPowDivisor(I, Builder))
return Mul;
+ // exp(exp(X)) / exp(X) -> exp(exp(X) - X)
+ if (I.hasAllowReassoc() &&
+ match(Op0, m_OneUse(m_Intrinsic<Intrinsic::exp>(
+ m_Intrinsic<Intrinsic::exp>(m_Value(X))))) &&
+ match(Op1, m_Intrinsic<Intrinsic::exp>(m_Specific(X)))) {
+ Value *ExpDiff = Builder.CreateFSubFMF(Op1, X, &I);
+ Value *NewExp = Builder.CreateUnaryIntrinsic(Intrinsic::exp, ExpDiff, &I);
+ return replaceInstUsesWith(I, NewExp);
+ }
+
if (Instruction *Mul = foldFDivSqrtDivisor(I, Builder))
return Mul;
diff --git a/llvm/test/Transforms/InstCombine/fdiv-exp.ll b/llvm/test/Transforms/InstCombine/fdiv-exp.ll
index a355c3bc6666..32f231e6e93b 100644
--- a/llvm/test/Transforms/InstCombine/fdiv-exp.ll
+++ b/llvm/test/Transforms/InstCombine/fdiv-exp.ll
@@ -6,8 +6,8 @@ define half @fdiv_exp_half(half %x) {
; CHECK-SAME: half [[X:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[EXP_X:%.*]] = call fast half @llvm.exp.f16(half [[X]])
-; CHECK-NEXT: [[EXP_EXP_X:%.*]] = call fast half @llvm.exp.f16(half [[EXP_X]])
-; CHECK-NEXT: [[DIV:%.*]] = fdiv fast half [[EXP_EXP_X]], [[EXP_X]]
+; CHECK-NEXT: [[TMP0:%.*]] = fsub fast half [[EXP_X]], [[X]]
+; CHECK-NEXT: [[DIV:%.*]] = call fast half @llvm.exp.f16(half [[TMP0]])
; CHECK-NEXT: ret half [[DIV]]
;
entry:
@@ -22,8 +22,8 @@ define float @fdiv_exp_float(float %x) {
; CHECK-SAME: float [[X:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[EXP_X:%.*]] = call fast float @llvm.exp.f32(float [[X]])
-; CHECK-NEXT: [[EXP_EXP_X:%.*]] = call fast float @llvm.exp.f32(float [[EXP_X]])
-; CHECK-NEXT: [[DIV:%.*]] = fdiv fast float [[EXP_EXP_X]], [[EXP_X]]
+; CHECK-NEXT: [[TMP0:%.*]] = fsub fast float [[EXP_X]], [[X]]
+; CHECK-NEXT: [[DIV:%.*]] = call fast float @llvm.exp.f32(float [[TMP0]])
; CHECK-NEXT: ret float [[DIV]]
;
entry:
@@ -38,8 +38,8 @@ define double @fdiv_exp_double(double %x) {
; CHECK-SAME: double [[X:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[EXP_X:%.*]] = call fast double @llvm.exp.f64(double [[X]])
-; CHECK-NEXT: [[EXP_EXP_X:%.*]] = call fast double @llvm.exp.f64(double [[EXP_X]])
-; CHECK-NEXT: [[DIV:%.*]] = fdiv fast double [[EXP_EXP_X]], [[EXP_X]]
+; CHECK-NEXT: [[TMP0:%.*]] = fsub fast double [[EXP_X]], [[X]]
+; CHECK-NEXT: [[DIV:%.*]] = call fast double @llvm.exp.f64(double [[TMP0]])
; CHECK-NEXT: ret double [[DIV]]
;
entry: