mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-12-13 22:58:50 +00:00
ed678c9f29
We already check hasNoNaNs and that x is finite and strictly positive. That only leaves the following special cases (taken from the Linux man page for pow): If x is +1, the result is 1.0 (even if y is a NaN). If the absolute value of x is less than 1, and y is negative infinity, the result is positive infinity. If the absolute value of x is greater than 1, and y is negative infinity, the result is +0. If the absolute value of x is less than 1, and y is positive infinity, the result is +0. If the absolute value of x is greater than 1, and y is positive infinity, the result is positive infinity. The first case is handled elsewhere, and this transformation preserves all the others, so there is no need to limit it to hasNoInfs. Differential Revision: https://reviews.llvm.org/D79409
501 lines
18 KiB
LLVM
501 lines
18 KiB
LLVM
; 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
|
|
}
|
|
|
|
; pow(C,x) -> exp2(log2(C)*x)
|
|
|
|
declare void @use_d(double)
|
|
declare void @use_f(float)
|
|
|
|
define double @pow_ok_base(double %e) {
|
|
; CHECK-LABEL: @pow_ok_base(
|
|
; Do not change 0xBFE0776{{.*}} to the exact constant, see PR42740
|
|
; CHECK-NEXT: [[MUL:%.*]] = fmul nnan ninf afn double [[E:%.*]], 0xBFE0776{{.*}}
|
|
; CHECK-NEXT: [[EXP2:%.*]] = call nnan ninf afn double @exp2(double [[MUL]])
|
|
; CHECK-NEXT: ret double [[EXP2]]
|
|
;
|
|
%call = tail call afn nnan ninf double @pow(double 0x3FE6666666666666, double %e)
|
|
ret double %call
|
|
}
|
|
|
|
define double @pow_ok_base_fast(double %e) {
|
|
; CHECK-LABEL: @pow_ok_base_fast(
|
|
; CHECK-NEXT: [[MUL:%.*]] = fmul fast double [[E:%.*]], 0xBFE0776{{.*}}
|
|
; CHECK-NEXT: [[EXP2:%.*]] = call fast double @exp2(double [[MUL]])
|
|
; CHECK-NEXT: ret double [[EXP2]]
|
|
;
|
|
%call = tail call fast double @pow(double 0x3FE6666666666666, double %e)
|
|
ret double %call
|
|
}
|
|
|
|
define double @pow_ok_base2(double %e) {
|
|
; CHECK-LABEL: @pow_ok_base2(
|
|
; CHECK-NEXT: [[MUL:%.*]] = fmul nnan ninf afn double [[E:%.*]], 0x4010952{{.*}}
|
|
; CHECK-NEXT: [[EXP2:%.*]] = call nnan ninf afn double @exp2(double [[MUL]])
|
|
; CHECK-NEXT: ret double [[EXP2]]
|
|
;
|
|
%call = tail call afn nnan ninf double @pow(double 1.770000e+01, double %e)
|
|
ret double %call
|
|
}
|
|
|
|
define double @pow_ok_base3(double %e) {
|
|
; CHECK-LABEL: @pow_ok_base3(
|
|
; CHECK-NEXT: [[MUL:%.*]] = fmul nnan ninf afn double [[E:%.*]], 0x400AB0B5{{.*}}
|
|
; CHECK-NEXT: [[EXP2:%.*]] = call nnan ninf afn double @exp2(double [[MUL]])
|
|
; CHECK-NEXT: ret double [[EXP2]]
|
|
;
|
|
%call = tail call afn nnan ninf double @pow(double 1.010000e+01, double %e)
|
|
ret double %call
|
|
}
|
|
|
|
define double @pow_ok_ten_base(double %e) {
|
|
; CHECK-LABEL: @pow_ok_ten_base(
|
|
; CHECK-NEXT: [[MUL:%.*]] = fmul nnan ninf afn double [[E:%.*]], 0x400A934F{{.*}}
|
|
; CHECK-NEXT: [[EXP2:%.*]] = call nnan ninf afn double @exp2(double [[MUL]])
|
|
; CHECK-NEXT: ret double [[EXP2]]
|
|
;
|
|
%call = tail call afn nnan ninf double @pow(double 1.000000e+01, double %e)
|
|
ret double %call
|
|
}
|
|
|
|
define double @pow_ok_denorm_base(double %e) {
|
|
; CHECK-LABEL: @pow_ok_denorm_base(
|
|
; CHECK-NEXT: [[MUL:%.*]] = fmul nnan ninf afn double [[E:%.*]], 0xC0904800000005C5
|
|
; CHECK-NEXT: [[EXP2:%.*]] = call nnan ninf afn double @exp2(double [[MUL]])
|
|
; CHECK-NEXT: ret double [[EXP2]]
|
|
;
|
|
%call = tail call afn nnan ninf double @pow(double 0x00000000FFFFFFFF, double %e)
|
|
ret double %call
|
|
}
|
|
|
|
define float @powf_ok_base(float %e) {
|
|
; CHECK-LABEL: @powf_ok_base(
|
|
; CHECK-NEXT: [[MUL:%.*]] = fmul nnan ninf afn float [[E:%.*]], 0xBFE07762{{.*}}
|
|
; CHECK-NEXT: [[EXP2F:%.*]] = call nnan ninf afn float @exp2f(float [[MUL]])
|
|
; CHECK-NEXT: ret float [[EXP2F]]
|
|
;
|
|
%call = tail call afn nnan ninf float @powf(float 0x3FE6666660000000, float %e)
|
|
ret float %call
|
|
}
|
|
|
|
define float @powf_ok_base2(float %e) {
|
|
; CHECK-LABEL: @powf_ok_base2(
|
|
; CHECK-NEXT: [[MUL:%.*]] = fmul nnan ninf afn float [[E:%.*]], 0x4010952{{.*}}
|
|
; CHECK-NEXT: [[EXP2F:%.*]] = call nnan ninf afn float @exp2f(float [[MUL]])
|
|
; CHECK-NEXT: ret float [[EXP2F]]
|
|
;
|
|
%call = tail call afn nnan ninf float @powf(float 0x4031B33340000000, float %e)
|
|
ret float %call
|
|
}
|
|
|
|
define float @powf_ok_base3(float %e) {
|
|
; CHECK-LABEL: @powf_ok_base3(
|
|
; CHECK-NEXT: [[MUL:%.*]] = fmul nnan ninf afn float [[E:%.*]], 0x400AB0B5{{.*}}
|
|
; CHECK-NEXT: [[EXP2F:%.*]] = call nnan ninf afn float @exp2f(float [[MUL]])
|
|
; CHECK-NEXT: ret float [[EXP2F]]
|
|
;
|
|
%call = tail call afn nnan ninf float @powf(float 0x4024333340000000, float %e)
|
|
ret float %call
|
|
}
|
|
|
|
define float @powf_ok_ten_base(float %e) {
|
|
; CHECK-LABEL: @powf_ok_ten_base(
|
|
; CHECK-NEXT: [[MUL:%.*]] = fmul nnan ninf afn float [[E:%.*]], 0x400A934{{.*}}
|
|
; CHECK-NEXT: [[EXP2F:%.*]] = call nnan ninf afn float @exp2f(float [[MUL]])
|
|
; CHECK-NEXT: ret float [[EXP2F]]
|
|
;
|
|
%call = tail call afn nnan ninf float @powf(float 1.000000e+01, float %e)
|
|
ret float %call
|
|
}
|
|
|
|
define float @powf_ok_denorm_base(float %e) {
|
|
; CHECK-LABEL: @powf_ok_denorm_base(
|
|
; CHECK-NEXT: [[MUL:%.*]] = fmul nnan ninf afn float [[E:%.*]], -1.350000e+02
|
|
; CHECK-NEXT: [[EXP2F:%.*]] = call nnan ninf afn float @exp2f(float [[MUL]])
|
|
; CHECK-NEXT: ret float [[EXP2F]]
|
|
;
|
|
%call = tail call afn nnan ninf float @powf(float 0x3780000000000000, float %e)
|
|
ret float %call
|
|
}
|
|
|
|
; Negative tests
|
|
|
|
define double @pow_zero_base(double %e) {
|
|
; CHECK-LABEL: @pow_zero_base(
|
|
; CHECK-NEXT: [[CALL:%.*]] = tail call nnan ninf afn double @pow(double 0.000000e+00, double [[E:%.*]])
|
|
; CHECK-NEXT: ret double [[CALL]]
|
|
;
|
|
%call = tail call afn nnan ninf double @pow(double 0.000000e+00, double %e)
|
|
ret double %call
|
|
}
|
|
|
|
define double @pow_zero_base2(double %e) {
|
|
; CHECK-LABEL: @pow_zero_base2(
|
|
; CHECK-NEXT: [[CALL:%.*]] = tail call nnan ninf afn double @pow(double -0.000000e+00, double [[E:%.*]])
|
|
; CHECK-NEXT: ret double [[CALL]]
|
|
;
|
|
%call = tail call afn nnan ninf double @pow(double -0.000000e+00, double %e)
|
|
ret double %call
|
|
}
|
|
|
|
define double @pow_inf_base(double %e) {
|
|
; CHECK-LABEL: @pow_inf_base(
|
|
; CHECK-NEXT: [[CALL:%.*]] = tail call nnan ninf afn double @pow(double 0x7FF0000000000000, double [[E:%.*]])
|
|
; CHECK-NEXT: ret double [[CALL]]
|
|
;
|
|
%call = tail call afn nnan ninf double @pow(double 0x7FF0000000000000, double %e)
|
|
ret double %call
|
|
}
|
|
|
|
define double @pow_nan_base(double %e) {
|
|
; CHECK-LABEL: @pow_nan_base(
|
|
; CHECK-NEXT: [[CALL:%.*]] = tail call nnan ninf afn double @pow(double 0x7FF8000000000000, double [[E:%.*]])
|
|
; CHECK-NEXT: ret double [[CALL]]
|
|
;
|
|
%call = tail call afn nnan ninf double @pow(double 0x7FF8000000000000, double %e)
|
|
ret double %call
|
|
}
|
|
|
|
define double @pow_negative_base(double %e) {
|
|
; CHECK-LABEL: @pow_negative_base(
|
|
; CHECK-NEXT: [[CALL:%.*]] = tail call nnan ninf afn double @pow(double -4.000000e+00, double [[E:%.*]])
|
|
; CHECK-NEXT: ret double [[CALL]]
|
|
;
|
|
%call = tail call afn nnan ninf double @pow(double -4.000000e+00, double %e)
|
|
ret double %call
|
|
}
|
|
|
|
define double @pow_multiuse(double %e) {
|
|
; CHECK-LABEL: @pow_multiuse(
|
|
; CHECK-NEXT: [[MUL:%.*]] = fmul nnan ninf afn double [[E:%.*]], 0x4002934{{.*}}
|
|
; CHECK-NEXT: [[EXP2:%.*]] = call nnan ninf afn double @exp2(double [[MUL]])
|
|
; CHECK-NEXT: tail call void @use_d(double [[EXP2]])
|
|
; CHECK-NEXT: ret double [[EXP2]]
|
|
;
|
|
%call = tail call afn nnan ninf double @pow(double 5.000000e+00, double %e)
|
|
tail call void @use_d(double %call)
|
|
ret double %call
|
|
}
|
|
|
|
define double @pow_ok_base_no_afn(double %e) {
|
|
; CHECK-LABEL: @pow_ok_base_no_afn(
|
|
; CHECK-NEXT: [[CALL:%.*]] = tail call nnan ninf double @pow(double 0x3FE6666666666666, double [[E:%.*]])
|
|
; CHECK-NEXT: ret double [[CALL]]
|
|
;
|
|
%call = tail call nnan ninf double @pow(double 0x3FE6666666666666, double %e)
|
|
ret double %call
|
|
}
|
|
|
|
define double @pow_ok_base_no_nnan(double %e) {
|
|
; CHECK-LABEL: @pow_ok_base_no_nnan(
|
|
; CHECK-NEXT: [[CALL:%.*]] = tail call ninf afn double @pow(double 0x3FE6666666666666, double [[E:%.*]])
|
|
; CHECK-NEXT: ret double [[CALL]]
|
|
;
|
|
%call = tail call afn ninf double @pow(double 0x3FE6666666666666, double %e)
|
|
ret double %call
|
|
}
|
|
|
|
define double @pow_ok_base_no_ninf(double %e) {
|
|
; CHECK-LABEL: @pow_ok_base_no_ninf(
|
|
; CHECK-NEXT: [[MUL:%.*]] = fmul nnan afn double [[E:%.*]], 0xBFE0776{{.*}}
|
|
; CHECK-NEXT: [[EXP2:%.*]] = call nnan afn double @exp2(double [[MUL]])
|
|
; CHECK-NEXT: ret double [[EXP2]]
|
|
;
|
|
%call = tail call afn nnan double @pow(double 0x3FE6666666666666, double %e)
|
|
ret double %call
|
|
}
|
|
|
|
define float @powf_zero_base(float %e) {
|
|
; CHECK-LABEL: @powf_zero_base(
|
|
; CHECK-NEXT: [[CALL:%.*]] = tail call nnan ninf afn float @powf(float 0.000000e+00, float [[E:%.*]])
|
|
; CHECK-NEXT: ret float [[CALL]]
|
|
;
|
|
%call = tail call afn nnan ninf float @powf(float 0.000000e+00, float %e)
|
|
ret float %call
|
|
}
|
|
|
|
define float @powf_zero_base2(float %e) {
|
|
; CHECK-LABEL: @powf_zero_base2(
|
|
; CHECK-NEXT: [[CALL:%.*]] = tail call nnan ninf afn float @powf(float -0.000000e+00, float [[E:%.*]])
|
|
; CHECK-NEXT: ret float [[CALL]]
|
|
;
|
|
%call = tail call afn nnan ninf float @powf(float -0.000000e+00, float %e)
|
|
ret float %call
|
|
}
|
|
|
|
define float @powf_inf_base(float %e) {
|
|
; CHECK-LABEL: @powf_inf_base(
|
|
; CHECK-NEXT: [[CALL:%.*]] = tail call nnan ninf afn float @powf(float 0x7FF0000000000000, float [[E:%.*]])
|
|
; CHECK-NEXT: ret float [[CALL]]
|
|
;
|
|
%call = tail call afn nnan ninf float @powf(float 0x7FF0000000000000, float %e)
|
|
ret float %call
|
|
}
|
|
|
|
define float @powf_nan_base(float %e) {
|
|
; CHECK-LABEL: @powf_nan_base(
|
|
; CHECK-NEXT: [[CALL:%.*]] = tail call nnan ninf afn float @powf(float 0x7FF8000000000000, float [[E:%.*]])
|
|
; CHECK-NEXT: ret float [[CALL]]
|
|
;
|
|
%call = tail call afn nnan ninf float @powf(float 0x7FF8000000000000, float %e)
|
|
ret float %call
|
|
}
|
|
|
|
define float @powf_negative_base(float %e) {
|
|
; CHECK-LABEL: @powf_negative_base(
|
|
; CHECK-NEXT: [[CALL:%.*]] = tail call nnan ninf afn float @powf(float -4.000000e+00, float [[E:%.*]])
|
|
; CHECK-NEXT: ret float [[CALL]]
|
|
;
|
|
%call = tail call afn nnan ninf float @powf(float -4.000000e+00, float %e)
|
|
ret float %call
|
|
}
|
|
|
|
define float @powf_multiuse(float %e) {
|
|
; CHECK-LABEL: @powf_multiuse(
|
|
; CHECK-NEXT: [[MUL:%.*]] = fmul nnan ninf afn float [[E:%.*]], 0x4002934{{.*}}
|
|
; CHECK-NEXT: [[EXP2F:%.*]] = call nnan ninf afn float @exp2f(float [[MUL]])
|
|
; CHECK-NEXT: tail call void @use_f(float [[EXP2F]])
|
|
; CHECK-NEXT: ret float [[EXP2F]]
|
|
;
|
|
%call = tail call afn nnan ninf float @powf(float 5.000000e+00, float %e)
|
|
tail call void @use_f(float %call)
|
|
ret float %call
|
|
}
|
|
|
|
define float @powf_ok_base_no_afn(float %e) {
|
|
; CHECK-LABEL: @powf_ok_base_no_afn(
|
|
; CHECK-NEXT: [[CALL:%.*]] = tail call float @powf(float 0x3FE6666660000000, float [[E:%.*]])
|
|
; CHECK-NEXT: ret float [[CALL]]
|
|
;
|
|
%call = tail call float @powf(float 0x3FE6666660000000, float %e)
|
|
ret float %call
|
|
}
|
|
|
|
define fp128 @powl_long_dbl_no_fold(fp128 %e) {
|
|
; CHECK-LABEL: @powl_long_dbl_no_fold(
|
|
; CHECK-NEXT: [[CALL:%.*]] = tail call nnan ninf afn fp128 @powl(fp128 0xL00000000000000005001000000000000, fp128 [[E:%.*]])
|
|
; CHECK-NEXT: ret fp128 [[CALL]]
|
|
;
|
|
%call = tail call afn nnan ninf fp128 @powl(fp128 0xL00000000000000005001000000000000, fp128 %e)
|
|
ret fp128 %call
|
|
}
|
|
|
|
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)
|