diff options
author | Matt Arsenault <Matthew.Arsenault@amd.com> | 2024-06-10 18:21:20 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-06-10 18:21:20 +0200 |
commit | 8788b666aaaf4658bbaab7459968ba2bca13f529 (patch) | |
tree | 9fbd89ca9ebb933f844f2077733e42d66a85f404 | |
parent | d63ade63b661e09cb1379d48cb3e49851fdf2509 (diff) | |
download | llvm-8788b666aaaf4658bbaab7459968ba2bca13f529.zip llvm-8788b666aaaf4658bbaab7459968ba2bca13f529.tar.gz llvm-8788b666aaaf4658bbaab7459968ba2bca13f529.tar.bz2 |
SimplifyLibCalls: Don't require ldexp to emit intrinsic in exp2 combine (#92707)
When folding exp2(itofp(x)) to ldexp(1, x), don't require an ldexp
libcall to emit the intrinsic.
The intrinsic needs to be handled regardless of whether the system has a
libcall, and we have an inline implementation of ldexp already. This
fixes the instance in the exp2->ldexp fold. Another instance exists for
the pow(2) -> ldexp case
The LTO test change isn't ideal, since it's just moving the problem to
another instance where we're relying on implied libm behavior for an
intrinsic transform. Use exp10 since that's a harder case to solve in
the libcall house of cards we have.
-rw-r--r-- | llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp | 13 | ||||
-rw-r--r-- | llvm/test/LTO/X86/triple-init2.ll | 11 | ||||
-rw-r--r-- | llvm/test/Transforms/InstCombine/exp2-1.ll | 29 | ||||
-rw-r--r-- | llvm/test/Transforms/InstCombine/exp2-to-ldexp.ll | 120 | ||||
-rw-r--r-- | llvm/test/Transforms/InstCombine/pow-to-ldexp.ll | 168 |
5 files changed, 118 insertions, 223 deletions
diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp index eb1224a..a91c3ff 100644 --- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp @@ -2376,7 +2376,13 @@ Value *LibCallSimplifier::optimizeExp2(CallInst *CI, IRBuilderBase &B) { hasFloatVersion(M, Name)) Ret = optimizeUnaryDoubleFP(CI, B, TLI, true); - const bool UseIntrinsic = CI->doesNotAccessMemory(); + // If we have an llvm.exp2 intrinsic, emit the llvm.ldexp intrinsic. If we + // have the libcall, emit the libcall. + // + // TODO: In principle we should be able to just always use the intrinsic for + // any doesNotAccessMemory callsite. + + const bool UseIntrinsic = Callee->isIntrinsic(); // Bail out for vectors because the code below only expects scalars. Type *Ty = CI->getType(); if (!UseIntrinsic && Ty->isVectorTy()) @@ -2386,12 +2392,11 @@ Value *LibCallSimplifier::optimizeExp2(CallInst *CI, IRBuilderBase &B) { // exp2(uitofp(x)) -> ldexp(1.0, zext(x)) if sizeof(x) < IntSize Value *Op = CI->getArgOperand(0); if ((isa<SIToFPInst>(Op) || isa<UIToFPInst>(Op)) && - hasFloatFn(M, TLI, Ty, LibFunc_ldexp, LibFunc_ldexpf, LibFunc_ldexpl)) { + (UseIntrinsic || + hasFloatFn(M, TLI, Ty, LibFunc_ldexp, LibFunc_ldexpf, LibFunc_ldexpl))) { if (Value *Exp = getIntToFPVal(Op, B, TLI->getIntSize())) { Constant *One = ConstantFP::get(Ty, 1.0); - // TODO: Emitting the intrinsic should not depend on whether the libcall - // is available. if (UseIntrinsic) { return copyFlags(*CI, B.CreateIntrinsic(Intrinsic::ldexp, {Ty, Exp->getType()}, diff --git a/llvm/test/LTO/X86/triple-init2.ll b/llvm/test/LTO/X86/triple-init2.ll index 2638180..bc5ecf9 100644 --- a/llvm/test/LTO/X86/triple-init2.ll +++ b/llvm/test/LTO/X86/triple-init2.ll @@ -11,21 +11,20 @@ ; RUN: llvm-lto2 run -r %t1,main,plx -o %t2 %t1 ; RUN: llvm-nm %t2.1 | FileCheck %s -; We check that LTO will be aware of target triple and prevent exp2 to ldexpf +; We check that LTO will be aware of target triple and prevent pow to exp10 ; transformation on Windows. -; CHECK: U exp2f +; CHECK: U powf target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-pc-windows-msvc19.11.0" +declare float @llvm.pow.f32(float, float) + define dso_local i32 @main(i32 %argc, ptr nocapture readnone %argv) local_unnamed_addr { entry: %conv = sitofp i32 %argc to float - %exp2 = tail call float @llvm.exp2.f32(float %conv) + %exp2 = tail call float @llvm.pow.f32(float 10.0, float %conv) %conv1 = fptosi float %exp2 to i32 ret i32 %conv1 } -; Function Attrs: nounwind readnone speculatable -declare float @llvm.exp2.f32(float) - diff --git a/llvm/test/Transforms/InstCombine/exp2-1.ll b/llvm/test/Transforms/InstCombine/exp2-1.ll index 2dff0b0..d8bd0a4 100644 --- a/llvm/test/Transforms/InstCombine/exp2-1.ll +++ b/llvm/test/Transforms/InstCombine/exp2-1.ll @@ -242,8 +242,8 @@ define double @test_simplify9(i8 zeroext %x) { ; NOLDEXPF-NEXT: ret double [[RET]] ; ; NOLDEXP-LABEL: @test_simplify9( -; NOLDEXP-NEXT: [[CONV:%.*]] = uitofp i8 [[X:%.*]] to double -; NOLDEXP-NEXT: [[RET:%.*]] = call double @llvm.exp2.f64(double [[CONV]]) +; NOLDEXP-NEXT: [[TMP1:%.*]] = zext i8 [[X:%.*]] to i32 +; NOLDEXP-NEXT: [[RET:%.*]] = call double @llvm.ldexp.f64.i32(double 1.000000e+00, i32 [[TMP1]]) ; NOLDEXP-NEXT: ret double [[RET]] ; %conv = uitofp i8 %x to double @@ -263,13 +263,13 @@ define float @test_simplify10(i8 zeroext %x) { ; LDEXP16-NEXT: ret float [[RET]] ; ; NOLDEXPF-LABEL: @test_simplify10( -; NOLDEXPF-NEXT: [[CONV:%.*]] = uitofp i8 [[X:%.*]] to float -; NOLDEXPF-NEXT: [[RET:%.*]] = call float @llvm.exp2.f32(float [[CONV]]) +; NOLDEXPF-NEXT: [[TMP1:%.*]] = zext i8 [[X:%.*]] to i32 +; NOLDEXPF-NEXT: [[RET:%.*]] = call float @llvm.ldexp.f32.i32(float 1.000000e+00, i32 [[TMP1]]) ; NOLDEXPF-NEXT: ret float [[RET]] ; ; NOLDEXP-LABEL: @test_simplify10( -; NOLDEXP-NEXT: [[CONV:%.*]] = uitofp i8 [[X:%.*]] to float -; NOLDEXP-NEXT: [[RET:%.*]] = call float @llvm.exp2.f32(float [[CONV]]) +; NOLDEXP-NEXT: [[TMP1:%.*]] = zext i8 [[X:%.*]] to i32 +; NOLDEXP-NEXT: [[RET:%.*]] = call float @llvm.ldexp.f32.i32(float 1.000000e+00, i32 [[TMP1]]) ; NOLDEXP-NEXT: ret float [[RET]] ; %conv = uitofp i8 %x to float @@ -289,13 +289,13 @@ define float @sitofp_scalar_intrinsic_with_FMF(i8 %x) { ; LDEXP16-NEXT: ret float [[R]] ; ; NOLDEXPF-LABEL: @sitofp_scalar_intrinsic_with_FMF( -; NOLDEXPF-NEXT: [[S:%.*]] = sitofp i8 [[X:%.*]] to float -; NOLDEXPF-NEXT: [[R:%.*]] = tail call nnan float @llvm.exp2.f32(float [[S]]) +; NOLDEXPF-NEXT: [[TMP1:%.*]] = sext i8 [[X:%.*]] to i32 +; NOLDEXPF-NEXT: [[R:%.*]] = tail call nnan float @llvm.ldexp.f32.i32(float 1.000000e+00, i32 [[TMP1]]) ; NOLDEXPF-NEXT: ret float [[R]] ; ; NOLDEXP-LABEL: @sitofp_scalar_intrinsic_with_FMF( -; NOLDEXP-NEXT: [[S:%.*]] = sitofp i8 [[X:%.*]] to float -; NOLDEXP-NEXT: [[R:%.*]] = tail call nnan float @llvm.exp2.f32(float [[S]]) +; NOLDEXP-NEXT: [[TMP1:%.*]] = sext i8 [[X:%.*]] to i32 +; NOLDEXP-NEXT: [[R:%.*]] = tail call nnan float @llvm.ldexp.f32.i32(float 1.000000e+00, i32 [[TMP1]]) ; NOLDEXP-NEXT: ret float [[R]] ; %s = sitofp i8 %x to float @@ -317,9 +317,14 @@ define <2 x float> @sitofp_vector_intrinsic_with_FMF(<2 x i8> %x) { ; LDEXP16-NEXT: [[R:%.*]] = call nnan <2 x float> @llvm.ldexp.v2f32.v2i16(<2 x float> <float 1.000000e+00, float 1.000000e+00>, <2 x i16> [[TMP1]]) ; LDEXP16-NEXT: ret <2 x float> [[R]] ; +; NOLDEXPF-LABEL: @sitofp_vector_intrinsic_with_FMF( +; NOLDEXPF-NEXT: [[TMP1:%.*]] = sext <2 x i8> [[X:%.*]] to <2 x i32> +; NOLDEXPF-NEXT: [[R:%.*]] = call nnan <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> <float 1.000000e+00, float 1.000000e+00>, <2 x i32> [[TMP1]]) +; NOLDEXPF-NEXT: ret <2 x float> [[R]] +; ; NOLDEXP-LABEL: @sitofp_vector_intrinsic_with_FMF( -; NOLDEXP-NEXT: [[S:%.*]] = sitofp <2 x i8> [[X:%.*]] to <2 x float> -; NOLDEXP-NEXT: [[R:%.*]] = call nnan <2 x float> @llvm.exp2.v2f32(<2 x float> [[S]]) +; NOLDEXP-NEXT: [[TMP1:%.*]] = sext <2 x i8> [[X:%.*]] to <2 x i32> +; NOLDEXP-NEXT: [[R:%.*]] = call nnan <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> <float 1.000000e+00, float 1.000000e+00>, <2 x i32> [[TMP1]]) ; NOLDEXP-NEXT: ret <2 x float> [[R]] ; %s = sitofp <2 x i8> %x to <2 x float> diff --git a/llvm/test/Transforms/InstCombine/exp2-to-ldexp.ll b/llvm/test/Transforms/InstCombine/exp2-to-ldexp.ll index 6e5be5a..9690201 100644 --- a/llvm/test/Transforms/InstCombine/exp2-to-ldexp.ll +++ b/llvm/test/Transforms/InstCombine/exp2-to-ldexp.ll @@ -1,19 +1,13 @@ ; 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 %s -; RUN: opt -S -passes=instcombine -disable-builtin=ldexpf -disable-builtin=ldexp -disable-builtin=ldexpl %s | FileCheck -check-prefixes=CHECK,NOLDEXP %s +; RUN: opt -S -passes=instcombine %s | FileCheck %s +; RUN: opt -S -passes=instcombine -disable-builtin=ldexpf -disable-builtin=ldexp -disable-builtin=ldexpl %s | FileCheck %s define float @exp2_f32_sitofp_i8(i8 %x) { -; LDEXP-LABEL: define float @exp2_f32_sitofp_i8( -; LDEXP-SAME: i8 [[X:%.*]]) { -; LDEXP-NEXT: [[TMP1:%.*]] = sext i8 [[X]] to i32 -; LDEXP-NEXT: [[LDEXPF:%.*]] = call float @llvm.ldexp.f32.i32(float 1.000000e+00, i32 [[TMP1]]) -; LDEXP-NEXT: ret float [[LDEXPF]] -; -; NOLDEXP-LABEL: define float @exp2_f32_sitofp_i8( -; NOLDEXP-SAME: i8 [[X:%.*]]) { -; NOLDEXP-NEXT: [[ITOFP:%.*]] = sitofp i8 [[X]] to float -; NOLDEXP-NEXT: [[EXP2:%.*]] = call float @llvm.exp2.f32(float [[ITOFP]]) -; NOLDEXP-NEXT: ret float [[EXP2]] +; CHECK-LABEL: define float @exp2_f32_sitofp_i8( +; CHECK-SAME: i8 [[X:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = sext i8 [[X]] to i32 +; CHECK-NEXT: [[EXP2:%.*]] = call float @llvm.ldexp.f32.i32(float 1.000000e+00, i32 [[TMP1]]) +; CHECK-NEXT: ret float [[EXP2]] ; %itofp = sitofp i8 %x to float %exp2 = call float @llvm.exp2.f32(float %itofp) @@ -21,17 +15,11 @@ define float @exp2_f32_sitofp_i8(i8 %x) { } define float @exp2_f32_sitofp_i8_flags(i8 %x) { -; LDEXP-LABEL: define float @exp2_f32_sitofp_i8_flags( -; LDEXP-SAME: i8 [[X:%.*]]) { -; LDEXP-NEXT: [[TMP1:%.*]] = sext i8 [[X]] to i32 -; LDEXP-NEXT: [[LDEXPF:%.*]] = call nnan ninf float @llvm.ldexp.f32.i32(float 1.000000e+00, i32 [[TMP1]]) -; LDEXP-NEXT: ret float [[LDEXPF]] -; -; NOLDEXP-LABEL: define float @exp2_f32_sitofp_i8_flags( -; NOLDEXP-SAME: i8 [[X:%.*]]) { -; NOLDEXP-NEXT: [[ITOFP:%.*]] = sitofp i8 [[X]] to float -; NOLDEXP-NEXT: [[EXP2:%.*]] = call nnan ninf float @llvm.exp2.f32(float [[ITOFP]]) -; NOLDEXP-NEXT: ret float [[EXP2]] +; CHECK-LABEL: define float @exp2_f32_sitofp_i8_flags( +; CHECK-SAME: i8 [[X:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = sext i8 [[X]] to i32 +; CHECK-NEXT: [[EXP2:%.*]] = call nnan ninf float @llvm.ldexp.f32.i32(float 1.000000e+00, i32 [[TMP1]]) +; CHECK-NEXT: ret float [[EXP2]] ; %itofp = sitofp i8 %x to float %exp2 = call nnan ninf float @llvm.exp2.f32(float %itofp) @@ -39,17 +27,11 @@ define float @exp2_f32_sitofp_i8_flags(i8 %x) { } define <2 x float> @exp2_v2f32_sitofp_v2i8(<2 x i8> %x) { -; LDEXP-LABEL: define <2 x float> @exp2_v2f32_sitofp_v2i8( -; LDEXP-SAME: <2 x i8> [[X:%.*]]) { -; LDEXP-NEXT: [[TMP1:%.*]] = sext <2 x i8> [[X]] to <2 x i32> -; LDEXP-NEXT: [[EXP2:%.*]] = call <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> <float 1.000000e+00, float 1.000000e+00>, <2 x i32> [[TMP1]]) -; LDEXP-NEXT: ret <2 x float> [[EXP2]] -; -; NOLDEXP-LABEL: define <2 x float> @exp2_v2f32_sitofp_v2i8( -; NOLDEXP-SAME: <2 x i8> [[X:%.*]]) { -; NOLDEXP-NEXT: [[ITOFP:%.*]] = sitofp <2 x i8> [[X]] to <2 x float> -; NOLDEXP-NEXT: [[EXP2:%.*]] = call <2 x float> @llvm.exp2.v2f32(<2 x float> [[ITOFP]]) -; NOLDEXP-NEXT: ret <2 x float> [[EXP2]] +; CHECK-LABEL: define <2 x float> @exp2_v2f32_sitofp_v2i8( +; CHECK-SAME: <2 x i8> [[X:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = sext <2 x i8> [[X]] to <2 x i32> +; CHECK-NEXT: [[EXP2:%.*]] = call <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> <float 1.000000e+00, float 1.000000e+00>, <2 x i32> [[TMP1]]) +; CHECK-NEXT: ret <2 x float> [[EXP2]] ; %itofp = sitofp <2 x i8> %x to <2 x float> %exp2 = call <2 x float> @llvm.exp2.v2f32(<2 x float> %itofp) @@ -57,17 +39,11 @@ define <2 x float> @exp2_v2f32_sitofp_v2i8(<2 x i8> %x) { } define float @exp2_f32_uitofp_i8(i8 %x) { -; LDEXP-LABEL: define float @exp2_f32_uitofp_i8( -; LDEXP-SAME: i8 [[X:%.*]]) { -; LDEXP-NEXT: [[TMP1:%.*]] = zext i8 [[X]] to i32 -; LDEXP-NEXT: [[LDEXPF:%.*]] = call float @llvm.ldexp.f32.i32(float 1.000000e+00, i32 [[TMP1]]) -; LDEXP-NEXT: ret float [[LDEXPF]] -; -; NOLDEXP-LABEL: define float @exp2_f32_uitofp_i8( -; NOLDEXP-SAME: i8 [[X:%.*]]) { -; NOLDEXP-NEXT: [[ITOFP:%.*]] = uitofp i8 [[X]] to float -; NOLDEXP-NEXT: [[EXP2:%.*]] = call float @llvm.exp2.f32(float [[ITOFP]]) -; NOLDEXP-NEXT: ret float [[EXP2]] +; CHECK-LABEL: define float @exp2_f32_uitofp_i8( +; CHECK-SAME: i8 [[X:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[X]] to i32 +; CHECK-NEXT: [[EXP2:%.*]] = call float @llvm.ldexp.f32.i32(float 1.000000e+00, i32 [[TMP1]]) +; CHECK-NEXT: ret float [[EXP2]] ; %itofp = uitofp i8 %x to float %exp2 = call float @llvm.exp2.f32(float %itofp) @@ -77,8 +53,8 @@ define float @exp2_f32_uitofp_i8(i8 %x) { define half @exp2_f16_sitofp_i8(i8 %x) { ; CHECK-LABEL: define half @exp2_f16_sitofp_i8( ; CHECK-SAME: i8 [[X:%.*]]) { -; CHECK-NEXT: [[ITOFP:%.*]] = sitofp i8 [[X]] to half -; CHECK-NEXT: [[EXP2:%.*]] = call half @llvm.exp2.f16(half [[ITOFP]]) +; CHECK-NEXT: [[TMP1:%.*]] = sext i8 [[X]] to i32 +; CHECK-NEXT: [[EXP2:%.*]] = call half @llvm.ldexp.f16.i32(half 0xH3C00, i32 [[TMP1]]) ; CHECK-NEXT: ret half [[EXP2]] ; %itofp = sitofp i8 %x to half @@ -87,17 +63,11 @@ define half @exp2_f16_sitofp_i8(i8 %x) { } define double @exp2_f64_sitofp_i8(i8 %x) { -; LDEXP-LABEL: define double @exp2_f64_sitofp_i8( -; LDEXP-SAME: i8 [[X:%.*]]) { -; LDEXP-NEXT: [[TMP1:%.*]] = sext i8 [[X]] to i32 -; LDEXP-NEXT: [[LDEXP:%.*]] = call double @llvm.ldexp.f64.i32(double 1.000000e+00, i32 [[TMP1]]) -; LDEXP-NEXT: ret double [[LDEXP]] -; -; NOLDEXP-LABEL: define double @exp2_f64_sitofp_i8( -; NOLDEXP-SAME: i8 [[X:%.*]]) { -; NOLDEXP-NEXT: [[ITOFP:%.*]] = sitofp i8 [[X]] to double -; NOLDEXP-NEXT: [[EXP2:%.*]] = call double @llvm.exp2.f64(double [[ITOFP]]) -; NOLDEXP-NEXT: ret double [[EXP2]] +; CHECK-LABEL: define double @exp2_f64_sitofp_i8( +; CHECK-SAME: i8 [[X:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = sext i8 [[X]] to i32 +; CHECK-NEXT: [[EXP2:%.*]] = call double @llvm.ldexp.f64.i32(double 1.000000e+00, i32 [[TMP1]]) +; CHECK-NEXT: ret double [[EXP2]] ; %itofp = sitofp i8 %x to double %exp2 = call double @llvm.exp2.f64(double %itofp) @@ -105,17 +75,11 @@ define double @exp2_f64_sitofp_i8(i8 %x) { } define fp128 @exp2_fp128_sitofp_i8(i8 %x) { -; LDEXP-LABEL: define fp128 @exp2_fp128_sitofp_i8( -; LDEXP-SAME: i8 [[X:%.*]]) { -; LDEXP-NEXT: [[TMP1:%.*]] = sext i8 [[X]] to i32 -; LDEXP-NEXT: [[LDEXPL:%.*]] = call fp128 @llvm.ldexp.f128.i32(fp128 0xL00000000000000003FFF000000000000, i32 [[TMP1]]) -; LDEXP-NEXT: ret fp128 [[LDEXPL]] -; -; NOLDEXP-LABEL: define fp128 @exp2_fp128_sitofp_i8( -; NOLDEXP-SAME: i8 [[X:%.*]]) { -; NOLDEXP-NEXT: [[ITOFP:%.*]] = sitofp i8 [[X]] to fp128 -; NOLDEXP-NEXT: [[EXP2:%.*]] = call fp128 @llvm.exp2.f128(fp128 [[ITOFP]]) -; NOLDEXP-NEXT: ret fp128 [[EXP2]] +; CHECK-LABEL: define fp128 @exp2_fp128_sitofp_i8( +; CHECK-SAME: i8 [[X:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = sext i8 [[X]] to i32 +; CHECK-NEXT: [[EXP2:%.*]] = call fp128 @llvm.ldexp.f128.i32(fp128 0xL00000000000000003FFF000000000000, i32 [[TMP1]]) +; CHECK-NEXT: ret fp128 [[EXP2]] ; %itofp = sitofp i8 %x to fp128 %exp2 = call fp128 @llvm.exp2.fp128(fp128 %itofp) @@ -123,17 +87,11 @@ define fp128 @exp2_fp128_sitofp_i8(i8 %x) { } define <vscale x 4 x float> @exp2_nxv4f32_sitofp_i8(<vscale x 4 x i8> %x) { -; LDEXP-LABEL: define <vscale x 4 x float> @exp2_nxv4f32_sitofp_i8( -; LDEXP-SAME: <vscale x 4 x i8> [[X:%.*]]) { -; LDEXP-NEXT: [[TMP1:%.*]] = sext <vscale x 4 x i8> [[X]] to <vscale x 4 x i32> -; LDEXP-NEXT: [[EXP2:%.*]] = 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> [[TMP1]]) -; LDEXP-NEXT: ret <vscale x 4 x float> [[EXP2]] -; -; NOLDEXP-LABEL: define <vscale x 4 x float> @exp2_nxv4f32_sitofp_i8( -; NOLDEXP-SAME: <vscale x 4 x i8> [[X:%.*]]) { -; NOLDEXP-NEXT: [[ITOFP:%.*]] = sitofp <vscale x 4 x i8> [[X]] to <vscale x 4 x float> -; NOLDEXP-NEXT: [[EXP2:%.*]] = call <vscale x 4 x float> @llvm.exp2.nxv4f32(<vscale x 4 x float> [[ITOFP]]) -; NOLDEXP-NEXT: ret <vscale x 4 x float> [[EXP2]] +; CHECK-LABEL: define <vscale x 4 x float> @exp2_nxv4f32_sitofp_i8( +; CHECK-SAME: <vscale x 4 x i8> [[X:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = sext <vscale x 4 x i8> [[X]] to <vscale x 4 x i32> +; CHECK-NEXT: [[EXP2:%.*]] = 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> [[TMP1]]) +; CHECK-NEXT: ret <vscale x 4 x float> [[EXP2]] ; %itofp = sitofp <vscale x 4 x i8> %x to <vscale x 4 x float> %exp2 = call <vscale x 4 x float> @llvm.exp2.nxv4f32(<vscale x 4 x float> %itofp) diff --git a/llvm/test/Transforms/InstCombine/pow-to-ldexp.ll b/llvm/test/Transforms/InstCombine/pow-to-ldexp.ll index b61f880..cb51e92 100644 --- a/llvm/test/Transforms/InstCombine/pow-to-ldexp.ll +++ b/llvm/test/Transforms/InstCombine/pow-to-ldexp.ll @@ -5,16 +5,10 @@ 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]] +; CHECK-LABEL: define float @pow_sitofp_f32_const_base_2( +; CHECK-SAME: i32 [[X:%.*]]) { +; CHECK-NEXT: [[EXP2:%.*]] = tail call float @llvm.ldexp.f32.i32(float 1.000000e+00, i32 [[X]]) +; CHECK-NEXT: ret float [[EXP2]] ; %itofp = sitofp i32 %x to float %pow = tail call float @llvm.pow.f32(float 2.000000e+00, float %itofp) @@ -22,16 +16,10 @@ define float @pow_sitofp_f32_const_base_2(i32 %x) { } 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]] +; CHECK-LABEL: define float @pow_sitofp_f32_const_base_2__flags( +; CHECK-SAME: i32 [[X:%.*]]) { +; CHECK-NEXT: [[EXP2:%.*]] = tail call nnan nsz float @llvm.ldexp.f32.i32(float 1.000000e+00, i32 [[X]]) +; CHECK-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) @@ -115,16 +103,10 @@ define float @pow_sitofp_f32_const_base_16(i32 %x) { } 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]] +; CHECK-LABEL: define double @pow_sitofp_f64_const_base_2( +; CHECK-SAME: i32 [[X:%.*]]) { +; CHECK-NEXT: [[EXP2:%.*]] = tail call double @llvm.ldexp.f64.i32(double 1.000000e+00, i32 [[X]]) +; CHECK-NEXT: ret double [[EXP2]] ; %itofp = sitofp i32 %x to double %pow = tail call double @llvm.pow.f64(double 2.000000e+00, double %itofp) @@ -144,16 +126,10 @@ define half @pow_sitofp_f16_const_base_2(i32 %x) { } define <2 x float> @pow_sitofp_v2f32_const_base_2(<2 x i32> %x) { -; LDEXP-LABEL: define <2 x float> @pow_sitofp_v2f32_const_base_2( -; LDEXP-SAME: <2 x i32> [[X:%.*]]) { -; LDEXP-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-NEXT: ret <2 x float> [[EXP2]] -; -; 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]] +; CHECK-LABEL: define <2 x float> @pow_sitofp_v2f32_const_base_2( +; CHECK-SAME: <2 x i32> [[X:%.*]]) { +; CHECK-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]]) +; CHECK-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 2.000000e+00, float 2.000000e+00>, <2 x float> %itofp) @@ -199,16 +175,10 @@ define <2 x float> @pow_sitofp_v2f32_const_base_mixed_2(<2 x i32> %x) { } define <2 x float> @pow_sitofp_v2f32_const_base_2__flags(<2 x i32> %x) { -; LDEXP-LABEL: define <2 x float> @pow_sitofp_v2f32_const_base_2__flags( -; LDEXP-SAME: <2 x i32> [[X:%.*]]) { -; LDEXP-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-NEXT: ret <2 x float> [[EXP2]] -; -; 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]] +; CHECK-LABEL: define <2 x float> @pow_sitofp_v2f32_const_base_2__flags( +; CHECK-SAME: <2 x i32> [[X:%.*]]) { +; CHECK-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]]) +; CHECK-NEXT: ret <2 x float> [[EXP2]] ; %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) @@ -216,16 +186,10 @@ define <2 x float> @pow_sitofp_v2f32_const_base_2__flags(<2 x i32> %x) { } define <vscale x 4 x float> @pow_sitofp_nxv4f32_const_base_2(<vscale x 4 x i32> %x) { -; LDEXP-LABEL: define <vscale x 4 x float> @pow_sitofp_nxv4f32_const_base_2( -; LDEXP-SAME: <vscale x 4 x i32> [[X:%.*]]) { -; LDEXP-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-NEXT: ret <vscale x 4 x float> [[EXP2]] -; -; 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]] +; CHECK-LABEL: define <vscale x 4 x float> @pow_sitofp_nxv4f32_const_base_2( +; CHECK-SAME: <vscale x 4 x i32> [[X:%.*]]) { +; CHECK-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]]) +; CHECK-NEXT: ret <vscale x 4 x float> [[EXP2]] ; %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) @@ -233,16 +197,10 @@ define <vscale x 4 x float> @pow_sitofp_nxv4f32_const_base_2(<vscale x 4 x i32> } define <2 x half> @pow_sitofp_v2f16_const_base_2(<2 x i32> %x) { -; LDEXP-LABEL: define <2 x half> @pow_sitofp_v2f16_const_base_2( -; LDEXP-SAME: <2 x i32> [[X:%.*]]) { -; LDEXP-NEXT: [[EXP2:%.*]] = tail call <2 x half> @llvm.ldexp.v2f16.v2i32(<2 x half> <half 0xH3C00, half 0xH3C00>, <2 x i32> [[X]]) -; LDEXP-NEXT: ret <2 x half> [[EXP2]] -; -; 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]] +; CHECK-LABEL: define <2 x half> @pow_sitofp_v2f16_const_base_2( +; CHECK-SAME: <2 x i32> [[X:%.*]]) { +; CHECK-NEXT: [[EXP2:%.*]] = tail call <2 x half> @llvm.ldexp.v2f16.v2i32(<2 x half> <half 0xH3C00, half 0xH3C00>, <2 x i32> [[X]]) +; CHECK-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) @@ -250,16 +208,10 @@ define <2 x half> @pow_sitofp_v2f16_const_base_2(<2 x i32> %x) { } define <2 x double> @pow_sitofp_v2f64_const_base_2(<2 x i32> %x) { -; LDEXP-LABEL: define <2 x double> @pow_sitofp_v2f64_const_base_2( -; LDEXP-SAME: <2 x i32> [[X:%.*]]) { -; LDEXP-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-NEXT: ret <2 x double> [[EXP2]] -; -; 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]] +; CHECK-LABEL: define <2 x double> @pow_sitofp_v2f64_const_base_2( +; CHECK-SAME: <2 x i32> [[X:%.*]]) { +; CHECK-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]]) +; CHECK-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) @@ -333,16 +285,10 @@ define <2 x double> @pow_sitofp_v2f64_const_base_8(<2 x i32> %x) { } define fp128 @pow_sitofp_fp128_const_base_2(i32 %x) { -; LDEXP-LABEL: define fp128 @pow_sitofp_fp128_const_base_2( -; LDEXP-SAME: i32 [[X:%.*]]) { -; LDEXP-NEXT: [[LDEXPL:%.*]] = tail call fp128 @llvm.ldexp.f128.i32(fp128 0xL00000000000000003FFF000000000000, i32 [[X]]) -; LDEXP-NEXT: ret fp128 [[LDEXPL]] -; -; NOLDEXP-LABEL: define fp128 @pow_sitofp_fp128_const_base_2( -; NOLDEXP-SAME: i32 [[X:%.*]]) { -; NOLDEXP-NEXT: [[ITOFP:%.*]] = sitofp i32 [[X]] to fp128 -; NOLDEXP-NEXT: [[POW:%.*]] = tail call fp128 @llvm.exp2.f128(fp128 [[ITOFP]]) -; NOLDEXP-NEXT: ret fp128 [[POW]] +; CHECK-LABEL: define fp128 @pow_sitofp_fp128_const_base_2( +; CHECK-SAME: i32 [[X:%.*]]) { +; CHECK-NEXT: [[EXP2:%.*]] = tail call fp128 @llvm.ldexp.f128.i32(fp128 0xL00000000000000003FFF000000000000, i32 [[X]]) +; CHECK-NEXT: ret fp128 [[EXP2]] ; %itofp = sitofp i32 %x to fp128 %pow = tail call fp128 @llvm.pow.fp128(fp128 0xL00000000000000004000000000000000, fp128 %itofp) @@ -412,16 +358,10 @@ define float @libcall_powf_sitofp_f32_const_base_2__flags(i32 %x) { } define float @readnone_libcall_powf_sitofp_f32_const_base_2(i32 %x) { -; LDEXP-LABEL: define float @readnone_libcall_powf_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 @readnone_libcall_powf_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]] +; CHECK-LABEL: define float @readnone_libcall_powf_sitofp_f32_const_base_2( +; CHECK-SAME: i32 [[X:%.*]]) { +; CHECK-NEXT: [[EXP2:%.*]] = tail call float @llvm.ldexp.f32.i32(float 1.000000e+00, i32 [[X]]) +; CHECK-NEXT: ret float [[EXP2]] ; %itofp = sitofp i32 %x to float %pow = tail call float @powf(float 2.000000e+00, float %itofp) memory(none) @@ -429,16 +369,10 @@ define float @readnone_libcall_powf_sitofp_f32_const_base_2(i32 %x) { } define double @readnone_libcall_pow_sitofp_f32_const_base_2(i32 %x) { -; LDEXP-LABEL: define double @readnone_libcall_pow_sitofp_f32_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 @readnone_libcall_pow_sitofp_f32_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]] +; CHECK-LABEL: define double @readnone_libcall_pow_sitofp_f32_const_base_2( +; CHECK-SAME: i32 [[X:%.*]]) { +; CHECK-NEXT: [[EXP2:%.*]] = tail call double @llvm.ldexp.f64.i32(double 1.000000e+00, i32 [[X]]) +; CHECK-NEXT: ret double [[EXP2]] ; %itofp = sitofp i32 %x to double %pow = tail call double @pow(double 2.000000e+00, double %itofp) memory(none) @@ -446,16 +380,10 @@ define double @readnone_libcall_pow_sitofp_f32_const_base_2(i32 %x) { } define fp128 @readnone_libcall_powl_sitofp_fp128_const_base_2(i32 %x) { -; LDEXP-LABEL: define fp128 @readnone_libcall_powl_sitofp_fp128_const_base_2( -; LDEXP-SAME: i32 [[X:%.*]]) { -; LDEXP-NEXT: [[LDEXPL:%.*]] = tail call fp128 @llvm.ldexp.f128.i32(fp128 0xL00000000000000003FFF000000000000, i32 [[X]]) -; LDEXP-NEXT: ret fp128 [[LDEXPL]] -; -; NOLDEXP-LABEL: define fp128 @readnone_libcall_powl_sitofp_fp128_const_base_2( -; NOLDEXP-SAME: i32 [[X:%.*]]) { -; NOLDEXP-NEXT: [[ITOFP:%.*]] = sitofp i32 [[X]] to fp128 -; NOLDEXP-NEXT: [[POW:%.*]] = tail call fp128 @llvm.exp2.f128(fp128 [[ITOFP]]) -; NOLDEXP-NEXT: ret fp128 [[POW]] +; CHECK-LABEL: define fp128 @readnone_libcall_powl_sitofp_fp128_const_base_2( +; CHECK-SAME: i32 [[X:%.*]]) { +; CHECK-NEXT: [[EXP2:%.*]] = tail call fp128 @llvm.ldexp.f128.i32(fp128 0xL00000000000000003FFF000000000000, i32 [[X]]) +; CHECK-NEXT: ret fp128 [[EXP2]] ; %itofp = sitofp i32 %x to fp128 %pow = tail call fp128 @powl(fp128 0xL00000000000000004000000000000000, fp128 %itofp) memory(none) |