1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -instcombine -S | FileCheck %s
4 define float @powf_expf(float %x, float %y) {
5 ; CHECK-LABEL: @powf_expf(
6 ; CHECK-NEXT: [[MUL:%.*]] = fmul fast float [[X:%.*]], [[Y:%.*]]
7 ; CHECK-NEXT: [[EXP:%.*]] = call fast float @llvm.exp.f32(float [[MUL]])
8 ; CHECK-NEXT: ret float [[EXP]]
10 %call = call fast float @expf(float %x) nounwind readnone
11 %pow = call fast float @llvm.pow.f32(float %call, float %y)
15 define float @powf_expf_libcall(float %x, float %y) {
16 ; CHECK-LABEL: @powf_expf_libcall(
17 ; CHECK-NEXT: [[MUL:%.*]] = fmul fast float [[X:%.*]], [[Y:%.*]]
18 ; CHECK-NEXT: [[EXPF:%.*]] = call fast float @expf(float [[MUL]])
19 ; CHECK-NEXT: ret float [[EXPF]]
21 %call = call fast float @expf(float %x)
22 %pow = call fast float @powf(float %call, float %y)
26 define double @pow_exp(double %x, double %y) {
27 ; CHECK-LABEL: @pow_exp(
28 ; CHECK-NEXT: [[MUL:%.*]] = fmul fast double [[X:%.*]], [[Y:%.*]]
29 ; CHECK-NEXT: [[EXP:%.*]] = call fast double @llvm.exp.f64(double [[MUL]])
30 ; CHECK-NEXT: ret double [[EXP]]
32 %call = call fast double @exp(double %x) nounwind readnone
33 %pow = call fast double @llvm.pow.f64(double %call, double %y)
37 define double @pow_exp_not_intrinsic(double %x, double %y) {
38 ; CHECK-LABEL: @pow_exp_not_intrinsic(
39 ; CHECK-NEXT: [[MUL:%.*]] = fmul fast double [[X:%.*]], [[Y:%.*]]
40 ; CHECK-NEXT: [[EXP:%.*]] = call fast double @llvm.exp.f64(double [[MUL]])
41 ; CHECK-NEXT: ret double [[EXP]]
43 %call = call fast double @exp(double %x) nounwind readnone
44 %pow = call fast double @pow(double %call, double %y) nounwind readnone
48 define fp128 @powl_expl(fp128 %x, fp128 %y) {
49 ; CHECK-LABEL: @powl_expl(
50 ; CHECK-NEXT: [[MUL:%.*]] = fmul fast fp128 [[X:%.*]], [[Y:%.*]]
51 ; CHECK-NEXT: [[EXP:%.*]] = call fast fp128 @llvm.exp.f128(fp128 [[MUL]])
52 ; CHECK-NEXT: ret fp128 [[EXP]]
54 %call = call fast fp128 @expl(fp128 %x) nounwind readnone
55 %pow = call fast fp128 @llvm.pow.f128(fp128 %call, fp128 %y)
59 define fp128 @powl_expl_not_fast(fp128 %x, fp128 %y) {
60 ; CHECK-LABEL: @powl_expl_not_fast(
61 ; CHECK-NEXT: [[CALL:%.*]] = call fp128 @expl(fp128 [[X:%.*]])
62 ; CHECK-NEXT: [[POW:%.*]] = call fast fp128 @llvm.pow.f128(fp128 [[CALL]], fp128 [[Y:%.*]])
63 ; CHECK-NEXT: ret fp128 [[POW]]
65 %call = call fp128 @expl(fp128 %x)
66 %pow = call fast fp128 @llvm.pow.f128(fp128 %call, fp128 %y)
70 define float @powf_exp2f(float %x, float %y) {
71 ; CHECK-LABEL: @powf_exp2f(
72 ; CHECK-NEXT: [[MUL:%.*]] = fmul fast float [[X:%.*]], [[Y:%.*]]
73 ; CHECK-NEXT: [[EXP2:%.*]] = call fast float @llvm.exp2.f32(float [[MUL]])
74 ; CHECK-NEXT: ret float [[EXP2]]
76 %call = call fast float @exp2f(float %x) nounwind readnone
77 %pow = call fast float @llvm.pow.f32(float %call, float %y)
81 define float @powf_exp2f_not_intrinsic(float %x, float %y) {
82 ; CHECK-LABEL: @powf_exp2f_not_intrinsic(
83 ; CHECK-NEXT: [[MUL:%.*]] = fmul fast float [[X:%.*]], [[Y:%.*]]
84 ; CHECK-NEXT: [[EXP2:%.*]] = call fast float @llvm.exp2.f32(float [[MUL]])
85 ; CHECK-NEXT: ret float [[EXP2]]
87 %call = call fast float @exp2f(float %x) nounwind readnone
88 %pow = call fast float @powf(float %call, float %y) nounwind readnone
92 define double @pow_exp2(double %x, double %y) {
93 ; CHECK-LABEL: @pow_exp2(
94 ; CHECK-NEXT: [[MUL:%.*]] = fmul fast double [[X:%.*]], [[Y:%.*]]
95 ; CHECK-NEXT: [[EXP2:%.*]] = call fast double @llvm.exp2.f64(double [[MUL]])
96 ; CHECK-NEXT: ret double [[EXP2]]
98 %call = call fast double @exp2(double %x) nounwind readnone
99 %pow = call fast double @llvm.pow.f64(double %call, double %y)
103 define double @pow_exp2_libcall(double %x, double %y) {
104 ; CHECK-LABEL: @pow_exp2_libcall(
105 ; CHECK-NEXT: [[MUL:%.*]] = fmul fast double [[X:%.*]], [[Y:%.*]]
106 ; CHECK-NEXT: [[EXP2:%.*]] = call fast double @exp2(double [[MUL]])
107 ; CHECK-NEXT: ret double [[EXP2]]
109 %call = call fast double @exp2(double %x)
110 %pow = call fast double @pow(double %call, double %y)
114 define fp128 @powl_exp2l(fp128 %x, fp128 %y) {
115 ; CHECK-LABEL: @powl_exp2l(
116 ; CHECK-NEXT: [[MUL:%.*]] = fmul fast fp128 [[X:%.*]], [[Y:%.*]]
117 ; CHECK-NEXT: [[EXP2:%.*]] = call fast fp128 @llvm.exp2.f128(fp128 [[MUL]])
118 ; CHECK-NEXT: ret fp128 [[EXP2]]
120 %call = call fast fp128 @exp2l(fp128 %x) nounwind readnone
121 %pow = call fast fp128 @llvm.pow.f128(fp128 %call, fp128 %y)
125 define fp128 @powl_exp2l_not_fast(fp128 %x, fp128 %y) {
126 ; CHECK-LABEL: @powl_exp2l_not_fast(
127 ; CHECK-NEXT: [[CALL:%.*]] = call fp128 @exp2l(fp128 [[X:%.*]])
128 ; CHECK-NEXT: [[POW:%.*]] = call fast fp128 @llvm.pow.f128(fp128 [[CALL]], fp128 [[Y:%.*]])
129 ; CHECK-NEXT: ret fp128 [[POW]]
131 %call = call fp128 @exp2l(fp128 %x)
132 %pow = call fast fp128 @llvm.pow.f128(fp128 %call, fp128 %y)
136 ; TODO: exp10() is not widely enabled by many targets yet.
138 define float @powf_exp10f(float %x, float %y) {
139 ; CHECK-LABEL: @powf_exp10f(
140 ; CHECK-NEXT: [[CALL:%.*]] = call fast float @exp10f(float [[X:%.*]]) #1
141 ; CHECK-NEXT: [[POW:%.*]] = call fast float @llvm.pow.f32(float [[CALL]], float [[Y:%.*]])
142 ; CHECK-NEXT: ret float [[POW]]
144 %call = call fast float @exp10f(float %x) nounwind readnone
145 %pow = call fast float @llvm.pow.f32(float %call, float %y)
149 define double @pow_exp10(double %x, double %y) {
150 ; CHECK-LABEL: @pow_exp10(
151 ; CHECK-NEXT: [[CALL:%.*]] = call fast double @exp10(double [[X:%.*]]) #1
152 ; CHECK-NEXT: [[POW:%.*]] = call fast double @llvm.pow.f64(double [[CALL]], double [[Y:%.*]])
153 ; CHECK-NEXT: ret double [[POW]]
155 %call = call fast double @exp10(double %x) nounwind readnone
156 %pow = call fast double @llvm.pow.f64(double %call, double %y)
160 define fp128 @pow_exp10l(fp128 %x, fp128 %y) {
161 ; CHECK-LABEL: @pow_exp10l(
162 ; CHECK-NEXT: [[CALL:%.*]] = call fast fp128 @exp10l(fp128 [[X:%.*]]) #1
163 ; CHECK-NEXT: [[POW:%.*]] = call fast fp128 @llvm.pow.f128(fp128 [[CALL]], fp128 [[Y:%.*]])
164 ; CHECK-NEXT: ret fp128 [[POW]]
166 %call = call fast fp128 @exp10l(fp128 %x) nounwind readnone
167 %pow = call fast fp128 @llvm.pow.f128(fp128 %call, fp128 %y)
171 define float @reuse_fast(float %x, float %y, float * %p) {
172 ; CHECK-LABEL: @reuse_fast(
173 ; CHECK-NEXT: [[EXP:%.*]] = call fast float @expf(float [[X:%.*]])
174 ; CHECK-NEXT: [[POW:%.*]] = call fast float @powf(float [[EXP]], float [[Y:%.*]])
175 ; CHECK-NEXT: store float [[EXP]], float* [[P:%.*]], align 4
176 ; CHECK-NEXT: ret float [[POW]]
178 %exp = call fast float @expf(float %x)
179 %pow = call fast float @powf(float %exp, float %y)
180 store float %exp, float *%p, align 4
184 define fp128 @reuse_libcall(fp128 %x, fp128 %y, fp128 * %p) {
185 ; CHECK-LABEL: @reuse_libcall(
186 ; CHECK-NEXT: [[EXP:%.*]] = call fp128 @expl(fp128 [[X:%.*]])
187 ; CHECK-NEXT: [[POW:%.*]] = call fp128 @powl(fp128 [[EXP]], fp128 [[Y:%.*]])
188 ; CHECK-NEXT: store fp128 [[EXP]], fp128* [[P:%.*]], align 16
189 ; CHECK-NEXT: ret fp128 [[POW]]
191 %exp = call fp128 @expl(fp128 %x)
192 %pow = call fp128 @powl(fp128 %exp, fp128 %y)
193 store fp128 %exp, fp128 *%p, align 16
197 define double @function_pointer(double ()* %fptr, double %p1) {
198 ; CHECK-LABEL: @function_pointer(
199 ; CHECK-NEXT: [[CALL1:%.*]] = call fast double [[FPTR:%.*]]()
200 ; CHECK-NEXT: [[POW:%.*]] = call fast double @llvm.pow.f64(double [[CALL1]], double [[P1:%.*]])
201 ; CHECK-NEXT: ret double [[POW]]
203 %call1 = call fast double %fptr()
204 %pow = call fast double @llvm.pow.f64(double %call1, double %p1)
208 declare float @expf(float)
209 declare double @exp(double)
210 declare fp128 @expl(fp128)
211 declare float @exp2f(float)
212 declare double @exp2(double)
213 declare fp128 @exp2l(fp128)
214 declare float @exp10f(float)
215 declare double @exp10(double)
216 declare fp128 @exp10l(fp128)
217 declare float @powf(float, float)
218 declare double @pow(double, double)
219 declare fp128 @powl(fp128, fp128)
220 declare float @llvm.pow.f32(float, float)
221 declare double @llvm.pow.f64(double, double)
222 declare fp128 @llvm.pow.f128(fp128, fp128)