Index: llvm/trunk/lib/Transforms/Utils/SimplifyLibCalls.cpp =================================================================== --- llvm/trunk/lib/Transforms/Utils/SimplifyLibCalls.cpp +++ llvm/trunk/lib/Transforms/Utils/SimplifyLibCalls.cpp @@ -1284,9 +1284,25 @@ return InnerChain[Exp]; } +// Return a properly extended 32-bit integer if the operation is an itofp. +static Value *getIntToFPVal(Value *I2F, IRBuilder<> &B) { + if (isa(I2F) || isa(I2F)) { + Value *Op = cast(I2F)->getOperand(0); + // Make sure that the exponent fits inside an int32_t, + // thus avoiding any range issues that FP has not. + unsigned BitWidth = Op->getType()->getPrimitiveSizeInBits(); + if (BitWidth < 32 || + (BitWidth == 32 && isa(I2F))) + return isa(I2F) ? B.CreateSExt(Op, B.getInt32Ty()) + : B.CreateZExt(Op, B.getInt32Ty()); + } + + return nullptr; +} + /// Use exp{,2}(x * y) for pow(exp{,2}(x), y); -/// exp2(n * x) for pow(2.0 ** n, x); exp10(x) for pow(10.0, x); -/// exp2(log2(n) * x) for pow(n, x). +/// ldexp(1.0, x) for pow(2.0, itofp(x)); exp2(n * x) for pow(2.0 ** n, x); +/// exp10(x) for pow(10.0, x); exp2(log2(n) * x) for pow(n, x). Value *LibCallSimplifier::replacePowWithExp(CallInst *Pow, IRBuilder<> &B) { Value *Base = Pow->getArgOperand(0), *Expo = Pow->getArgOperand(1); AttributeList Attrs = Pow->getCalledFunction()->getAttributes(); @@ -1368,6 +1384,16 @@ if (!match(Pow->getArgOperand(0), m_APFloat(BaseF))) return nullptr; + // pow(2.0, itofp(x)) -> ldexp(1.0, x) + if (match(Base, m_SpecificFP(2.0)) && + (isa(Expo) || isa(Expo)) && + hasFloatFn(TLI, Ty, LibFunc_ldexp, LibFunc_ldexpf, LibFunc_ldexpl)) { + if (Value *ExpoI = getIntToFPVal(Expo, B)) + return emitBinaryFloatFnCall(ConstantFP::get(Ty, 1.0), ExpoI, TLI, + LibFunc_ldexp, LibFunc_ldexpf, LibFunc_ldexpl, + B, Attrs); + } + // pow(2.0 ** n, x) -> exp2(n * x) if (hasFloatFn(TLI, Ty, LibFunc_exp2, LibFunc_exp2f, LibFunc_exp2l)) { APFloat BaseR = APFloat(1.0); @@ -1605,16 +1631,8 @@ // powf(x, itofp(y)) -> powi(x, y) if (AllowApprox && (isa(Expo) || isa(Expo))) { - Value *IntExpo = cast(Expo)->getOperand(0); - Value *NewExpo = nullptr; - unsigned BitWidth = IntExpo->getType()->getPrimitiveSizeInBits(); - if (isa(Expo) && BitWidth == 32) - NewExpo = IntExpo; - else if (BitWidth < 32) - NewExpo = isa(Expo) ? B.CreateSExt(IntExpo, B.getInt32Ty()) - : B.CreateZExt(IntExpo, B.getInt32Ty()); - if (NewExpo) - return createPowWithIntegerExponent(Base, NewExpo, M, B); + if (Value *ExpoI = getIntToFPVal(Expo, B)) + return createPowWithIntegerExponent(Base, ExpoI, M, B); } return Shrunk; @@ -1635,20 +1653,12 @@ // Turn exp2(uitofp(x)) -> ldexp(1.0, zext(x)) if sizeof(x) < 32 if ((isa(Op) || isa(Op)) && hasFloatFn(TLI, Ty, LibFunc_ldexp, LibFunc_ldexpf, LibFunc_ldexpl)) { - Instruction *OpC = cast(Op); - Value *Exp = OpC->getOperand(0); - unsigned BitWidth = Exp->getType()->getPrimitiveSizeInBits(); - - if (BitWidth < 32 || - (BitWidth == 32 && isa(Op))) { - Exp = isa(Op) ? B.CreateSExt(Exp, B.getInt32Ty()) - : B.CreateZExt(Exp, B.getInt32Ty()); - + if (Value *Exp = getIntToFPVal(Op, B)) return emitBinaryFloatFnCall(ConstantFP::get(Ty, 1.0), Exp, TLI, LibFunc_ldexp, LibFunc_ldexpf, LibFunc_ldexpl, B, CI->getCalledFunction()->getAttributes()); - } } + return Ret; } Index: llvm/trunk/test/Transforms/InstCombine/pow_fp_int.ll =================================================================== --- llvm/trunk/test/Transforms/InstCombine/pow_fp_int.ll +++ llvm/trunk/test/Transforms/InstCombine/pow_fp_int.ll @@ -49,6 +49,18 @@ ret double %pow } +define double @pow_sitofp_double_const_base_2_fast(i32 %x) { +; CHECK-LABEL: @pow_sitofp_double_const_base_2_fast( +; CHECK-NEXT: [[LDEXPF:%.*]] = call afn float @ldexpf(float 1.000000e+00, i32 [[X:%.*]]) #1 +; CHECK-NEXT: [[RES:%.*]] = fpext float [[LDEXPF]] to double +; CHECK-NEXT: ret double [[RES]] +; + %subfp = sitofp i32 %x to float + %pow = tail call afn float @llvm.pow.f32(float 2.000000e+00, float %subfp) + %res = fpext float %pow to double + ret double %res +} + define double @pow_sitofp_double_const_base_power_of_2_fast(i32 %x) { ; CHECK-LABEL: @pow_sitofp_double_const_base_power_of_2_fast( ; CHECK-NEXT: [[SUBFP:%.*]] = sitofp i32 [[X:%.*]] to float @@ -63,6 +75,19 @@ ret double %res } +define double @pow_uitofp_const_base_2_fast(i31 %x) { +; CHECK-LABEL: @pow_uitofp_const_base_2_fast( +; CHECK-NEXT: [[TMP1:%.*]] = zext i31 [[X:%.*]] to i32 +; CHECK-NEXT: [[LDEXPF:%.*]] = call afn float @ldexpf(float 1.000000e+00, i32 [[TMP1]]) #1 +; CHECK-NEXT: [[RES:%.*]] = fpext float [[LDEXPF]] to double +; CHECK-NEXT: ret double [[RES]] +; + %subfp = uitofp i31 %x to float + %pow = tail call afn float @llvm.pow.f32(float 2.000000e+00, float %subfp) + %res = fpext float %pow to double + ret double %res +} + define double @pow_uitofp_const_base_power_of_2_fast(i31 %x) { ; CHECK-LABEL: @pow_uitofp_const_base_power_of_2_fast( ; CHECK-NEXT: [[SUBFP:%.*]] = uitofp i31 [[X:%.*]] to float @@ -210,6 +235,19 @@ ret double %res } +define double @pow_uitofp_const_base_2_fast_i32(i32 %x) { +; CHECK-LABEL: @pow_uitofp_const_base_2_fast_i32( +; CHECK-NEXT: [[SUBFP:%.*]] = uitofp i32 [[X:%.*]] to float +; CHECK-NEXT: [[EXP2:%.*]] = call fast float @llvm.exp2.f32(float [[SUBFP]]) +; CHECK-NEXT: [[RES:%.*]] = fpext float [[EXP2]] to double +; CHECK-NEXT: ret double [[RES]] +; + %subfp = uitofp i32 %x to float + %pow = tail call fast float @llvm.pow.f32(float 2.000000e+00, float %subfp) + %res = fpext float %pow to double + ret double %res +} + define double @pow_uitofp_const_base_power_of_2_fast_i32(i32 %x) { ; CHECK-LABEL: @pow_uitofp_const_base_power_of_2_fast_i32( ; CHECK-NEXT: [[SUBFP:%.*]] = uitofp i32 [[X:%.*]] to float @@ -303,6 +341,18 @@ ret double %res } +define double @pow_sitofp_const_base_2_no_fast(i32 %x) { +; CHECK-LABEL: @pow_sitofp_const_base_2_no_fast( +; CHECK-NEXT: [[LDEXPF:%.*]] = call float @ldexpf(float 1.000000e+00, i32 [[X:%.*]]) #1 +; CHECK-NEXT: [[RES:%.*]] = fpext float [[LDEXPF]] to double +; CHECK-NEXT: ret double [[RES]] +; + %subfp = sitofp i32 %x to float + %pow = tail call float @llvm.pow.f32(float 2.000000e+00, float %subfp) + %res = fpext float %pow to double + ret double %res +} + define double @pow_sitofp_const_base_power_of_2_no_fast(i32 %x) { ; CHECK-LABEL: @pow_sitofp_const_base_power_of_2_no_fast( ; CHECK-NEXT: [[SUBFP:%.*]] = sitofp i32 [[X:%.*]] to float @@ -317,6 +367,19 @@ ret double %res } +define double @pow_uitofp_const_base_2_no_fast(i32 %x) { +; CHECK-LABEL: @pow_uitofp_const_base_2_no_fast( +; CHECK-NEXT: [[SUBFP:%.*]] = uitofp i32 [[X:%.*]] to float +; CHECK-NEXT: [[EXP2:%.*]] = call float @llvm.exp2.f32(float [[SUBFP]]) +; CHECK-NEXT: [[RES:%.*]] = fpext float [[EXP2]] to double +; CHECK-NEXT: ret double [[RES]] +; + %subfp = uitofp i32 %x to float + %pow = tail call float @llvm.pow.f32(float 2.000000e+00, float %subfp) + %res = fpext float %pow to double + ret double %res +} + define double @pow_uitofp_const_base_power_of_2_no_fast(i32 %x) { ; CHECK-LABEL: @pow_uitofp_const_base_power_of_2_no_fast( ; CHECK-NEXT: [[SUBFP:%.*]] = uitofp i32 [[X:%.*]] to float