diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp index c9567b740026bf..eb1224abf00e29 100644 --- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp @@ -2087,15 +2087,16 @@ Value *LibCallSimplifier::replacePowWithExp(CallInst *Pow, IRBuilderBase &B) { AttributeList NoAttrs; // Attributes are only meaningful on the original call + const bool UseIntrinsic = Pow->doesNotAccessMemory(); + // pow(2.0, itofp(x)) -> ldexp(1.0, x) - // TODO: This does not work for vectors because there is no ldexp intrinsic. - if (!Ty->isVectorTy() && match(Base, m_SpecificFP(2.0)) && + if ((UseIntrinsic || !Ty->isVectorTy()) && match(Base, m_SpecificFP(2.0)) && (isa(Expo) || isa(Expo)) && hasFloatFn(M, TLI, Ty, LibFunc_ldexp, LibFunc_ldexpf, LibFunc_ldexpl)) { if (Value *ExpoI = getIntToFPVal(Expo, B, TLI->getIntSize())) { Constant *One = ConstantFP::get(Ty, 1.0); - if (Pow->doesNotAccessMemory()) { + if (UseIntrinsic) { return copyFlags(*Pow, B.CreateIntrinsic(Intrinsic::ldexp, {Ty, ExpoI->getType()}, {One, ExpoI}, Pow, "exp2")); diff --git a/llvm/test/Transforms/InstCombine/pow-to-ldexp.ll b/llvm/test/Transforms/InstCombine/pow-to-ldexp.ll index 27249dd5d72aec..b61f8809bd2598 100644 --- a/llvm/test/Transforms/InstCombine/pow-to-ldexp.ll +++ b/llvm/test/Transforms/InstCombine/pow-to-ldexp.ll @@ -144,16 +144,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-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> , <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> , <2 x float> [[ITOFP]]) -; LDEXP-NOEXP2-NEXT: ret <2 x float> [[POW]] +; 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> , <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:%.*]]) { @@ -205,15 +199,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-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> , <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> , <2 x i32> [[X]]) -; LDEXP-NOEXP2-NEXT: ret <2 x float> [[POW]] +; 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> , <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:%.*]]) { @@ -227,16 +216,10 @@ define <2 x float> @pow_sitofp_v2f32_const_base_2__flags(<2 x i32> %x) { } define @pow_sitofp_nxv4f32_const_base_2( %x) { -; LDEXP-EXP2-LABEL: define @pow_sitofp_nxv4f32_const_base_2( -; LDEXP-EXP2-SAME: [[X:%.*]]) { -; LDEXP-EXP2-NEXT: [[EXP2:%.*]] = tail call @llvm.ldexp.nxv4f32.nxv4i32( shufflevector ( insertelement ( poison, float 1.000000e+00, i64 0), poison, zeroinitializer), [[X]]) -; LDEXP-EXP2-NEXT: ret [[EXP2]] -; -; LDEXP-NOEXP2-LABEL: define @pow_sitofp_nxv4f32_const_base_2( -; LDEXP-NOEXP2-SAME: [[X:%.*]]) { -; LDEXP-NOEXP2-NEXT: [[ITOFP:%.*]] = sitofp [[X]] to -; LDEXP-NOEXP2-NEXT: [[POW:%.*]] = tail call @llvm.pow.nxv4f32( shufflevector ( insertelement ( poison, float 2.000000e+00, i64 0), poison, zeroinitializer), [[ITOFP]]) -; LDEXP-NOEXP2-NEXT: ret [[POW]] +; LDEXP-LABEL: define @pow_sitofp_nxv4f32_const_base_2( +; LDEXP-SAME: [[X:%.*]]) { +; LDEXP-NEXT: [[EXP2:%.*]] = tail call @llvm.ldexp.nxv4f32.nxv4i32( shufflevector ( insertelement ( poison, float 1.000000e+00, i64 0), poison, zeroinitializer), [[X]]) +; LDEXP-NEXT: ret [[EXP2]] ; ; NOLDEXP-LABEL: define @pow_sitofp_nxv4f32_const_base_2( ; NOLDEXP-SAME: [[X:%.*]]) { @@ -250,16 +233,10 @@ define @pow_sitofp_nxv4f32_const_base_2( } 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> , <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> , <2 x half> [[ITOFP]]) -; LDEXP-NOEXP2-NEXT: ret <2 x half> [[POW]] +; 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> , <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:%.*]]) { @@ -273,16 +250,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-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> , <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> , <2 x double> [[ITOFP]]) -; LDEXP-NOEXP2-NEXT: ret <2 x double> [[POW]] +; 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> , <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:%.*]]) {