1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc -mtriple=riscv32 -mattr=+f -verify-machineinstrs < %s \
3; RUN:   | FileCheck -check-prefix=RV32IF %s
4; RUN: llc -mtriple=riscv32 -mattr=+d -verify-machineinstrs < %s \
5; RUN:   | FileCheck -check-prefix=RV32IF %s
6
7declare float @llvm.sqrt.f32(float)
8
9define float @sqrt_f32(float %a) nounwind {
10; RV32IF-LABEL: sqrt_f32:
11; RV32IF:       # %bb.0:
12; RV32IF-NEXT:    fmv.w.x ft0, a0
13; RV32IF-NEXT:    fsqrt.s ft0, ft0
14; RV32IF-NEXT:    fmv.x.w a0, ft0
15; RV32IF-NEXT:    ret
16  %1 = call float @llvm.sqrt.f32(float %a)
17  ret float %1
18}
19
20declare float @llvm.powi.f32(float, i32)
21
22define float @powi_f32(float %a, i32 %b) nounwind {
23; RV32IF-LABEL: powi_f32:
24; RV32IF:       # %bb.0:
25; RV32IF-NEXT:    addi sp, sp, -16
26; RV32IF-NEXT:    sw ra, 12(sp)
27; RV32IF-NEXT:    call __powisf2
28; RV32IF-NEXT:    lw ra, 12(sp)
29; RV32IF-NEXT:    addi sp, sp, 16
30; RV32IF-NEXT:    ret
31  %1 = call float @llvm.powi.f32(float %a, i32 %b)
32  ret float %1
33}
34
35declare float @llvm.sin.f32(float)
36
37define float @sin_f32(float %a) nounwind {
38; RV32IF-LABEL: sin_f32:
39; RV32IF:       # %bb.0:
40; RV32IF-NEXT:    addi sp, sp, -16
41; RV32IF-NEXT:    sw ra, 12(sp)
42; RV32IF-NEXT:    call sinf
43; RV32IF-NEXT:    lw ra, 12(sp)
44; RV32IF-NEXT:    addi sp, sp, 16
45; RV32IF-NEXT:    ret
46  %1 = call float @llvm.sin.f32(float %a)
47  ret float %1
48}
49
50declare float @llvm.cos.f32(float)
51
52define float @cos_f32(float %a) nounwind {
53; RV32IF-LABEL: cos_f32:
54; RV32IF:       # %bb.0:
55; RV32IF-NEXT:    addi sp, sp, -16
56; RV32IF-NEXT:    sw ra, 12(sp)
57; RV32IF-NEXT:    call cosf
58; RV32IF-NEXT:    lw ra, 12(sp)
59; RV32IF-NEXT:    addi sp, sp, 16
60; RV32IF-NEXT:    ret
61  %1 = call float @llvm.cos.f32(float %a)
62  ret float %1
63}
64
65; The sin+cos combination results in an FSINCOS SelectionDAG node.
66define float @sincos_f32(float %a) nounwind {
67; RV32IF-LABEL: sincos_f32:
68; RV32IF:       # %bb.0:
69; RV32IF-NEXT:    addi sp, sp, -16
70; RV32IF-NEXT:    sw ra, 12(sp)
71; RV32IF-NEXT:    sw s1, 8(sp)
72; RV32IF-NEXT:    sw s2, 4(sp)
73; RV32IF-NEXT:    mv s1, a0
74; RV32IF-NEXT:    call sinf
75; RV32IF-NEXT:    mv s2, a0
76; RV32IF-NEXT:    mv a0, s1
77; RV32IF-NEXT:    call cosf
78; RV32IF-NEXT:    fmv.w.x ft0, a0
79; RV32IF-NEXT:    fmv.w.x ft1, s2
80; RV32IF-NEXT:    fadd.s ft0, ft1, ft0
81; RV32IF-NEXT:    fmv.x.w a0, ft0
82; RV32IF-NEXT:    lw s2, 4(sp)
83; RV32IF-NEXT:    lw s1, 8(sp)
84; RV32IF-NEXT:    lw ra, 12(sp)
85; RV32IF-NEXT:    addi sp, sp, 16
86; RV32IF-NEXT:    ret
87  %1 = call float @llvm.sin.f32(float %a)
88  %2 = call float @llvm.cos.f32(float %a)
89  %3 = fadd float %1, %2
90  ret float %3
91}
92
93declare float @llvm.pow.f32(float, float)
94
95define float @pow_f32(float %a, float %b) nounwind {
96; RV32IF-LABEL: pow_f32:
97; RV32IF:       # %bb.0:
98; RV32IF-NEXT:    addi sp, sp, -16
99; RV32IF-NEXT:    sw ra, 12(sp)
100; RV32IF-NEXT:    call powf
101; RV32IF-NEXT:    lw ra, 12(sp)
102; RV32IF-NEXT:    addi sp, sp, 16
103; RV32IF-NEXT:    ret
104  %1 = call float @llvm.pow.f32(float %a, float %b)
105  ret float %1
106}
107
108declare float @llvm.exp.f32(float)
109
110define float @exp_f32(float %a) nounwind {
111; RV32IF-LABEL: exp_f32:
112; RV32IF:       # %bb.0:
113; RV32IF-NEXT:    addi sp, sp, -16
114; RV32IF-NEXT:    sw ra, 12(sp)
115; RV32IF-NEXT:    call expf
116; RV32IF-NEXT:    lw ra, 12(sp)
117; RV32IF-NEXT:    addi sp, sp, 16
118; RV32IF-NEXT:    ret
119  %1 = call float @llvm.exp.f32(float %a)
120  ret float %1
121}
122
123declare float @llvm.exp2.f32(float)
124
125define float @exp2_f32(float %a) nounwind {
126; RV32IF-LABEL: exp2_f32:
127; RV32IF:       # %bb.0:
128; RV32IF-NEXT:    addi sp, sp, -16
129; RV32IF-NEXT:    sw ra, 12(sp)
130; RV32IF-NEXT:    call exp2f
131; RV32IF-NEXT:    lw ra, 12(sp)
132; RV32IF-NEXT:    addi sp, sp, 16
133; RV32IF-NEXT:    ret
134  %1 = call float @llvm.exp2.f32(float %a)
135  ret float %1
136}
137
138declare float @llvm.log.f32(float)
139
140define float @log_f32(float %a) nounwind {
141; RV32IF-LABEL: log_f32:
142; RV32IF:       # %bb.0:
143; RV32IF-NEXT:    addi sp, sp, -16
144; RV32IF-NEXT:    sw ra, 12(sp)
145; RV32IF-NEXT:    call logf
146; RV32IF-NEXT:    lw ra, 12(sp)
147; RV32IF-NEXT:    addi sp, sp, 16
148; RV32IF-NEXT:    ret
149  %1 = call float @llvm.log.f32(float %a)
150  ret float %1
151}
152
153declare float @llvm.log10.f32(float)
154
155define float @log10_f32(float %a) nounwind {
156; RV32IF-LABEL: log10_f32:
157; RV32IF:       # %bb.0:
158; RV32IF-NEXT:    addi sp, sp, -16
159; RV32IF-NEXT:    sw ra, 12(sp)
160; RV32IF-NEXT:    call log10f
161; RV32IF-NEXT:    lw ra, 12(sp)
162; RV32IF-NEXT:    addi sp, sp, 16
163; RV32IF-NEXT:    ret
164  %1 = call float @llvm.log10.f32(float %a)
165  ret float %1
166}
167
168declare float @llvm.log2.f32(float)
169
170define float @log2_f32(float %a) nounwind {
171; RV32IF-LABEL: log2_f32:
172; RV32IF:       # %bb.0:
173; RV32IF-NEXT:    addi sp, sp, -16
174; RV32IF-NEXT:    sw ra, 12(sp)
175; RV32IF-NEXT:    call log2f
176; RV32IF-NEXT:    lw ra, 12(sp)
177; RV32IF-NEXT:    addi sp, sp, 16
178; RV32IF-NEXT:    ret
179  %1 = call float @llvm.log2.f32(float %a)
180  ret float %1
181}
182
183declare float @llvm.fma.f32(float, float, float)
184
185define float @fma_f32(float %a, float %b, float %c) nounwind {
186; RV32IF-LABEL: fma_f32:
187; RV32IF:       # %bb.0:
188; RV32IF-NEXT:    fmv.w.x ft0, a2
189; RV32IF-NEXT:    fmv.w.x ft1, a1
190; RV32IF-NEXT:    fmv.w.x ft2, a0
191; RV32IF-NEXT:    fmadd.s ft0, ft2, ft1, ft0
192; RV32IF-NEXT:    fmv.x.w a0, ft0
193; RV32IF-NEXT:    ret
194  %1 = call float @llvm.fma.f32(float %a, float %b, float %c)
195  ret float %1
196}
197
198declare float @llvm.fmuladd.f32(float, float, float)
199
200define float @fmuladd_f32(float %a, float %b, float %c) nounwind {
201; Use of fmadd depends on TargetLowering::isFMAFasterthanFMulAndFAdd
202; RV32IF-LABEL: fmuladd_f32:
203; RV32IF:       # %bb.0:
204; RV32IF-NEXT:    fmv.w.x ft0, a1
205; RV32IF-NEXT:    fmv.w.x ft1, a0
206; RV32IF-NEXT:    fmul.s ft0, ft1, ft0
207; RV32IF-NEXT:    fmv.w.x ft1, a2
208; RV32IF-NEXT:    fadd.s ft0, ft0, ft1
209; RV32IF-NEXT:    fmv.x.w a0, ft0
210; RV32IF-NEXT:    ret
211  %1 = call float @llvm.fmuladd.f32(float %a, float %b, float %c)
212  ret float %1
213}
214
215declare float @llvm.fabs.f32(float)
216
217define float @fabs_f32(float %a) nounwind {
218; RV32IF-LABEL: fabs_f32:
219; RV32IF:       # %bb.0:
220; RV32IF-NEXT:    lui a1, 524288
221; RV32IF-NEXT:    addi a1, a1, -1
222; RV32IF-NEXT:    and a0, a0, a1
223; RV32IF-NEXT:    ret
224  %1 = call float @llvm.fabs.f32(float %a)
225  ret float %1
226}
227
228declare float @llvm.minnum.f32(float, float)
229
230define float @minnum_f32(float %a, float %b) nounwind {
231; RV32IF-LABEL: minnum_f32:
232; RV32IF:       # %bb.0:
233; RV32IF-NEXT:    fmv.w.x ft0, a1
234; RV32IF-NEXT:    fmv.w.x ft1, a0
235; RV32IF-NEXT:    fmin.s ft0, ft1, ft0
236; RV32IF-NEXT:    fmv.x.w a0, ft0
237; RV32IF-NEXT:    ret
238  %1 = call float @llvm.minnum.f32(float %a, float %b)
239  ret float %1
240}
241
242declare float @llvm.maxnum.f32(float, float)
243
244define float @maxnum_f32(float %a, float %b) nounwind {
245; RV32IF-LABEL: maxnum_f32:
246; RV32IF:       # %bb.0:
247; RV32IF-NEXT:    fmv.w.x ft0, a1
248; RV32IF-NEXT:    fmv.w.x ft1, a0
249; RV32IF-NEXT:    fmax.s ft0, ft1, ft0
250; RV32IF-NEXT:    fmv.x.w a0, ft0
251; RV32IF-NEXT:    ret
252  %1 = call float @llvm.maxnum.f32(float %a, float %b)
253  ret float %1
254}
255
256; TODO: FMINNAN and FMAXNAN aren't handled in
257; SelectionDAGLegalize::ExpandNode.
258
259; declare float @llvm.minimum.f32(float, float)
260
261; define float @fminimum_f32(float %a, float %b) nounwind {
262;   %1 = call float @llvm.minimum.f32(float %a, float %b)
263;   ret float %1
264; }
265
266; declare float @llvm.maximum.f32(float, float)
267
268; define float @fmaximum_f32(float %a, float %b) nounwind {
269;   %1 = call float @llvm.maximum.f32(float %a, float %b)
270;   ret float %1
271; }
272
273declare float @llvm.copysign.f32(float, float)
274
275define float @copysign_f32(float %a, float %b) nounwind {
276; RV32IF-LABEL: copysign_f32:
277; RV32IF:       # %bb.0:
278; RV32IF-NEXT:    fmv.w.x ft0, a1
279; RV32IF-NEXT:    fmv.w.x ft1, a0
280; RV32IF-NEXT:    fsgnj.s ft0, ft1, ft0
281; RV32IF-NEXT:    fmv.x.w a0, ft0
282; RV32IF-NEXT:    ret
283  %1 = call float @llvm.copysign.f32(float %a, float %b)
284  ret float %1
285}
286
287declare float @llvm.floor.f32(float)
288
289define float @floor_f32(float %a) nounwind {
290; RV32IF-LABEL: floor_f32:
291; RV32IF:       # %bb.0:
292; RV32IF-NEXT:    addi sp, sp, -16
293; RV32IF-NEXT:    sw ra, 12(sp)
294; RV32IF-NEXT:    call floorf
295; RV32IF-NEXT:    lw ra, 12(sp)
296; RV32IF-NEXT:    addi sp, sp, 16
297; RV32IF-NEXT:    ret
298  %1 = call float @llvm.floor.f32(float %a)
299  ret float %1
300}
301
302declare float @llvm.ceil.f32(float)
303
304define float @ceil_f32(float %a) nounwind {
305; RV32IF-LABEL: ceil_f32:
306; RV32IF:       # %bb.0:
307; RV32IF-NEXT:    addi sp, sp, -16
308; RV32IF-NEXT:    sw ra, 12(sp)
309; RV32IF-NEXT:    call ceilf
310; RV32IF-NEXT:    lw ra, 12(sp)
311; RV32IF-NEXT:    addi sp, sp, 16
312; RV32IF-NEXT:    ret
313  %1 = call float @llvm.ceil.f32(float %a)
314  ret float %1
315}
316
317declare float @llvm.trunc.f32(float)
318
319define float @trunc_f32(float %a) nounwind {
320; RV32IF-LABEL: trunc_f32:
321; RV32IF:       # %bb.0:
322; RV32IF-NEXT:    addi sp, sp, -16
323; RV32IF-NEXT:    sw ra, 12(sp)
324; RV32IF-NEXT:    call truncf
325; RV32IF-NEXT:    lw ra, 12(sp)
326; RV32IF-NEXT:    addi sp, sp, 16
327; RV32IF-NEXT:    ret
328  %1 = call float @llvm.trunc.f32(float %a)
329  ret float %1
330}
331
332declare float @llvm.rint.f32(float)
333
334define float @rint_f32(float %a) nounwind {
335; RV32IF-LABEL: rint_f32:
336; RV32IF:       # %bb.0:
337; RV32IF-NEXT:    addi sp, sp, -16
338; RV32IF-NEXT:    sw ra, 12(sp)
339; RV32IF-NEXT:    call rintf
340; RV32IF-NEXT:    lw ra, 12(sp)
341; RV32IF-NEXT:    addi sp, sp, 16
342; RV32IF-NEXT:    ret
343  %1 = call float @llvm.rint.f32(float %a)
344  ret float %1
345}
346
347declare float @llvm.nearbyint.f32(float)
348
349define float @nearbyint_f32(float %a) nounwind {
350; RV32IF-LABEL: nearbyint_f32:
351; RV32IF:       # %bb.0:
352; RV32IF-NEXT:    addi sp, sp, -16
353; RV32IF-NEXT:    sw ra, 12(sp)
354; RV32IF-NEXT:    call nearbyintf
355; RV32IF-NEXT:    lw ra, 12(sp)
356; RV32IF-NEXT:    addi sp, sp, 16
357; RV32IF-NEXT:    ret
358  %1 = call float @llvm.nearbyint.f32(float %a)
359  ret float %1
360}
361
362declare float @llvm.round.f32(float)
363
364define float @round_f32(float %a) nounwind {
365; RV32IF-LABEL: round_f32:
366; RV32IF:       # %bb.0:
367; RV32IF-NEXT:    addi sp, sp, -16
368; RV32IF-NEXT:    sw ra, 12(sp)
369; RV32IF-NEXT:    call roundf
370; RV32IF-NEXT:    lw ra, 12(sp)
371; RV32IF-NEXT:    addi sp, sp, 16
372; RV32IF-NEXT:    ret
373  %1 = call float @llvm.round.f32(float %a)
374  ret float %1
375}
376