Skip to content

SimplifyLibCalls: Prefer to emit intrinsic in pow(2, x) -> ldexp(1, x) #92363

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

arsenm
Copy link
Contributor

@arsenm arsenm commented May 16, 2024

No description provided.

@arsenm arsenm added llvm:instcombine Covers the InstCombine, InstSimplify and AggressiveInstCombine passes floating-point Floating-point math labels May 16, 2024
@llvmbot
Copy link
Member

llvmbot commented May 16, 2024

@llvm/pr-subscribers-llvm-transforms

Author: Matt Arsenault (arsenm)

Changes

Patch is 30.00 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/92363.diff

4 Files Affected:

  • (modified) llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp (+13-5)
  • (added) llvm/test/Transforms/InstCombine/pow-to-ldexp.ll (+492)
  • (modified) llvm/test/Transforms/InstCombine/pow_fp_int.ll (+3-3)
  • (modified) llvm/test/Transforms/InstCombine/pow_fp_int16.ll (+3-3)
diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
index c9f6839e4b94a..c9567b740026b 100644
--- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
@@ -2092,11 +2092,19 @@ Value *LibCallSimplifier::replacePowWithExp(CallInst *Pow, IRBuilderBase &B) {
   if (!Ty->isVectorTy() && match(Base, m_SpecificFP(2.0)) &&
       (isa<SIToFPInst>(Expo) || isa<UIToFPInst>(Expo)) &&
       hasFloatFn(M, TLI, Ty, LibFunc_ldexp, LibFunc_ldexpf, LibFunc_ldexpl)) {
-    if (Value *ExpoI = getIntToFPVal(Expo, B, TLI->getIntSize()))
-      return copyFlags(*Pow,
-                       emitBinaryFloatFnCall(ConstantFP::get(Ty, 1.0), ExpoI,
-                                             TLI, LibFunc_ldexp, LibFunc_ldexpf,
-                                             LibFunc_ldexpl, B, NoAttrs));
+    if (Value *ExpoI = getIntToFPVal(Expo, B, TLI->getIntSize())) {
+      Constant *One = ConstantFP::get(Ty, 1.0);
+
+      if (Pow->doesNotAccessMemory()) {
+        return copyFlags(*Pow, B.CreateIntrinsic(Intrinsic::ldexp,
+                                                 {Ty, ExpoI->getType()},
+                                                 {One, ExpoI}, Pow, "exp2"));
+      }
+
+      return copyFlags(*Pow, emitBinaryFloatFnCall(
+                                 One, ExpoI, TLI, LibFunc_ldexp, LibFunc_ldexpf,
+                                 LibFunc_ldexpl, B, NoAttrs));
+    }
   }
 
   // pow(2.0 ** n, x) -> exp2(n * x)
diff --git a/llvm/test/Transforms/InstCombine/pow-to-ldexp.ll b/llvm/test/Transforms/InstCombine/pow-to-ldexp.ll
new file mode 100644
index 0000000000000..27249dd5d72ae
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/pow-to-ldexp.ll
@@ -0,0 +1,492 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
+; RUN: opt -S -passes=instcombine %s | FileCheck -check-prefixes=CHECK,LDEXP,LDEXP-EXP2 %s
+; RUN: opt -S -passes=instcombine -disable-builtin=exp2f -disable-builtin=exp2 -disable-builtin=exp2l %s | FileCheck -check-prefixes=CHECK,LDEXP,LDEXP-NOEXP2 %s
+; RUN: opt -S -passes=instcombine -disable-builtin=ldexpf -disable-builtin=ldexp -disable-builtin=ldexpl %s | FileCheck -check-prefixes=CHECK,NOLDEXP %s
+
+
+define float @pow_sitofp_f32_const_base_2(i32 %x) {
+; LDEXP-LABEL: define float @pow_sitofp_f32_const_base_2(
+; LDEXP-SAME: i32 [[X:%.*]]) {
+; LDEXP-NEXT:    [[LDEXPF:%.*]] = tail call float @llvm.ldexp.f32.i32(float 1.000000e+00, i32 [[X]])
+; LDEXP-NEXT:    ret float [[LDEXPF]]
+;
+; NOLDEXP-LABEL: define float @pow_sitofp_f32_const_base_2(
+; NOLDEXP-SAME: i32 [[X:%.*]]) {
+; NOLDEXP-NEXT:    [[ITOFP:%.*]] = sitofp i32 [[X]] to float
+; NOLDEXP-NEXT:    [[POW:%.*]] = tail call float @llvm.exp2.f32(float [[ITOFP]])
+; NOLDEXP-NEXT:    ret float [[POW]]
+;
+  %itofp = sitofp i32 %x to float
+  %pow = tail call float @llvm.pow.f32(float 2.000000e+00, float %itofp)
+  ret float %pow
+}
+
+define float @pow_sitofp_f32_const_base_2__flags(i32 %x) {
+; LDEXP-LABEL: define float @pow_sitofp_f32_const_base_2__flags(
+; LDEXP-SAME: i32 [[X:%.*]]) {
+; LDEXP-NEXT:    [[LDEXPF:%.*]] = tail call nnan nsz float @llvm.ldexp.f32.i32(float 1.000000e+00, i32 [[X]])
+; LDEXP-NEXT:    ret float [[LDEXPF]]
+;
+; NOLDEXP-LABEL: define float @pow_sitofp_f32_const_base_2__flags(
+; NOLDEXP-SAME: i32 [[X:%.*]]) {
+; NOLDEXP-NEXT:    [[ITOFP:%.*]] = sitofp i32 [[X]] to float
+; NOLDEXP-NEXT:    [[EXP2:%.*]] = tail call nnan nsz float @llvm.exp2.f32(float [[ITOFP]])
+; NOLDEXP-NEXT:    ret float [[EXP2]]
+;
+  %itofp = sitofp i32 %x to float
+  %pow = tail call nsz nnan float @llvm.pow.f32(float 2.000000e+00, float %itofp)
+  ret float %pow
+}
+
+define float @pow_uitofp_f32_const_base_2(i32 %x) {
+; LDEXP-EXP2-LABEL: define float @pow_uitofp_f32_const_base_2(
+; LDEXP-EXP2-SAME: i32 [[X:%.*]]) {
+; LDEXP-EXP2-NEXT:    [[ITOFP:%.*]] = uitofp i32 [[X]] to float
+; LDEXP-EXP2-NEXT:    [[EXP2:%.*]] = tail call float @llvm.exp2.f32(float [[ITOFP]])
+; LDEXP-EXP2-NEXT:    ret float [[EXP2]]
+;
+; LDEXP-NOEXP2-LABEL: define float @pow_uitofp_f32_const_base_2(
+; LDEXP-NOEXP2-SAME: i32 [[X:%.*]]) {
+; LDEXP-NOEXP2-NEXT:    [[ITOFP:%.*]] = uitofp i32 [[X]] to float
+; LDEXP-NOEXP2-NEXT:    [[POW:%.*]] = tail call float @llvm.pow.f32(float 2.000000e+00, float [[ITOFP]])
+; LDEXP-NOEXP2-NEXT:    ret float [[POW]]
+;
+; NOLDEXP-LABEL: define float @pow_uitofp_f32_const_base_2(
+; NOLDEXP-SAME: i32 [[X:%.*]]) {
+; NOLDEXP-NEXT:    [[ITOFP:%.*]] = uitofp i32 [[X]] to float
+; NOLDEXP-NEXT:    [[EXP2:%.*]] = tail call float @llvm.exp2.f32(float [[ITOFP]])
+; NOLDEXP-NEXT:    ret float [[EXP2]]
+;
+  %itofp = uitofp i32 %x to float
+  %pow = tail call float @llvm.pow.f32(float 2.000000e+00, float %itofp)
+  ret float %pow
+}
+
+define float @pow_sitofp_f32_const_base_4(i32 %x) {
+; LDEXP-EXP2-LABEL: define float @pow_sitofp_f32_const_base_4(
+; LDEXP-EXP2-SAME: i32 [[X:%.*]]) {
+; LDEXP-EXP2-NEXT:    [[ITOFP:%.*]] = sitofp i32 [[X]] to float
+; LDEXP-EXP2-NEXT:    [[MUL:%.*]] = fmul float [[ITOFP]], 2.000000e+00
+; LDEXP-EXP2-NEXT:    [[EXP2:%.*]] = tail call float @llvm.exp2.f32(float [[MUL]])
+; LDEXP-EXP2-NEXT:    ret float [[EXP2]]
+;
+; LDEXP-NOEXP2-LABEL: define float @pow_sitofp_f32_const_base_4(
+; LDEXP-NOEXP2-SAME: i32 [[X:%.*]]) {
+; LDEXP-NOEXP2-NEXT:    [[ITOFP:%.*]] = sitofp i32 [[X]] to float
+; LDEXP-NOEXP2-NEXT:    [[POW:%.*]] = tail call float @llvm.pow.f32(float 4.000000e+00, float [[ITOFP]])
+; LDEXP-NOEXP2-NEXT:    ret float [[POW]]
+;
+; NOLDEXP-LABEL: define float @pow_sitofp_f32_const_base_4(
+; NOLDEXP-SAME: i32 [[X:%.*]]) {
+; NOLDEXP-NEXT:    [[ITOFP:%.*]] = sitofp i32 [[X]] to float
+; NOLDEXP-NEXT:    [[MUL:%.*]] = fmul float [[ITOFP]], 2.000000e+00
+; NOLDEXP-NEXT:    [[EXP2:%.*]] = tail call float @llvm.exp2.f32(float [[MUL]])
+; NOLDEXP-NEXT:    ret float [[EXP2]]
+;
+  %itofp = sitofp i32 %x to float
+  %pow = tail call float @llvm.pow.f32(float 4.000000e+00, float %itofp)
+  ret float %pow
+}
+
+define float @pow_sitofp_f32_const_base_16(i32 %x) {
+; LDEXP-EXP2-LABEL: define float @pow_sitofp_f32_const_base_16(
+; LDEXP-EXP2-SAME: i32 [[X:%.*]]) {
+; LDEXP-EXP2-NEXT:    [[ITOFP:%.*]] = sitofp i32 [[X]] to float
+; LDEXP-EXP2-NEXT:    [[MUL:%.*]] = fmul float [[ITOFP]], 4.000000e+00
+; LDEXP-EXP2-NEXT:    [[EXP2:%.*]] = tail call float @llvm.exp2.f32(float [[MUL]])
+; LDEXP-EXP2-NEXT:    ret float [[EXP2]]
+;
+; LDEXP-NOEXP2-LABEL: define float @pow_sitofp_f32_const_base_16(
+; LDEXP-NOEXP2-SAME: i32 [[X:%.*]]) {
+; LDEXP-NOEXP2-NEXT:    [[ITOFP:%.*]] = sitofp i32 [[X]] to float
+; LDEXP-NOEXP2-NEXT:    [[POW:%.*]] = tail call float @llvm.pow.f32(float 1.600000e+01, float [[ITOFP]])
+; LDEXP-NOEXP2-NEXT:    ret float [[POW]]
+;
+; NOLDEXP-LABEL: define float @pow_sitofp_f32_const_base_16(
+; NOLDEXP-SAME: i32 [[X:%.*]]) {
+; NOLDEXP-NEXT:    [[ITOFP:%.*]] = sitofp i32 [[X]] to float
+; NOLDEXP-NEXT:    [[MUL:%.*]] = fmul float [[ITOFP]], 4.000000e+00
+; NOLDEXP-NEXT:    [[EXP2:%.*]] = tail call float @llvm.exp2.f32(float [[MUL]])
+; NOLDEXP-NEXT:    ret float [[EXP2]]
+;
+  %itofp = sitofp i32 %x to float
+  %pow = tail call float @llvm.pow.f32(float 16.000000e+00, float %itofp)
+  ret float %pow
+}
+
+define double @pow_sitofp_f64_const_base_2(i32 %x) {
+; LDEXP-LABEL: define double @pow_sitofp_f64_const_base_2(
+; LDEXP-SAME: i32 [[X:%.*]]) {
+; LDEXP-NEXT:    [[LDEXP:%.*]] = tail call double @llvm.ldexp.f64.i32(double 1.000000e+00, i32 [[X]])
+; LDEXP-NEXT:    ret double [[LDEXP]]
+;
+; NOLDEXP-LABEL: define double @pow_sitofp_f64_const_base_2(
+; NOLDEXP-SAME: i32 [[X:%.*]]) {
+; NOLDEXP-NEXT:    [[ITOFP:%.*]] = sitofp i32 [[X]] to double
+; NOLDEXP-NEXT:    [[POW:%.*]] = tail call double @llvm.exp2.f64(double [[ITOFP]])
+; NOLDEXP-NEXT:    ret double [[POW]]
+;
+  %itofp = sitofp i32 %x to double
+  %pow = tail call double @llvm.pow.f64(double 2.000000e+00, double %itofp)
+  ret double %pow
+}
+
+define half @pow_sitofp_f16_const_base_2(i32 %x) {
+; CHECK-LABEL: define half @pow_sitofp_f16_const_base_2(
+; CHECK-SAME: i32 [[X:%.*]]) {
+; CHECK-NEXT:    [[ITOFP:%.*]] = sitofp i32 [[X]] to half
+; CHECK-NEXT:    [[POW:%.*]] = tail call half @llvm.pow.f16(half 0xH4000, half [[ITOFP]])
+; CHECK-NEXT:    ret half [[POW]]
+;
+  %itofp = sitofp i32 %x to half
+  %pow = tail call half @llvm.pow.f16(half 2.000000e+00, half %itofp)
+  ret half %pow
+}
+
+define <2 x float> @pow_sitofp_v2f32_const_base_2(<2 x i32> %x) {
+; LDEXP-EXP2-LABEL: define <2 x float> @pow_sitofp_v2f32_const_base_2(
+; LDEXP-EXP2-SAME: <2 x i32> [[X:%.*]]) {
+; LDEXP-EXP2-NEXT:    [[EXP2:%.*]] = tail call <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> <float 1.000000e+00, float 1.000000e+00>, <2 x i32> [[X]])
+; LDEXP-EXP2-NEXT:    ret <2 x float> [[EXP2]]
+;
+; LDEXP-NOEXP2-LABEL: define <2 x float> @pow_sitofp_v2f32_const_base_2(
+; LDEXP-NOEXP2-SAME: <2 x i32> [[X:%.*]]) {
+; LDEXP-NOEXP2-NEXT:    [[ITOFP:%.*]] = sitofp <2 x i32> [[X]] to <2 x float>
+; LDEXP-NOEXP2-NEXT:    [[POW:%.*]] = tail call <2 x float> @llvm.pow.v2f32(<2 x float> <float 2.000000e+00, float 2.000000e+00>, <2 x float> [[ITOFP]])
+; LDEXP-NOEXP2-NEXT:    ret <2 x float> [[POW]]
+;
+; NOLDEXP-LABEL: define <2 x float> @pow_sitofp_v2f32_const_base_2(
+; NOLDEXP-SAME: <2 x i32> [[X:%.*]]) {
+; NOLDEXP-NEXT:    [[ITOFP:%.*]] = sitofp <2 x i32> [[X]] to <2 x float>
+; NOLDEXP-NEXT:    [[POW:%.*]] = tail call <2 x float> @llvm.exp2.v2f32(<2 x float> [[ITOFP]])
+; NOLDEXP-NEXT:    ret <2 x float> [[POW]]
+;
+  %itofp = sitofp <2 x i32> %x to <2 x float>
+  %pow = tail call <2 x float> @llvm.pow.v2f32(<2 x float> <float 2.000000e+00, float 2.000000e+00>, <2 x float> %itofp)
+  ret <2 x float> %pow
+}
+
+define <2 x float> @pow_sitofp_v2f32_const_base_8(<2 x i32> %x) {
+; LDEXP-EXP2-LABEL: define <2 x float> @pow_sitofp_v2f32_const_base_8(
+; LDEXP-EXP2-SAME: <2 x i32> [[X:%.*]]) {
+; LDEXP-EXP2-NEXT:    [[ITOFP:%.*]] = sitofp <2 x i32> [[X]] to <2 x float>
+; LDEXP-EXP2-NEXT:    [[MUL:%.*]] = fmul <2 x float> [[ITOFP]], <float 3.000000e+00, float 3.000000e+00>
+; LDEXP-EXP2-NEXT:    [[EXP2:%.*]] = tail call <2 x float> @llvm.exp2.v2f32(<2 x float> [[MUL]])
+; LDEXP-EXP2-NEXT:    ret <2 x float> [[EXP2]]
+;
+; LDEXP-NOEXP2-LABEL: define <2 x float> @pow_sitofp_v2f32_const_base_8(
+; LDEXP-NOEXP2-SAME: <2 x i32> [[X:%.*]]) {
+; LDEXP-NOEXP2-NEXT:    [[ITOFP:%.*]] = sitofp <2 x i32> [[X]] to <2 x float>
+; LDEXP-NOEXP2-NEXT:    [[POW:%.*]] = tail call <2 x float> @llvm.pow.v2f32(<2 x float> <float 8.000000e+00, float 8.000000e+00>, <2 x float> [[ITOFP]])
+; LDEXP-NOEXP2-NEXT:    ret <2 x float> [[POW]]
+;
+; NOLDEXP-LABEL: define <2 x float> @pow_sitofp_v2f32_const_base_8(
+; NOLDEXP-SAME: <2 x i32> [[X:%.*]]) {
+; NOLDEXP-NEXT:    [[ITOFP:%.*]] = sitofp <2 x i32> [[X]] to <2 x float>
+; NOLDEXP-NEXT:    [[MUL:%.*]] = fmul <2 x float> [[ITOFP]], <float 3.000000e+00, float 3.000000e+00>
+; NOLDEXP-NEXT:    [[EXP2:%.*]] = tail call <2 x float> @llvm.exp2.v2f32(<2 x float> [[MUL]])
+; NOLDEXP-NEXT:    ret <2 x float> [[EXP2]]
+;
+  %itofp = sitofp <2 x i32> %x to <2 x float>
+  %pow = tail call <2 x float> @llvm.pow.v2f32(<2 x float> <float 8.000000e+00, float 8.000000e+00>, <2 x float> %itofp)
+  ret <2 x float> %pow
+}
+
+define <2 x float> @pow_sitofp_v2f32_const_base_mixed_2(<2 x i32> %x) {
+; CHECK-LABEL: define <2 x float> @pow_sitofp_v2f32_const_base_mixed_2(
+; CHECK-SAME: <2 x i32> [[X:%.*]]) {
+; CHECK-NEXT:    [[ITOFP:%.*]] = sitofp <2 x i32> [[X]] to <2 x float>
+; CHECK-NEXT:    [[POW:%.*]] = tail call <2 x float> @llvm.pow.v2f32(<2 x float> <float 2.000000e+00, float 4.000000e+00>, <2 x float> [[ITOFP]])
+; CHECK-NEXT:    ret <2 x float> [[POW]]
+;
+  %itofp = sitofp <2 x i32> %x to <2 x float>
+  %pow = tail call <2 x float> @llvm.pow.v2f32(<2 x float> <float 2.000000e+00, float 4.000000e+00>, <2 x float> %itofp)
+  ret <2 x float> %pow
+}
+
+define <2 x float> @pow_sitofp_v2f32_const_base_2__flags(<2 x i32> %x) {
+; LDEXP-EXP2-LABEL: define <2 x float> @pow_sitofp_v2f32_const_base_2__flags(
+; LDEXP-EXP2-SAME: <2 x i32> [[X:%.*]]) {
+; LDEXP-EXP2-NEXT:    [[EXP2:%.*]] = tail call nsz afn <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> <float 1.000000e+00, float 1.000000e+00>, <2 x i32> [[X]])
+; LDEXP-EXP2-NEXT:    ret <2 x float> [[EXP2]]
+;
+; LDEXP-NOEXP2-LABEL: define <2 x float> @pow_sitofp_v2f32_const_base_2__flags(
+; LDEXP-NOEXP2-SAME: <2 x i32> [[X:%.*]]) {
+; LDEXP-NOEXP2-NEXT:    [[POW:%.*]] = tail call nsz afn <2 x float> @llvm.powi.v2f32.v2i32(<2 x float> <float 2.000000e+00, float 2.000000e+00>, <2 x i32> [[X]])
+; LDEXP-NOEXP2-NEXT:    ret <2 x float> [[POW]]
+;
+; NOLDEXP-LABEL: define <2 x float> @pow_sitofp_v2f32_const_base_2__flags(
+; NOLDEXP-SAME: <2 x i32> [[X:%.*]]) {
+; NOLDEXP-NEXT:    [[ITOFP:%.*]] = sitofp <2 x i32> [[X]] to <2 x float>
+; NOLDEXP-NEXT:    [[POW:%.*]] = tail call nsz afn <2 x float> @llvm.exp2.v2f32(<2 x float> [[ITOFP]])
+; NOLDEXP-NEXT:    ret <2 x float> [[POW]]
+;
+  %itofp = sitofp <2 x i32> %x to <2 x float>
+  %pow = tail call nsz afn <2 x float> @llvm.pow.v2f32(<2 x float> <float 2.000000e+00, float 2.000000e+00>, <2 x float> %itofp)
+  ret <2 x float> %pow
+}
+
+define <vscale x 4 x float> @pow_sitofp_nxv4f32_const_base_2(<vscale x 4 x i32> %x) {
+; LDEXP-EXP2-LABEL: define <vscale x 4 x float> @pow_sitofp_nxv4f32_const_base_2(
+; LDEXP-EXP2-SAME: <vscale x 4 x i32> [[X:%.*]]) {
+; LDEXP-EXP2-NEXT:    [[EXP2:%.*]] = tail call <vscale x 4 x float> @llvm.ldexp.nxv4f32.nxv4i32(<vscale x 4 x float> shufflevector (<vscale x 4 x float> insertelement (<vscale x 4 x float> poison, float 1.000000e+00, i64 0), <vscale x 4 x float> poison, <vscale x 4 x i32> zeroinitializer), <vscale x 4 x i32> [[X]])
+; LDEXP-EXP2-NEXT:    ret <vscale x 4 x float> [[EXP2]]
+;
+; LDEXP-NOEXP2-LABEL: define <vscale x 4 x float> @pow_sitofp_nxv4f32_const_base_2(
+; LDEXP-NOEXP2-SAME: <vscale x 4 x i32> [[X:%.*]]) {
+; LDEXP-NOEXP2-NEXT:    [[ITOFP:%.*]] = sitofp <vscale x 4 x i32> [[X]] to <vscale x 4 x float>
+; LDEXP-NOEXP2-NEXT:    [[POW:%.*]] = tail call <vscale x 4 x float> @llvm.pow.nxv4f32(<vscale x 4 x float> shufflevector (<vscale x 4 x float> insertelement (<vscale x 4 x float> poison, float 2.000000e+00, i64 0), <vscale x 4 x float> poison, <vscale x 4 x i32> zeroinitializer), <vscale x 4 x float> [[ITOFP]])
+; LDEXP-NOEXP2-NEXT:    ret <vscale x 4 x float> [[POW]]
+;
+; NOLDEXP-LABEL: define <vscale x 4 x float> @pow_sitofp_nxv4f32_const_base_2(
+; NOLDEXP-SAME: <vscale x 4 x i32> [[X:%.*]]) {
+; NOLDEXP-NEXT:    [[ITOFP:%.*]] = sitofp <vscale x 4 x i32> [[X]] to <vscale x 4 x float>
+; NOLDEXP-NEXT:    [[POW:%.*]] = tail call <vscale x 4 x float> @llvm.exp2.nxv4f32(<vscale x 4 x float> [[ITOFP]])
+; NOLDEXP-NEXT:    ret <vscale x 4 x float> [[POW]]
+;
+  %itofp = sitofp <vscale x 4 x i32> %x to <vscale x 4 x float>
+  %pow = tail call <vscale x 4 x float> @llvm.pow.nxv4f32(<vscale x 4 x float> splat (float 2.0), <vscale x 4 x float> %itofp)
+  ret <vscale x 4 x float> %pow
+}
+
+define <2 x half> @pow_sitofp_v2f16_const_base_2(<2 x i32> %x) {
+; LDEXP-EXP2-LABEL: define <2 x half> @pow_sitofp_v2f16_const_base_2(
+; LDEXP-EXP2-SAME: <2 x i32> [[X:%.*]]) {
+; LDEXP-EXP2-NEXT:    [[EXP2:%.*]] = tail call <2 x half> @llvm.ldexp.v2f16.v2i32(<2 x half> <half 0xH3C00, half 0xH3C00>, <2 x i32> [[X]])
+; LDEXP-EXP2-NEXT:    ret <2 x half> [[EXP2]]
+;
+; LDEXP-NOEXP2-LABEL: define <2 x half> @pow_sitofp_v2f16_const_base_2(
+; LDEXP-NOEXP2-SAME: <2 x i32> [[X:%.*]]) {
+; LDEXP-NOEXP2-NEXT:    [[ITOFP:%.*]] = sitofp <2 x i32> [[X]] to <2 x half>
+; LDEXP-NOEXP2-NEXT:    [[POW:%.*]] = tail call <2 x half> @llvm.pow.v2f16(<2 x half> <half 0xH4000, half 0xH4000>, <2 x half> [[ITOFP]])
+; LDEXP-NOEXP2-NEXT:    ret <2 x half> [[POW]]
+;
+; NOLDEXP-LABEL: define <2 x half> @pow_sitofp_v2f16_const_base_2(
+; NOLDEXP-SAME: <2 x i32> [[X:%.*]]) {
+; NOLDEXP-NEXT:    [[ITOFP:%.*]] = sitofp <2 x i32> [[X]] to <2 x half>
+; NOLDEXP-NEXT:    [[EXP2:%.*]] = tail call <2 x half> @llvm.exp2.v2f16(<2 x half> [[ITOFP]])
+; NOLDEXP-NEXT:    ret <2 x half> [[EXP2]]
+;
+  %itofp = sitofp <2 x i32> %x to <2 x half>
+  %pow = tail call <2 x half> @llvm.pow.v2f16(<2 x half> <half 2.000000e+00, half 2.000000e+00>, <2 x half> %itofp)
+  ret <2 x half> %pow
+}
+
+define <2 x double> @pow_sitofp_v2f64_const_base_2(<2 x i32> %x) {
+; LDEXP-EXP2-LABEL: define <2 x double> @pow_sitofp_v2f64_const_base_2(
+; LDEXP-EXP2-SAME: <2 x i32> [[X:%.*]]) {
+; LDEXP-EXP2-NEXT:    [[EXP2:%.*]] = tail call <2 x double> @llvm.ldexp.v2f64.v2i32(<2 x double> <double 1.000000e+00, double 1.000000e+00>, <2 x i32> [[X]])
+; LDEXP-EXP2-NEXT:    ret <2 x double> [[EXP2]]
+;
+; LDEXP-NOEXP2-LABEL: define <2 x double> @pow_sitofp_v2f64_const_base_2(
+; LDEXP-NOEXP2-SAME: <2 x i32> [[X:%.*]]) {
+; LDEXP-NOEXP2-NEXT:    [[ITOFP:%.*]] = sitofp <2 x i32> [[X]] to <2 x double>
+; LDEXP-NOEXP2-NEXT:    [[POW:%.*]] = tail call <2 x double> @llvm.pow.v2f64(<2 x double> <double 2.000000e+00, double 2.000000e+00>, <2 x double> [[ITOFP]])
+; LDEXP-NOEXP2-NEXT:    ret <2 x double> [[POW]]
+;
+; NOLDEXP-LABEL: define <2 x double> @pow_sitofp_v2f64_const_base_2(
+; NOLDEXP-SAME: <2 x i32> [[X:%.*]]) {
+; NOLDEXP-NEXT:    [[ITOFP:%.*]] = sitofp <2 x i32> [[X]] to <2 x double>
+; NOLDEXP-NEXT:    [[EXP2:%.*]] = tail call <2 x double> @llvm.exp2.v2f64(<2 x double> [[ITOFP]])
+; NOLDEXP-NEXT:    ret <2 x double> [[EXP2]]
+;
+  %itofp = sitofp <2 x i32> %x to <2 x double>
+  %pow = tail call <2 x double> @llvm.pow.v2f64(<2 x double> <double 2.000000e+00, double 2.000000e+00>, <2 x double> %itofp)
+  ret <2 x double> %pow
+}
+
+define <2 x half> @pow_sitofp_v2f16_const_base_8(<2 x i32> %x) {
+; EXP2-LABEL: define <2 x half> @pow_sitofp_v2f16_const_base_8(
+; EXP2-SAME: <2 x i32> [[X:%.*]]) {
+; EXP2-NEXT:    [[ITOFP:%.*]] = sitofp <2 x i32> [[X]] to <2 x half>
+; EXP2-NEXT:    [[MUL:%.*]] = fmul <2 x half> [[ITOFP]], <half 0xH4200, half 0xH4200>
+; EXP2-NEXT:    [[EXP2:%.*]] = tail call <2 x half> @llvm.exp2.v2f16(<2 x half> [[MUL]])
+; EXP2-NEXT:    ret <2 x half> [[EXP2]]
+;
+; LDEXP-EXP2-LABEL: define <2 x half> @pow_sitofp_v2f16_const_base_8(
+; LDEXP-EXP2-SAME: <2 x i32> [[X:%.*]]) {
+; LDEXP-EXP2-NEXT:    [[ITOFP:%.*]] = sitofp <2 x i32> [[X]] to <2 x half>
+; LDEXP-EXP2-NEXT:    [[MUL:%.*]] = fmul <2 x half> [[ITOFP]], <half 0xH4200, half 0xH4200>
+; LDEXP-EXP2-NEXT:    [[EXP2:%.*]] = tail call <2 x half> @llvm.exp2.v2f16(<2 x half> [[MUL]])
+; LDEXP-EXP2-NEXT:    ret <2 x half> [[EXP2]]
+;
+; LDEXP-NOEXP2-LABEL: define <2 x half> @pow_sitofp_v2f16_const_base_8(
+; LDEXP-NOEXP2-SAME: <2 x i32> [[X:%.*]]) {
+; LDEXP-NOEXP2-NEXT:    [[ITOFP:%.*]] = sitofp <2 x i32> [[X]] to <2 x half>
+; LDEXP-NOEXP2-NEXT:    [[POW:%.*]] = tail call <2 x half> @llvm.pow.v2f16(<2 x half> <half 0xH4800, half 0xH4800>, <2 x half> [[ITOFP]])
+; LDEXP-NOEXP2-NEXT:    ret <2 x half> [[POW]]
+;
+; NOLDEXP-LABEL: define <2 x half> @pow_sitofp_v2f16_const_base_8(
+; NOLDEXP-SAME: <2 x i32> [[X:%.*]]) {
+; NOLDEXP-NEXT:    [[ITOFP:%.*]] = sitofp <2 x i32> [[X]] to <2 x half>
+; NOLDEXP-NEXT:    [[MUL:%.*]] = fmul <2 x half> [[ITOFP]], <half 0xH4200, half 0xH4200>
+; NOLDEXP-NEXT:    [[EXP2:%.*]] = tail call <2 x half> @llvm.exp2.v2f16(<2 x half> [[MUL]])
+; NOLDEXP-NEXT:    ret <2 x half> [[EXP2]]
+;
+  %itofp = sitofp <2 x i32> %x to <2 x half>
+  %pow = tail call <2 x half> @llvm.pow.v2f16(<2 x half> <half 8.000000e+00, half 8.000000e+00>, <2 x half> %itofp)
+  ret <2 x half> %pow
+}
+
+define <2 x double> @pow_sitofp_v2f64_const_base_8(<2 x i32> %x) {
+; EXP2-LABEL: define <2 x double> @pow_sitofp_v2f64_const_base_8(
+; EXP2-SAME: <2 x i32> [[X:%.*]]) {
+; EXP2-NEXT:    [[ITOFP:%.*]] = sitofp <2 x i32> [[X]] to <2 x double>
+; EXP2-NEXT:    [[MUL:%.*]] = fmul <2 x double> [[ITOFP]], <double 3.000000e+00, double 3.000000e+00>
+; EXP2-NEXT:    [[EXP2:%.*]] = tail call <2 x double> @llvm.exp2.v2f64(<2 x double> [[MUL]])
+; EXP2-NEXT:    ret <2 x double> [[EXP2]]
+;
+; LDEXP-EXP2-LABEL: define <2 x double> @pow_sitofp_v2f64_const_base_8(
+; LDEXP-EXP2-SAME: <2 x i32> [[X:%.*]]) {
+; LDEXP-EXP2-NEXT:    [[ITOFP:%.*]] = sitofp <2 x i32> [[X]] to <2 x double>
+; LDEXP-EXP2-NEXT:    [[MUL:%.*]] = fmul <2 x double> [[ITOFP]], <double 3.000000e+00, double 3.000000e+00>
+; LDEXP-EXP2-NEXT:    [[EXP2:%.*]] = tail call <2 x double> @llvm.exp2.v2f64(<2 x double>...
[truncated]

Copy link
Member

@dtcxzyw dtcxzyw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

@arsenm arsenm merged commit f5c8242 into llvm:main May 17, 2024
7 of 8 checks passed
@arsenm arsenm deleted the simplifylibcalls-emit-ldexp-intrinsic-pow-combine branch May 17, 2024 12:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
floating-point Floating-point math llvm:instcombine Covers the InstCombine, InstSimplify and AggressiveInstCombine passes llvm:transforms
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants