From 265547e39bd6ade2f3c7cd262dacc5a80a0e4900 Mon Sep 17 00:00:00 2001 From: Iris Shi <0.0@owo.li> Date: Sat, 21 Jun 2025 15:15:38 +0800 Subject: [PATCH 1/2] pre-commit tests --- llvm/test/Transforms/InstCombine/fdiv-exp.ll | 115 +++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 llvm/test/Transforms/InstCombine/fdiv-exp.ll diff --git a/llvm/test/Transforms/InstCombine/fdiv-exp.ll b/llvm/test/Transforms/InstCombine/fdiv-exp.ll new file mode 100644 index 0000000000000..a355c3bc6666d --- /dev/null +++ b/llvm/test/Transforms/InstCombine/fdiv-exp.ll @@ -0,0 +1,115 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 +; RUN: opt -S -passes=instcombine < %s | FileCheck %s + +define half @fdiv_exp_half(half %x) { +; CHECK-LABEL: define half @fdiv_exp_half( +; 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: ret half [[DIV]] +; +entry: + %exp_x = call fast half @llvm.exp.f16(half %x) + %exp_exp_x = call fast half @llvm.exp.f16(half %exp_x) + %div = fdiv fast half %exp_exp_x, %exp_x + ret half %div +} + +define float @fdiv_exp_float(float %x) { +; CHECK-LABEL: define float @fdiv_exp_float( +; 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: ret float [[DIV]] +; +entry: + %exp_x = call fast float @llvm.exp.f32(float %x) + %exp_exp_x = call fast float @llvm.exp.f32(float %exp_x) + %div = fdiv fast float %exp_exp_x, %exp_x + ret float %div +} + +define double @fdiv_exp_double(double %x) { +; CHECK-LABEL: define double @fdiv_exp_double( +; 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: ret double [[DIV]] +; +entry: + %exp_x = call fast double @llvm.exp.f64(double %x) + %exp_exp_x = call fast double @llvm.exp.f64(double %exp_x) + %div = fdiv fast double %exp_exp_x, %exp_x + ret double %div +} + +define double @fdiv_exp_swapped(double %x) { +; CHECK-LABEL: define double @fdiv_exp_swapped( +; CHECK-SAME: double [[X:%.*]]) { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[EXP_X:%.*]] = call fast double @llvm.exp.f64(double [[X]]) +; CHECK-NEXT: [[TMP0:%.*]] = fsub fast double [[X]], [[EXP_X]] +; CHECK-NEXT: [[DIV:%.*]] = call fast double @llvm.exp.f64(double [[TMP0]]) +; CHECK-NEXT: ret double [[DIV]] +; +entry: + %exp_x = call fast double @llvm.exp.f64(double %x) + %exp_exp_x = call fast double @llvm.exp.f64(double %exp_x) + %div = fdiv fast double %exp_x, %exp_exp_x + ret double %div +} + +define double @fdiv_exp_xy(double %x, double %y) { +; CHECK-LABEL: define double @fdiv_exp_xy( +; CHECK-SAME: double [[X:%.*]], double [[Y:%.*]]) { +; CHECK-NEXT: [[EXP_X:%.*]] = call fast double @llvm.exp.f64(double [[X]]) +; CHECK-NEXT: [[TMP1:%.*]] = fsub fast double [[EXP_X]], [[Y]] +; CHECK-NEXT: [[DIV:%.*]] = call fast double @llvm.exp.f64(double [[TMP1]]) +; CHECK-NEXT: ret double [[DIV]] +; + %exp_x = call fast double @llvm.exp.f64(double %x) + %exp_y = call fast double @llvm.exp.f64(double %y) + %exp_exp_x = call fast double @llvm.exp.f64(double %exp_x) + %div = fdiv fast double %exp_exp_x, %exp_y + ret double %div +} + +define double @fdiv_exp_use(double %x) { +; CHECK-LABEL: define double @fdiv_exp_use( +; 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: call void @use(double [[EXP_EXP_X]]) +; CHECK-NEXT: ret double [[DIV]] +; +entry: + %exp_x = call fast double @llvm.exp.f64(double %x) + %exp_exp_x = call fast double @llvm.exp.f64(double %exp_x) + %div = fdiv fast double %exp_exp_x, %exp_x + call void @use(double %exp_exp_x) + ret double %div +} + +define double @fdiv_exp_nofmf(double %x) { +; CHECK-LABEL: define double @fdiv_exp_nofmf( +; CHECK-SAME: double [[X:%.*]]) { +; CHECK-NEXT: [[EXP_X:%.*]] = call double @llvm.exp.f64(double [[X]]) +; CHECK-NEXT: [[EXP_EXP_X:%.*]] = call double @llvm.exp.f64(double [[EXP_X]]) +; CHECK-NEXT: [[DIV:%.*]] = fdiv double [[EXP_EXP_X]], [[EXP_X]] +; CHECK-NEXT: ret double [[DIV]] +; + %exp_x = call double @llvm.exp.f64(double %x) + %exp_exp_x = call double @llvm.exp.f64(double %exp_x) + %div = fdiv double %exp_exp_x, %exp_x + ret double %div +} + +declare void @use(double) From 0fc7ec0b45def5d03cb1822bc8672784b5f37fbe Mon Sep 17 00:00:00 2001 From: Iris Shi <0.0@owo.li> Date: Sat, 21 Jun 2025 15:30:42 +0800 Subject: [PATCH 2/2] [InstCombine] Fold `exp(exp(x)) / exp(x)` -> `exp(exp(x) - x)` --- .../Transforms/InstCombine/InstCombineMulDivRem.cpp | 10 ++++++++++ llvm/test/Transforms/InstCombine/fdiv-exp.ll | 12 ++++++------ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp index d7310b1c741c0..dc79448b247ec 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( + m_Intrinsic(m_Value(X))))) && + match(Op1, m_Intrinsic(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 a355c3bc6666d..32f231e6e93bd 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: pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy