xref: /llvm-project/llvm/test/Transforms/InstCombine/pow_fp_int.ll (revision 38fffa630ee80163dc65e759392ad29798905679)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 3
2; RUN: opt -mtriple unknown -passes=instcombine -S < %s | FileCheck %s
3target datalayout = "e"
4
5; PR42190
6; Can't generate test checks due to PR42740.
7
8define double @pow_sitofp_const_base_fast(i32 %x) {
9; CHECK-LABEL: define double @pow_sitofp_const_base_fast(
10; CHECK-SAME: i32 [[X:%.*]]) {
11; CHECK-NEXT:    [[POW:%.*]] = tail call afn float @llvm.powi.f32.i32(float 7.000000e+00, i32 [[X]])
12; CHECK-NEXT:    [[RES:%.*]] = fpext float [[POW]] to double
13; CHECK-NEXT:    ret double [[RES]]
14;
15  %subfp = sitofp i32 %x to float
16  %pow = tail call afn float @llvm.pow.f32(float 7.000000e+00, float %subfp)
17  %res = fpext float %pow to double
18  ret double %res
19}
20
21define double @pow_uitofp_const_base_fast(i31 %x) {
22; CHECK-LABEL: define double @pow_uitofp_const_base_fast(
23; CHECK-SAME: i31 [[X:%.*]]) {
24; CHECK-NEXT:    [[TMP1:%.*]] = zext i31 [[X]] to i32
25; CHECK-NEXT:    [[POW:%.*]] = tail call afn float @llvm.powi.f32.i32(float 7.000000e+00, i32 [[TMP1]])
26; CHECK-NEXT:    [[RES:%.*]] = fpext float [[POW]] to double
27; CHECK-NEXT:    ret double [[RES]]
28;
29  %subfp = uitofp i31 %x to float
30  %pow = tail call afn float @llvm.pow.f32(float 7.000000e+00, float %subfp)
31  %res = fpext float %pow to double
32  ret double %res
33}
34
35define double @pow_sitofp_double_const_base_fast(i32 %x) {
36; CHECK-LABEL: define double @pow_sitofp_double_const_base_fast(
37; CHECK-SAME: i32 [[X:%.*]]) {
38; CHECK-NEXT:    [[POW:%.*]] = tail call afn double @llvm.powi.f64.i32(double 7.000000e+00, i32 [[X]])
39; CHECK-NEXT:    ret double [[POW]]
40;
41  %subfp = sitofp i32 %x to double
42  %pow = tail call afn double @llvm.pow.f64(double 7.000000e+00, double %subfp)
43  ret double %pow
44}
45
46define double @pow_uitofp_double_const_base_fast(i31 %x) {
47; CHECK-LABEL: define double @pow_uitofp_double_const_base_fast(
48; CHECK-SAME: i31 [[X:%.*]]) {
49; CHECK-NEXT:    [[TMP1:%.*]] = zext i31 [[X]] to i32
50; CHECK-NEXT:    [[POW:%.*]] = tail call afn double @llvm.powi.f64.i32(double 7.000000e+00, i32 [[TMP1]])
51; CHECK-NEXT:    ret double [[POW]]
52;
53  %subfp = uitofp i31 %x to double
54  %pow = tail call afn double @llvm.pow.f64(double 7.000000e+00, double %subfp)
55  ret double %pow
56}
57
58define double @pow_sitofp_double_const_base_2_fast(i32 %x) {
59; CHECK-LABEL: define double @pow_sitofp_double_const_base_2_fast(
60; CHECK-SAME: i32 [[X:%.*]]) {
61; CHECK-NEXT:    [[LDEXPF:%.*]] = tail call afn float @llvm.ldexp.f32.i32(float 1.000000e+00, i32 [[X]])
62; CHECK-NEXT:    [[RES:%.*]] = fpext float [[LDEXPF]] to double
63; CHECK-NEXT:    ret double [[RES]]
64;
65  %subfp = sitofp i32 %x to float
66  %pow = tail call afn float @llvm.pow.f32(float 2.000000e+00, float %subfp)
67  %res = fpext float %pow to double
68  ret double %res
69}
70
71define double @pow_sitofp_double_const_base_power_of_2_fast(i32 %x) {
72; CHECK-LABEL: define double @pow_sitofp_double_const_base_power_of_2_fast(
73; CHECK-SAME: i32 [[X:%.*]]) {
74; CHECK-NEXT:    [[SUBFP:%.*]] = sitofp i32 [[X]] to float
75; CHECK-NEXT:    [[MUL:%.*]] = fmul afn float [[SUBFP]], 4.000000e+00
76; CHECK-NEXT:    [[EXP2:%.*]] = tail call afn float @llvm.exp2.f32(float [[MUL]])
77; CHECK-NEXT:    [[RES:%.*]] = fpext float [[EXP2]] to double
78; CHECK-NEXT:    ret double [[RES]]
79;
80  %subfp = sitofp i32 %x to float
81  %pow = tail call afn float @llvm.pow.f32(float 16.000000e+00, float %subfp)
82  %res = fpext float %pow to double
83  ret double %res
84}
85
86define double @pow_uitofp_const_base_2_fast(i31 %x) {
87; CHECK-LABEL: define double @pow_uitofp_const_base_2_fast(
88; CHECK-SAME: i31 [[X:%.*]]) {
89; CHECK-NEXT:    [[TMP1:%.*]] = zext i31 [[X]] to i32
90; CHECK-NEXT:    [[LDEXPF:%.*]] = tail call afn float @llvm.ldexp.f32.i32(float 1.000000e+00, i32 [[TMP1]])
91; CHECK-NEXT:    [[RES:%.*]] = fpext float [[LDEXPF]] to double
92; CHECK-NEXT:    ret double [[RES]]
93;
94  %subfp = uitofp i31 %x to float
95  %pow = tail call afn float @llvm.pow.f32(float 2.000000e+00, float %subfp)
96  %res = fpext float %pow to double
97  ret double %res
98}
99
100define double @pow_uitofp_const_base_power_of_2_fast(i31 %x) {
101; CHECK-LABEL: define double @pow_uitofp_const_base_power_of_2_fast(
102; CHECK-SAME: i31 [[X:%.*]]) {
103; CHECK-NEXT:    [[SUBFP:%.*]] = uitofp i31 [[X]] to float
104; CHECK-NEXT:    [[MUL:%.*]] = fmul afn float [[SUBFP]], 4.000000e+00
105; CHECK-NEXT:    [[EXP2:%.*]] = tail call afn float @llvm.exp2.f32(float [[MUL]])
106; CHECK-NEXT:    [[RES:%.*]] = fpext float [[EXP2]] to double
107; CHECK-NEXT:    ret double [[RES]]
108;
109  %subfp = uitofp i31 %x to float
110  %pow = tail call afn float @llvm.pow.f32(float 16.000000e+00, float %subfp)
111  %res = fpext float %pow to double
112  ret double %res
113}
114
115define double @pow_sitofp_float_base_fast(float %base, i32 %x) {
116; CHECK-LABEL: define double @pow_sitofp_float_base_fast(
117; CHECK-SAME: float [[BASE:%.*]], i32 [[X:%.*]]) {
118; CHECK-NEXT:    [[POW:%.*]] = tail call afn float @llvm.powi.f32.i32(float [[BASE]], i32 [[X]])
119; CHECK-NEXT:    [[RES:%.*]] = fpext float [[POW]] to double
120; CHECK-NEXT:    ret double [[RES]]
121;
122  %subfp = sitofp i32 %x to float
123  %pow = tail call afn float @llvm.pow.f32(float %base, float %subfp)
124  %res = fpext float %pow to double
125  ret double %res
126}
127
128define double @pow_uitofp_float_base_fast(float %base, i31 %x) {
129; CHECK-LABEL: define double @pow_uitofp_float_base_fast(
130; CHECK-SAME: float [[BASE:%.*]], i31 [[X:%.*]]) {
131; CHECK-NEXT:    [[TMP1:%.*]] = zext i31 [[X]] to i32
132; CHECK-NEXT:    [[POW:%.*]] = tail call afn float @llvm.powi.f32.i32(float [[BASE]], i32 [[TMP1]])
133; CHECK-NEXT:    [[RES:%.*]] = fpext float [[POW]] to double
134; CHECK-NEXT:    ret double [[RES]]
135;
136  %subfp = uitofp i31 %x to float
137  %pow = tail call afn float @llvm.pow.f32(float %base, float %subfp)
138  %res = fpext float %pow to double
139  ret double %res
140}
141
142define double @pow_sitofp_double_base_fast(double %base, i32 %x) {
143; CHECK-LABEL: define double @pow_sitofp_double_base_fast(
144; CHECK-SAME: double [[BASE:%.*]], i32 [[X:%.*]]) {
145; CHECK-NEXT:    [[RES:%.*]] = tail call afn double @llvm.powi.f64.i32(double [[BASE]], i32 [[X]])
146; CHECK-NEXT:    ret double [[RES]]
147;
148  %subfp = sitofp i32 %x to double
149  %res = tail call afn double @llvm.pow.f64(double %base, double %subfp)
150  ret double %res
151}
152
153define double @pow_uitofp_double_base_fast(double %base, i31 %x) {
154; CHECK-LABEL: define double @pow_uitofp_double_base_fast(
155; CHECK-SAME: double [[BASE:%.*]], i31 [[X:%.*]]) {
156; CHECK-NEXT:    [[TMP1:%.*]] = zext i31 [[X]] to i32
157; CHECK-NEXT:    [[RES:%.*]] = tail call afn double @llvm.powi.f64.i32(double [[BASE]], i32 [[TMP1]])
158; CHECK-NEXT:    ret double [[RES]]
159;
160  %subfp = uitofp i31 %x to double
161  %res = tail call afn double @llvm.pow.f64(double %base, double %subfp)
162  ret double %res
163}
164
165define double @pow_sitofp_const_base_fast_i8(i8 %x) {
166; CHECK-LABEL: define double @pow_sitofp_const_base_fast_i8(
167; CHECK-SAME: i8 [[X:%.*]]) {
168; CHECK-NEXT:    [[TMP1:%.*]] = sext i8 [[X]] to i32
169; CHECK-NEXT:    [[POW:%.*]] = tail call afn float @llvm.powi.f32.i32(float 7.000000e+00, i32 [[TMP1]])
170; CHECK-NEXT:    [[RES:%.*]] = fpext float [[POW]] to double
171; CHECK-NEXT:    ret double [[RES]]
172;
173  %subfp = sitofp i8 %x to float
174  %pow = tail call afn float @llvm.pow.f32(float 7.000000e+00, float %subfp)
175  %res = fpext float %pow to double
176  ret double %res
177}
178
179define double @pow_sitofp_const_base_fast_i16(i16 %x) {
180; CHECK-LABEL: define double @pow_sitofp_const_base_fast_i16(
181; CHECK-SAME: i16 [[X:%.*]]) {
182; CHECK-NEXT:    [[TMP1:%.*]] = sext i16 [[X]] to i32
183; CHECK-NEXT:    [[POW:%.*]] = tail call afn float @llvm.powi.f32.i32(float 7.000000e+00, i32 [[TMP1]])
184; CHECK-NEXT:    [[RES:%.*]] = fpext float [[POW]] to double
185; CHECK-NEXT:    ret double [[RES]]
186;
187  %subfp = sitofp i16 %x to float
188  %pow = tail call afn float @llvm.pow.f32(float 7.000000e+00, float %subfp)
189  %res = fpext float %pow to double
190  ret double %res
191}
192
193
194define double @pow_uitofp_const_base_fast_i8(i8 %x) {
195; CHECK-LABEL: define double @pow_uitofp_const_base_fast_i8(
196; CHECK-SAME: i8 [[X:%.*]]) {
197; CHECK-NEXT:    [[TMP1:%.*]] = zext i8 [[X]] to i32
198; CHECK-NEXT:    [[POW:%.*]] = tail call afn float @llvm.powi.f32.i32(float 7.000000e+00, i32 [[TMP1]])
199; CHECK-NEXT:    [[RES:%.*]] = fpext float [[POW]] to double
200; CHECK-NEXT:    ret double [[RES]]
201;
202  %subfp = uitofp i8 %x to float
203  %pow = tail call afn float @llvm.pow.f32(float 7.000000e+00, float %subfp)
204  %res = fpext float %pow to double
205  ret double %res
206}
207
208define double @pow_uitofp_const_base_fast_i16(i16 %x) {
209; CHECK-LABEL: define double @pow_uitofp_const_base_fast_i16(
210; CHECK-SAME: i16 [[X:%.*]]) {
211; CHECK-NEXT:    [[TMP1:%.*]] = zext i16 [[X]] to i32
212; CHECK-NEXT:    [[POW:%.*]] = tail call afn float @llvm.powi.f32.i32(float 7.000000e+00, i32 [[TMP1]])
213; CHECK-NEXT:    [[RES:%.*]] = fpext float [[POW]] to double
214; CHECK-NEXT:    ret double [[RES]]
215;
216  %subfp = uitofp i16 %x to float
217  %pow = tail call afn float @llvm.pow.f32(float 7.000000e+00, float %subfp)
218  %res = fpext float %pow to double
219  ret double %res
220}
221
222define double @powf_exp_const_int_fast(double %base) {
223; CHECK-LABEL: define double @powf_exp_const_int_fast(
224; CHECK-SAME: double [[BASE:%.*]]) {
225; CHECK-NEXT:    [[RES:%.*]] = tail call fast double @llvm.powi.f64.i32(double [[BASE]], i32 40)
226; CHECK-NEXT:    ret double [[RES]]
227;
228  %res = tail call fast double @llvm.pow.f64(double %base, double 4.000000e+01)
229  ret double %res
230}
231
232define double @powf_exp_const2_int_fast(double %base) {
233; CHECK-LABEL: define double @powf_exp_const2_int_fast(
234; CHECK-SAME: double [[BASE:%.*]]) {
235; CHECK-NEXT:    [[RES:%.*]] = tail call fast double @llvm.powi.f64.i32(double [[BASE]], i32 -40)
236; CHECK-NEXT:    ret double [[RES]]
237;
238  %res = tail call fast double @llvm.pow.f64(double %base, double -4.000000e+01)
239  ret double %res
240}
241
242; Negative tests
243
244define double @pow_uitofp_const_base_fast_i32(i32 %x) {
245; CHECK-LABEL: define double @pow_uitofp_const_base_fast_i32(
246; CHECK-SAME: i32 [[X:%.*]]) {
247; CHECK-NEXT:    [[SUBFP:%.*]] = uitofp i32 [[X]] to float
248; CHECK-NEXT:    [[MUL:%.*]] = fmul fast float [[SUBFP]], 0x4006757680000000
249; CHECK-NEXT:    [[EXP2:%.*]] = tail call fast float @llvm.exp2.f32(float [[MUL]])
250; CHECK-NEXT:    [[RES:%.*]] = fpext float [[EXP2]] to double
251; CHECK-NEXT:    ret double [[RES]]
252;
253  %subfp = uitofp i32 %x to float
254  %pow = tail call fast float @llvm.pow.f32(float 7.000000e+00, float %subfp)
255  %res = fpext float %pow to double
256  ret double %res
257}
258
259define double @pow_uitofp_const_base_2_fast_i32(i32 %x) {
260; CHECK-LABEL: define double @pow_uitofp_const_base_2_fast_i32(
261; CHECK-SAME: i32 [[X:%.*]]) {
262; CHECK-NEXT:    [[SUBFP:%.*]] = uitofp i32 [[X]] to float
263; CHECK-NEXT:    [[EXP2:%.*]] = tail call fast float @llvm.exp2.f32(float [[SUBFP]])
264; CHECK-NEXT:    [[RES:%.*]] = fpext float [[EXP2]] to double
265; CHECK-NEXT:    ret double [[RES]]
266;
267  %subfp = uitofp i32 %x to float
268  %pow = tail call fast float @llvm.pow.f32(float 2.000000e+00, float %subfp)
269  %res = fpext float %pow to double
270  ret double %res
271}
272
273define double @pow_uitofp_const_base_power_of_2_fast_i32(i32 %x) {
274; CHECK-LABEL: define double @pow_uitofp_const_base_power_of_2_fast_i32(
275; CHECK-SAME: i32 [[X:%.*]]) {
276; CHECK-NEXT:    [[SUBFP:%.*]] = uitofp i32 [[X]] to float
277; CHECK-NEXT:    [[MUL:%.*]] = fmul fast float [[SUBFP]], 4.000000e+00
278; CHECK-NEXT:    [[EXP2:%.*]] = tail call fast float @llvm.exp2.f32(float [[MUL]])
279; CHECK-NEXT:    [[RES:%.*]] = fpext float [[EXP2]] to double
280; CHECK-NEXT:    ret double [[RES]]
281;
282  %subfp = uitofp i32 %x to float
283  %pow = tail call fast float @llvm.pow.f32(float 16.000000e+00, float %subfp)
284  %res = fpext float %pow to double
285  ret double %res
286}
287
288define double @pow_uitofp_float_base_fast_i32(float %base, i32 %x) {
289; CHECK-LABEL: define double @pow_uitofp_float_base_fast_i32(
290; CHECK-SAME: float [[BASE:%.*]], i32 [[X:%.*]]) {
291; CHECK-NEXT:    [[SUBFP:%.*]] = uitofp i32 [[X]] to float
292; CHECK-NEXT:    [[POW:%.*]] = tail call fast float @llvm.pow.f32(float [[BASE]], float [[SUBFP]])
293; CHECK-NEXT:    [[RES:%.*]] = fpext float [[POW]] to double
294; CHECK-NEXT:    ret double [[RES]]
295;
296  %subfp = uitofp i32 %x to float
297  %pow = tail call fast float @llvm.pow.f32(float %base, float %subfp)
298  %res = fpext float %pow to double
299  ret double %res
300}
301
302define double @pow_uitofp_double_base_fast_i32(double %base, i32 %x) {
303; CHECK-LABEL: define double @pow_uitofp_double_base_fast_i32(
304; CHECK-SAME: double [[BASE:%.*]], i32 [[X:%.*]]) {
305; CHECK-NEXT:    [[SUBFP:%.*]] = uitofp i32 [[X]] to double
306; CHECK-NEXT:    [[RES:%.*]] = tail call fast double @llvm.pow.f64(double [[BASE]], double [[SUBFP]])
307; CHECK-NEXT:    ret double [[RES]]
308;
309  %subfp = uitofp i32 %x to double
310  %res = tail call fast double @llvm.pow.f64(double %base, double %subfp)
311  ret double %res
312}
313
314define double @pow_sitofp_const_base_fast_i64(i64 %x) {
315; CHECK-LABEL: define double @pow_sitofp_const_base_fast_i64(
316; CHECK-SAME: i64 [[X:%.*]]) {
317; CHECK-NEXT:    [[SUBFP:%.*]] = sitofp i64 [[X]] to float
318; CHECK-NEXT:    [[MUL:%.*]] = fmul fast float [[SUBFP]], 0x4006757680000000
319; CHECK-NEXT:    [[EXP2:%.*]] = tail call fast float @llvm.exp2.f32(float [[MUL]])
320; CHECK-NEXT:    [[RES:%.*]] = fpext float [[EXP2]] to double
321; CHECK-NEXT:    ret double [[RES]]
322;
323; Do not change 0x400675{{.*}} to the exact constant, see PR42740
324  %subfp = sitofp i64 %x to float
325  %pow = tail call fast float @llvm.pow.f32(float 7.000000e+00, float %subfp)
326  %res = fpext float %pow to double
327  ret double %res
328}
329
330define double @pow_uitofp_const_base_fast_i64(i64 %x) {
331; CHECK-LABEL: define double @pow_uitofp_const_base_fast_i64(
332; CHECK-SAME: i64 [[X:%.*]]) {
333; CHECK-NEXT:    [[SUBFP:%.*]] = uitofp i64 [[X]] to float
334; CHECK-NEXT:    [[MUL:%.*]] = fmul fast float [[SUBFP]], 0x4006757680000000
335; CHECK-NEXT:    [[EXP2:%.*]] = tail call fast float @llvm.exp2.f32(float [[MUL]])
336; CHECK-NEXT:    [[RES:%.*]] = fpext float [[EXP2]] to double
337; CHECK-NEXT:    ret double [[RES]]
338;
339  %subfp = uitofp i64 %x to float
340  %pow = tail call fast float @llvm.pow.f32(float 7.000000e+00, float %subfp)
341  %res = fpext float %pow to double
342  ret double %res
343}
344
345define double @pow_sitofp_const_base_no_fast(i32 %x) {
346; CHECK-LABEL: define double @pow_sitofp_const_base_no_fast(
347; CHECK-SAME: i32 [[X:%.*]]) {
348; CHECK-NEXT:    [[SUBFP:%.*]] = sitofp i32 [[X]] to float
349; CHECK-NEXT:    [[POW:%.*]] = tail call float @llvm.pow.f32(float 7.000000e+00, float [[SUBFP]])
350; CHECK-NEXT:    [[RES:%.*]] = fpext float [[POW]] to double
351; CHECK-NEXT:    ret double [[RES]]
352;
353  %subfp = sitofp i32 %x to float
354  %pow = tail call float @llvm.pow.f32(float 7.000000e+00, float %subfp)
355  %res = fpext float %pow to double
356  ret double %res
357}
358
359define double @pow_uitofp_const_base_no_fast(i32 %x) {
360; CHECK-LABEL: define double @pow_uitofp_const_base_no_fast(
361; CHECK-SAME: i32 [[X:%.*]]) {
362; CHECK-NEXT:    [[SUBFP:%.*]] = uitofp i32 [[X]] to float
363; CHECK-NEXT:    [[POW:%.*]] = tail call float @llvm.pow.f32(float 7.000000e+00, float [[SUBFP]])
364; CHECK-NEXT:    [[RES:%.*]] = fpext float [[POW]] to double
365; CHECK-NEXT:    ret double [[RES]]
366;
367  %subfp = uitofp i32 %x to float
368  %pow = tail call float @llvm.pow.f32(float 7.000000e+00, float %subfp)
369  %res = fpext float %pow to double
370  ret double %res
371}
372
373define double @pow_sitofp_const_base_2_no_fast(i32 %x) {
374; CHECK-LABEL: define double @pow_sitofp_const_base_2_no_fast(
375; CHECK-SAME: i32 [[X:%.*]]) {
376; CHECK-NEXT:    [[LDEXPF:%.*]] = tail call float @llvm.ldexp.f32.i32(float 1.000000e+00, i32 [[X]])
377; CHECK-NEXT:    [[RES:%.*]] = fpext float [[LDEXPF]] to double
378; CHECK-NEXT:    ret double [[RES]]
379;
380  %subfp = sitofp i32 %x to float
381  %pow = tail call float @llvm.pow.f32(float 2.000000e+00, float %subfp)
382  %res = fpext float %pow to double
383  ret double %res
384}
385
386define double @pow_sitofp_const_base_power_of_2_no_fast(i32 %x) {
387; CHECK-LABEL: define double @pow_sitofp_const_base_power_of_2_no_fast(
388; CHECK-SAME: i32 [[X:%.*]]) {
389; CHECK-NEXT:    [[SUBFP:%.*]] = sitofp i32 [[X]] to float
390; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[SUBFP]], 4.000000e+00
391; CHECK-NEXT:    [[EXP2:%.*]] = tail call float @llvm.exp2.f32(float [[MUL]])
392; CHECK-NEXT:    [[RES:%.*]] = fpext float [[EXP2]] to double
393; CHECK-NEXT:    ret double [[RES]]
394;
395  %subfp = sitofp i32 %x to float
396  %pow = tail call float @llvm.pow.f32(float 16.000000e+00, float %subfp)
397  %res = fpext float %pow to double
398  ret double %res
399}
400
401define double @pow_uitofp_const_base_2_no_fast(i32 %x) {
402; CHECK-LABEL: define double @pow_uitofp_const_base_2_no_fast(
403; CHECK-SAME: i32 [[X:%.*]]) {
404; CHECK-NEXT:    [[SUBFP:%.*]] = uitofp i32 [[X]] to float
405; CHECK-NEXT:    [[EXP2:%.*]] = tail call float @llvm.exp2.f32(float [[SUBFP]])
406; CHECK-NEXT:    [[RES:%.*]] = fpext float [[EXP2]] to double
407; CHECK-NEXT:    ret double [[RES]]
408;
409  %subfp = uitofp i32 %x to float
410  %pow = tail call float @llvm.pow.f32(float 2.000000e+00, float %subfp)
411  %res = fpext float %pow to double
412  ret double %res
413}
414
415define double @pow_uitofp_const_base_power_of_2_no_fast(i32 %x) {
416; CHECK-LABEL: define double @pow_uitofp_const_base_power_of_2_no_fast(
417; CHECK-SAME: i32 [[X:%.*]]) {
418; CHECK-NEXT:    [[SUBFP:%.*]] = uitofp i32 [[X]] to float
419; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[SUBFP]], 4.000000e+00
420; CHECK-NEXT:    [[EXP2:%.*]] = tail call float @llvm.exp2.f32(float [[MUL]])
421; CHECK-NEXT:    [[RES:%.*]] = fpext float [[EXP2]] to double
422; CHECK-NEXT:    ret double [[RES]]
423;
424  %subfp = uitofp i32 %x to float
425  %pow = tail call float @llvm.pow.f32(float 16.000000e+00, float %subfp)
426  %res = fpext float %pow to double
427  ret double %res
428}
429
430define double @pow_sitofp_float_base_no_fast(float %base, i32 %x) {
431; CHECK-LABEL: define double @pow_sitofp_float_base_no_fast(
432; CHECK-SAME: float [[BASE:%.*]], i32 [[X:%.*]]) {
433; CHECK-NEXT:    [[SUBFP:%.*]] = sitofp i32 [[X]] to float
434; CHECK-NEXT:    [[POW:%.*]] = tail call float @llvm.pow.f32(float [[BASE]], float [[SUBFP]])
435; CHECK-NEXT:    [[RES:%.*]] = fpext float [[POW]] to double
436; CHECK-NEXT:    ret double [[RES]]
437;
438  %subfp = sitofp i32 %x to float
439  %pow = tail call float @llvm.pow.f32(float %base, float %subfp)
440  %res = fpext float %pow to double
441  ret double %res
442}
443
444define double @pow_uitofp_float_base_no_fast(float %base, i32 %x) {
445; CHECK-LABEL: define double @pow_uitofp_float_base_no_fast(
446; CHECK-SAME: float [[BASE:%.*]], i32 [[X:%.*]]) {
447; CHECK-NEXT:    [[SUBFP:%.*]] = uitofp i32 [[X]] to float
448; CHECK-NEXT:    [[POW:%.*]] = tail call float @llvm.pow.f32(float [[BASE]], float [[SUBFP]])
449; CHECK-NEXT:    [[RES:%.*]] = fpext float [[POW]] to double
450; CHECK-NEXT:    ret double [[RES]]
451;
452  %subfp = uitofp i32 %x to float
453  %pow = tail call float @llvm.pow.f32(float %base, float %subfp)
454  %res = fpext float %pow to double
455  ret double %res
456}
457
458define double @pow_sitofp_double_base_no_fast(double %base, i32 %x) {
459; CHECK-LABEL: define double @pow_sitofp_double_base_no_fast(
460; CHECK-SAME: double [[BASE:%.*]], i32 [[X:%.*]]) {
461; CHECK-NEXT:    [[SUBFP:%.*]] = sitofp i32 [[X]] to double
462; CHECK-NEXT:    [[POW:%.*]] = tail call double @llvm.pow.f64(double [[BASE]], double [[SUBFP]])
463; CHECK-NEXT:    ret double [[POW]]
464;
465  %subfp = sitofp i32 %x to double
466  %pow = tail call double @llvm.pow.f64(double %base, double %subfp)
467  ret double %pow
468}
469
470define double @pow_uitofp_double_base_no_fast(double %base, i32 %x) {
471; CHECK-LABEL: define double @pow_uitofp_double_base_no_fast(
472; CHECK-SAME: double [[BASE:%.*]], i32 [[X:%.*]]) {
473; CHECK-NEXT:    [[SUBFP:%.*]] = uitofp i32 [[X]] to double
474; CHECK-NEXT:    [[POW:%.*]] = tail call double @llvm.pow.f64(double [[BASE]], double [[SUBFP]])
475; CHECK-NEXT:    ret double [[POW]]
476;
477  %subfp = uitofp i32 %x to double
478  %pow = tail call double @llvm.pow.f64(double %base, double %subfp)
479  ret double %pow
480}
481
482; negative test - pow with no FMF is not the same as the loosely-specified powi
483
484define double @powf_exp_const_int_no_fast(double %base) {
485; CHECK-LABEL: define double @powf_exp_const_int_no_fast(
486; CHECK-SAME: double [[BASE:%.*]]) {
487; CHECK-NEXT:    [[RES:%.*]] = tail call double @llvm.pow.f64(double [[BASE]], double 4.000000e+01)
488; CHECK-NEXT:    ret double [[RES]]
489;
490  %res = tail call double @llvm.pow.f64(double %base, double 4.000000e+01)
491  ret double %res
492}
493
494define double @powf_exp_const_not_int_fast(double %base) {
495; CHECK-LABEL: define double @powf_exp_const_not_int_fast(
496; CHECK-SAME: double [[BASE:%.*]]) {
497; CHECK-NEXT:    [[SQRT:%.*]] = call fast double @llvm.sqrt.f64(double [[BASE]])
498; CHECK-NEXT:    [[TMP1:%.*]] = tail call fast double @llvm.powi.f64.i32(double [[BASE]], i32 37)
499; CHECK-NEXT:    [[RES:%.*]] = fmul fast double [[TMP1]], [[SQRT]]
500; CHECK-NEXT:    ret double [[RES]]
501;
502  %res = tail call fast double @llvm.pow.f64(double %base, double 3.750000e+01)
503  ret double %res
504}
505
506define double @powf_exp_const_not_int_no_fast(double %base) {
507; CHECK-LABEL: define double @powf_exp_const_not_int_no_fast(
508; CHECK-SAME: double [[BASE:%.*]]) {
509; CHECK-NEXT:    [[RES:%.*]] = tail call double @llvm.pow.f64(double [[BASE]], double 3.750000e+01)
510; CHECK-NEXT:    ret double [[RES]]
511;
512  %res = tail call double @llvm.pow.f64(double %base, double 3.750000e+01)
513  ret double %res
514}
515
516; negative test - pow with no FMF is not the same as the loosely-specified powi
517
518define double @powf_exp_const2_int_no_fast(double %base) {
519; CHECK-LABEL: define double @powf_exp_const2_int_no_fast(
520; CHECK-SAME: double [[BASE:%.*]]) {
521; CHECK-NEXT:    [[RES:%.*]] = tail call double @llvm.pow.f64(double [[BASE]], double -4.000000e+01)
522; CHECK-NEXT:    ret double [[RES]]
523;
524  %res = tail call double @llvm.pow.f64(double %base, double -4.000000e+01)
525  ret double %res
526}
527
528; TODO: This could be transformed the same as scalar if there is an ldexp intrinsic.
529
530define <2 x float> @pow_sitofp_const_base_2_no_fast_vector(<2 x i8> %x) {
531; CHECK-LABEL: define <2 x float> @pow_sitofp_const_base_2_no_fast_vector(
532; CHECK-SAME: <2 x i8> [[X:%.*]]) {
533; CHECK-NEXT:    [[TMP1:%.*]] = sext <2 x i8> [[X]] to <2 x i32>
534; CHECK-NEXT:    [[EXP2:%.*]] = call <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> splat (float 1.000000e+00), <2 x i32> [[TMP1]])
535; CHECK-NEXT:    ret <2 x float> [[EXP2]]
536;
537  %s = sitofp <2 x i8> %x to <2 x float>
538  %r = call <2 x float> @llvm.pow.v2f32(<2 x float><float 2.0, float 2.0>, <2 x float> %s)
539  ret <2 x float> %r
540}
541
542declare float @llvm.pow.f32(float, float)
543declare double @llvm.pow.f64(double, double)
544declare <2 x float> @llvm.pow.v2f32(<2 x float>, <2 x float>)
545