| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py |
| ; RUN: opt < %s -instcombine -S | FileCheck %s |
| |
| define float @powf_expf(float %x, float %y) { |
| ; CHECK-LABEL: @powf_expf( |
| ; 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 |
| } |
| |
| define float @powf_expf_libcall(float %x, float %y) { |
| ; CHECK-LABEL: @powf_expf_libcall( |
| ; 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 |
| } |
| |
| 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 @llvm.exp.f64(double [[MUL]]) |
| ; CHECK-NEXT: ret double [[EXP]] |
| ; |
| %call = call fast double @exp(double %x) nounwind readnone |
| %pow = call fast double @llvm.pow.f64(double %call, double %y) |
| ret double %pow |
| } |
| |
| 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 @llvm.exp.f64(double [[MUL]]) |
| ; CHECK-NEXT: ret double [[EXP]] |
| ; |
| %call = call fast double @exp(double %x) nounwind readnone |
| %pow = call fast double @pow(double %call, double %y) nounwind readnone |
| ret double %pow |
| } |
| |
| define fp128 @powl_expl(fp128 %x, fp128 %y) { |
| ; CHECK-LABEL: @powl_expl( |
| ; 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) |
| ret fp128 %pow |
| } |
| |
| define fp128 @powl_expl_not_fast(fp128 %x, fp128 %y) { |
| ; CHECK-LABEL: @powl_expl_not_fast( |
| ; CHECK-NEXT: [[CALL:%.*]] = call fp128 @expl(fp128 [[X:%.*]]) |
| ; CHECK-NEXT: [[POW:%.*]] = call fast fp128 @llvm.pow.f128(fp128 [[CALL]], fp128 [[Y:%.*]]) |
| ; CHECK-NEXT: ret fp128 [[POW]] |
| ; |
| %call = call fp128 @expl(fp128 %x) |
| %pow = call fast fp128 @llvm.pow.f128(fp128 %call, fp128 %y) |
| ret fp128 %pow |
| } |
| |
| define float @powf_exp2f(float %x, float %y) { |
| ; CHECK-LABEL: @powf_exp2f( |
| ; 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 |
| } |
| |
| define float @powf_exp2f_not_intrinsic(float %x, float %y) { |
| ; CHECK-LABEL: @powf_exp2f_not_intrinsic( |
| ; 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 |
| } |
| |
| 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 @llvm.exp2.f64(double [[MUL]]) |
| ; CHECK-NEXT: ret double [[EXP2]] |
| ; |
| %call = call fast double @exp2(double %x) nounwind readnone |
| %pow = call fast double @llvm.pow.f64(double %call, double %y) |
| ret double %pow |
| } |
| |
| define double @pow_exp2_libcall(double %x, double %y) { |
| ; CHECK-LABEL: @pow_exp2_libcall( |
| ; CHECK-NEXT: [[MUL:%.*]] = fmul fast double [[X:%.*]], [[Y:%.*]] |
| ; CHECK-NEXT: [[EXP2:%.*]] = call fast double @exp2(double [[MUL]]) |
| ; CHECK-NEXT: ret double [[EXP2]] |
| ; |
| %call = call fast double @exp2(double %x) |
| %pow = call fast double @pow(double %call, double %y) |
| ret double %pow |
| } |
| |
| define fp128 @powl_exp2l(fp128 %x, fp128 %y) { |
| ; CHECK-LABEL: @powl_exp2l( |
| ; 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) |
| ret fp128 %pow |
| } |
| |
| define fp128 @powl_exp2l_not_fast(fp128 %x, fp128 %y) { |
| ; CHECK-LABEL: @powl_exp2l_not_fast( |
| ; CHECK-NEXT: [[CALL:%.*]] = call fp128 @exp2l(fp128 [[X:%.*]]) |
| ; CHECK-NEXT: [[POW:%.*]] = call fast fp128 @llvm.pow.f128(fp128 [[CALL]], fp128 [[Y:%.*]]) |
| ; CHECK-NEXT: ret fp128 [[POW]] |
| ; |
| %call = call fp128 @exp2l(fp128 %x) |
| %pow = call fast fp128 @llvm.pow.f128(fp128 %call, fp128 %y) |
| ret fp128 %pow |
| } |
| |
| ; TODO: exp10() is not widely enabled by many targets yet. |
| |
| define float @powf_exp10f(float %x, float %y) { |
| ; CHECK-LABEL: @powf_exp10f( |
| ; CHECK-NEXT: [[CALL:%.*]] = call fast float @exp10f(float [[X:%.*]]) #1 |
| ; CHECK-NEXT: [[POW:%.*]] = call fast float @llvm.pow.f32(float [[CALL]], float [[Y:%.*]]) |
| ; CHECK-NEXT: ret float [[POW]] |
| ; |
| %call = call fast float @exp10f(float %x) nounwind readnone |
| %pow = call fast float @llvm.pow.f32(float %call, float %y) |
| ret float %pow |
| } |
| |
| define double @pow_exp10(double %x, double %y) { |
| ; CHECK-LABEL: @pow_exp10( |
| ; CHECK-NEXT: [[CALL:%.*]] = call fast double @exp10(double [[X:%.*]]) #1 |
| ; CHECK-NEXT: [[POW:%.*]] = call fast double @llvm.pow.f64(double [[CALL]], double [[Y:%.*]]) |
| ; CHECK-NEXT: ret double [[POW]] |
| ; |
| %call = call fast double @exp10(double %x) nounwind readnone |
| %pow = call fast double @llvm.pow.f64(double %call, double %y) |
| ret double %pow |
| } |
| |
| define fp128 @pow_exp10l(fp128 %x, fp128 %y) { |
| ; CHECK-LABEL: @pow_exp10l( |
| ; CHECK-NEXT: [[CALL:%.*]] = call fast fp128 @exp10l(fp128 [[X:%.*]]) #1 |
| ; CHECK-NEXT: [[POW:%.*]] = call fast fp128 @llvm.pow.f128(fp128 [[CALL]], fp128 [[Y:%.*]]) |
| ; CHECK-NEXT: ret fp128 [[POW]] |
| ; |
| %call = call fast fp128 @exp10l(fp128 %x) nounwind readnone |
| %pow = call fast fp128 @llvm.pow.f128(fp128 %call, fp128 %y) |
| ret fp128 %pow |
| } |
| |
| define float @reuse_fast(float %x, float %y, float * %p) { |
| ; CHECK-LABEL: @reuse_fast( |
| ; CHECK-NEXT: [[EXP:%.*]] = call fast float @expf(float [[X:%.*]]) |
| ; CHECK-NEXT: [[POW:%.*]] = call fast float @powf(float [[EXP]], float [[Y:%.*]]) |
| ; CHECK-NEXT: store float [[EXP]], float* [[P:%.*]], align 4 |
| ; CHECK-NEXT: ret float [[POW]] |
| ; |
| %exp = call fast float @expf(float %x) |
| %pow = call fast float @powf(float %exp, float %y) |
| store float %exp, float *%p, align 4 |
| ret float %pow |
| } |
| |
| define fp128 @reuse_libcall(fp128 %x, fp128 %y, fp128 * %p) { |
| ; CHECK-LABEL: @reuse_libcall( |
| ; CHECK-NEXT: [[EXP:%.*]] = call fp128 @expl(fp128 [[X:%.*]]) |
| ; CHECK-NEXT: [[POW:%.*]] = call fp128 @powl(fp128 [[EXP]], fp128 [[Y:%.*]]) |
| ; CHECK-NEXT: store fp128 [[EXP]], fp128* [[P:%.*]], align 16 |
| ; CHECK-NEXT: ret fp128 [[POW]] |
| ; |
| %exp = call fp128 @expl(fp128 %x) |
| %pow = call fp128 @powl(fp128 %exp, fp128 %y) |
| store fp128 %exp, fp128 *%p, align 16 |
| ret fp128 %pow |
| } |
| |
| define double @function_pointer(double ()* %fptr, double %p1) { |
| ; CHECK-LABEL: @function_pointer( |
| ; CHECK-NEXT: [[CALL1:%.*]] = call fast double [[FPTR:%.*]]() |
| ; CHECK-NEXT: [[POW:%.*]] = call fast double @llvm.pow.f64(double [[CALL1]], double [[P1:%.*]]) |
| ; CHECK-NEXT: ret double [[POW]] |
| ; |
| %call1 = call fast double %fptr() |
| %pow = call fast double @llvm.pow.f64(double %call1, double %p1) |
| ret double %pow |
| } |
| |
| declare float @expf(float) |
| declare double @exp(double) |
| declare fp128 @expl(fp128) |
| declare float @exp2f(float) |
| declare double @exp2(double) |
| declare fp128 @exp2l(fp128) |
| declare float @exp10f(float) |
| declare double @exp10(double) |
| declare fp128 @exp10l(fp128) |
| declare float @powf(float, float) |
| declare double @pow(double, double) |
| declare fp128 @powl(fp128, fp128) |
| declare float @llvm.pow.f32(float, float) |
| declare double @llvm.pow.f64(double, double) |
| declare fp128 @llvm.pow.f128(fp128, fp128) |