Index: llvm/trunk/lib/Transforms/Utils/SimplifyLibCalls.cpp =================================================================== --- llvm/trunk/lib/Transforms/Utils/SimplifyLibCalls.cpp +++ llvm/trunk/lib/Transforms/Utils/SimplifyLibCalls.cpp @@ -1212,14 +1212,31 @@ LibFunc LibFn; Function *CalleeFn = BaseFn->getCalledFunction(); - if (CalleeFn && TLI->getLibFunc(CalleeFn->getName(), LibFn) && - (LibFn == LibFunc_exp || LibFn == LibFunc_exp2) && TLI->has(LibFn)) { + if (CalleeFn && + TLI->getLibFunc(CalleeFn->getName(), LibFn) && TLI->has(LibFn)) { + StringRef ExpName; + Intrinsic::ID ID; Value *ExpFn; + switch (LibFn) { + default: + return nullptr; + case LibFunc_expf: case LibFunc_exp: case LibFunc_expl: + ExpName = TLI->getName(LibFunc_exp); + ID = Intrinsic::exp; + break; + case LibFunc_exp2f: case LibFunc_exp2: case LibFunc_exp2l: + ExpName = TLI->getName(LibFunc_exp2); + ID = Intrinsic::exp2; + break; + } + // Create new exp{,2}() with the product as its argument. Value *FMul = B.CreateFMul(BaseFn->getArgOperand(0), Expo, "mul"); - ExpFn = emitUnaryFloatFnCall(FMul, CalleeFn->getName(), B, - BaseFn->getAttributes()); + ExpFn = BaseFn->doesNotAccessMemory() + ? B.CreateCall(Intrinsic::getDeclaration(Mod, ID, Ty), + FMul, ExpName) + : emitUnaryFloatFnCall(FMul, ExpName, B, BaseFn->getAttributes()); // Since the new exp{,2}() is different from the original one, dead code // elimination cannot be trusted to remove it, since it may have side Index: llvm/trunk/test/Transforms/InstCombine/pow-exp.ll =================================================================== --- llvm/trunk/test/Transforms/InstCombine/pow-exp.ll +++ llvm/trunk/test/Transforms/InstCombine/pow-exp.ll @@ -1,35 +1,32 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -instcombine -S | FileCheck %s -; TODO: Should result in expf(x * y). define float @powf_expf(float %x, float %y) { ; CHECK-LABEL: @powf_expf( -; CHECK-NEXT: [[CALL:%.*]] = call fast float @expf(float [[X:%.*]]) #1 -; CHECK-NEXT: [[POW:%.*]] = call fast float @llvm.pow.f32(float [[CALL]], float [[Y:%.*]]) -; CHECK-NEXT: ret float [[POW]] +; CHECK-NEXT: [[MUL:%.*]] = fmul fast float [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[EXP:%.*]] = call fast float @llvm.exp.f32(float [[MUL]]) +; CHECK-NEXT: ret float [[EXP]] ; %call = call fast float @expf(float %x) nounwind readnone %pow = call fast float @llvm.pow.f32(float %call, float %y) ret float %pow } -; TODO: Should result in expf(x * y). define float @powf_expf_libcall(float %x, float %y) { ; CHECK-LABEL: @powf_expf_libcall( -; CHECK-NEXT: [[CALL:%.*]] = call fast float @expf(float [[X:%.*]]) -; CHECK-NEXT: [[POW:%.*]] = call fast float @powf(float [[CALL]], float [[Y:%.*]]) -; CHECK-NEXT: ret float [[POW]] +; CHECK-NEXT: [[MUL:%.*]] = fmul fast float [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[EXPF:%.*]] = call fast float @expf(float [[MUL]]) +; CHECK-NEXT: ret float [[EXPF]] ; %call = call fast float @expf(float %x) %pow = call fast float @powf(float %call, float %y) ret float %pow } -; TODO: Should result in intrinsic call to exp(). define double @pow_exp(double %x, double %y) { ; CHECK-LABEL: @pow_exp( ; CHECK-NEXT: [[MUL:%.*]] = fmul fast double [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[EXP:%.*]] = call fast double @exp(double [[MUL]]) #1 +; CHECK-NEXT: [[EXP:%.*]] = call fast double @llvm.exp.f64(double [[MUL]]) ; CHECK-NEXT: ret double [[EXP]] ; %call = call fast double @exp(double %x) nounwind readnone @@ -37,11 +34,10 @@ ret double %pow } -; TODO: Should result in intrinsic call to exp(). define double @pow_exp_not_intrinsic(double %x, double %y) { ; CHECK-LABEL: @pow_exp_not_intrinsic( ; CHECK-NEXT: [[MUL:%.*]] = fmul fast double [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[EXP:%.*]] = call fast double @exp(double [[MUL]]) +; CHECK-NEXT: [[EXP:%.*]] = call fast double @llvm.exp.f64(double [[MUL]]) ; CHECK-NEXT: ret double [[EXP]] ; %call = call fast double @exp(double %x) nounwind readnone @@ -49,12 +45,11 @@ ret double %pow } -; TODO: Should result in expl(x * y). define fp128 @powl_expl(fp128 %x, fp128 %y) { ; CHECK-LABEL: @powl_expl( -; CHECK-NEXT: [[CALL:%.*]] = call fast fp128 @expl(fp128 [[X:%.*]]) #1 -; CHECK-NEXT: [[POW:%.*]] = call fast fp128 @llvm.pow.f128(fp128 [[CALL]], fp128 [[Y:%.*]]) -; CHECK-NEXT: ret fp128 [[POW]] +; CHECK-NEXT: [[MUL:%.*]] = fmul fast fp128 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[EXP:%.*]] = call fast fp128 @llvm.exp.f128(fp128 [[MUL]]) +; CHECK-NEXT: ret fp128 [[EXP]] ; %call = call fast fp128 @expl(fp128 %x) nounwind readnone %pow = call fast fp128 @llvm.pow.f128(fp128 %call, fp128 %y) @@ -72,35 +67,32 @@ ret fp128 %pow } -; TODO: Should result in exp2f(x * y). define float @powf_exp2f(float %x, float %y) { ; CHECK-LABEL: @powf_exp2f( -; CHECK-NEXT: [[CALL:%.*]] = call fast float @exp2f(float [[X:%.*]]) #1 -; CHECK-NEXT: [[POW:%.*]] = call fast float @llvm.pow.f32(float [[CALL]], float [[Y:%.*]]) -; CHECK-NEXT: ret float [[POW]] +; CHECK-NEXT: [[MUL:%.*]] = fmul fast float [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[EXP2:%.*]] = call fast float @llvm.exp2.f32(float [[MUL]]) +; CHECK-NEXT: ret float [[EXP2]] ; %call = call fast float @exp2f(float %x) nounwind readnone %pow = call fast float @llvm.pow.f32(float %call, float %y) ret float %pow } -; TODO: Should result in exp2f(x * y). define float @powf_exp2f_not_intrinsic(float %x, float %y) { ; CHECK-LABEL: @powf_exp2f_not_intrinsic( -; CHECK-NEXT: [[CALL:%.*]] = call fast float @exp2f(float [[X:%.*]]) #1 -; CHECK-NEXT: [[POW:%.*]] = call fast float @powf(float [[CALL]], float [[Y:%.*]]) #1 -; CHECK-NEXT: ret float [[POW]] +; CHECK-NEXT: [[MUL:%.*]] = fmul fast float [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[EXP2:%.*]] = call fast float @llvm.exp2.f32(float [[MUL]]) +; CHECK-NEXT: ret float [[EXP2]] ; %call = call fast float @exp2f(float %x) nounwind readnone %pow = call fast float @powf(float %call, float %y) nounwind readnone ret float %pow } -; TODO: Should result in intrinsic call to exp2(). define double @pow_exp2(double %x, double %y) { ; CHECK-LABEL: @pow_exp2( ; CHECK-NEXT: [[MUL:%.*]] = fmul fast double [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[EXP2:%.*]] = call fast double @exp2(double [[MUL]]) #1 +; CHECK-NEXT: [[EXP2:%.*]] = call fast double @llvm.exp2.f64(double [[MUL]]) ; CHECK-NEXT: ret double [[EXP2]] ; %call = call fast double @exp2(double %x) nounwind readnone @@ -110,7 +102,7 @@ define double @pow_exp2_libcall(double %x, double %y) { ; CHECK-LABEL: @pow_exp2_libcall( -; CHECK-NEXT: [[MUL:%.*]] = fmul fast double [[X]], [[Y:%.*]] +; CHECK-NEXT: [[MUL:%.*]] = fmul fast double [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: [[EXP2:%.*]] = call fast double @exp2(double [[MUL]]) ; CHECK-NEXT: ret double [[EXP2]] ; @@ -119,12 +111,11 @@ ret double %pow } -; TODO: Should result in intrinsic call to exp2l(). define fp128 @powl_exp2l(fp128 %x, fp128 %y) { ; CHECK-LABEL: @powl_exp2l( -; CHECK-NEXT: [[CALL:%.*]] = call fast fp128 @exp2l(fp128 [[X:%.*]]) #1 -; CHECK-NEXT: [[POW:%.*]] = call fast fp128 @llvm.pow.f128(fp128 [[CALL]], fp128 [[Y:%.*]]) -; CHECK-NEXT: ret fp128 [[POW]] +; CHECK-NEXT: [[MUL:%.*]] = fmul fast fp128 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[EXP2:%.*]] = call fast fp128 @llvm.exp2.f128(fp128 [[MUL]]) +; CHECK-NEXT: ret fp128 [[EXP2]] ; %call = call fast fp128 @exp2l(fp128 %x) nounwind readnone %pow = call fast fp128 @llvm.pow.f128(fp128 %call, fp128 %y)