xref: /llvm-project/llvm/test/CodeGen/RISCV/half-arith-strict.ll (revision 9122c5235ec85ce0c0ad337e862b006e7b349d84)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc -mtriple=riscv32 -mattr=+zfh -verify-machineinstrs \
3; RUN:   -disable-strictnode-mutation -target-abi ilp32f < %s | FileCheck %s
4; RUN: llc -mtriple=riscv64 -mattr=+zfh -verify-machineinstrs \
5; RUN:   -disable-strictnode-mutation -target-abi lp64f < %s | FileCheck %s
6; RUN: llc -mtriple=riscv32 -mattr=+zhinx -verify-machineinstrs \
7; RUN:   -disable-strictnode-mutation -target-abi ilp32 < %s \
8; RUN:   | FileCheck -check-prefix=CHECK-ZHINX %s
9; RUN: llc -mtriple=riscv64 -mattr=+zhinx -verify-machineinstrs \
10; RUN:   -disable-strictnode-mutation -target-abi lp64 < %s \
11; RUN:   | FileCheck -check-prefix=CHECK-ZHINX %s
12; RUN: llc -mtriple=riscv32 -mattr=+zfhmin -verify-machineinstrs \
13; RUN:   -disable-strictnode-mutation -target-abi ilp32f < %s \
14; RUN:   | FileCheck -check-prefixes=CHECK-ZFHMIN,CHECK-ZFHMIN-RV32 %s
15; RUN: llc -mtriple=riscv64 -mattr=+zfhmin -verify-machineinstrs \
16; RUN:   -disable-strictnode-mutation -target-abi lp64f < %s \
17; RUN:  | FileCheck -check-prefixes=CHECK-ZFHMIN,CHECK-ZFHMIN-RV64 %s
18; RUN: llc -mtriple=riscv32 -mattr=+zhinxmin -verify-machineinstrs \
19; RUN:   -disable-strictnode-mutation -target-abi ilp32 < %s \
20; RUN:   | FileCheck -check-prefixes=CHECK-ZHINXMIN,CHECK-ZHINXMIN-RV32 %s
21; RUN: llc -mtriple=riscv64 -mattr=+zhinxmin -verify-machineinstrs \
22; RUN:   -disable-strictnode-mutation -target-abi lp64 < %s \
23; RUN:   | FileCheck -check-prefixes=CHECK-ZHINXMIN,CHECK-ZHINXMIN-RV64 %s
24
25; FIXME: We can't test without Zfh because soft promote legalization isn't
26; implemented in SelectionDAG for STRICT nodes.
27
28define half @fadd_h(half %a, half %b) nounwind strictfp {
29; CHECK-LABEL: fadd_h:
30; CHECK:       # %bb.0:
31; CHECK-NEXT:    fadd.h fa0, fa0, fa1
32; CHECK-NEXT:    ret
33;
34; CHECK-ZHINX-LABEL: fadd_h:
35; CHECK-ZHINX:       # %bb.0:
36; CHECK-ZHINX-NEXT:    fadd.h a0, a0, a1
37; CHECK-ZHINX-NEXT:    ret
38;
39; CHECK-ZFHMIN-LABEL: fadd_h:
40; CHECK-ZFHMIN:       # %bb.0:
41; CHECK-ZFHMIN-NEXT:    fcvt.s.h fa5, fa1
42; CHECK-ZFHMIN-NEXT:    fcvt.s.h fa4, fa0
43; CHECK-ZFHMIN-NEXT:    fadd.s fa5, fa4, fa5
44; CHECK-ZFHMIN-NEXT:    fcvt.h.s fa0, fa5
45; CHECK-ZFHMIN-NEXT:    ret
46;
47; CHECK-ZHINXMIN-LABEL: fadd_h:
48; CHECK-ZHINXMIN:       # %bb.0:
49; CHECK-ZHINXMIN-NEXT:    fcvt.s.h a1, a1
50; CHECK-ZHINXMIN-NEXT:    fcvt.s.h a0, a0
51; CHECK-ZHINXMIN-NEXT:    fadd.s a0, a0, a1
52; CHECK-ZHINXMIN-NEXT:    fcvt.h.s a0, a0
53; CHECK-ZHINXMIN-NEXT:    ret
54  %1 = call half @llvm.experimental.constrained.fadd.f16(half %a, half %b, metadata !"round.dynamic", metadata !"fpexcept.strict") strictfp
55  ret half %1
56}
57declare half @llvm.experimental.constrained.fadd.f16(half, half, metadata, metadata)
58
59define half @fsub_h(half %a, half %b) nounwind strictfp {
60; CHECK-LABEL: fsub_h:
61; CHECK:       # %bb.0:
62; CHECK-NEXT:    fsub.h fa0, fa0, fa1
63; CHECK-NEXT:    ret
64;
65; CHECK-ZHINX-LABEL: fsub_h:
66; CHECK-ZHINX:       # %bb.0:
67; CHECK-ZHINX-NEXT:    fsub.h a0, a0, a1
68; CHECK-ZHINX-NEXT:    ret
69;
70; CHECK-ZFHMIN-LABEL: fsub_h:
71; CHECK-ZFHMIN:       # %bb.0:
72; CHECK-ZFHMIN-NEXT:    fcvt.s.h fa5, fa1
73; CHECK-ZFHMIN-NEXT:    fcvt.s.h fa4, fa0
74; CHECK-ZFHMIN-NEXT:    fsub.s fa5, fa4, fa5
75; CHECK-ZFHMIN-NEXT:    fcvt.h.s fa0, fa5
76; CHECK-ZFHMIN-NEXT:    ret
77;
78; CHECK-ZHINXMIN-LABEL: fsub_h:
79; CHECK-ZHINXMIN:       # %bb.0:
80; CHECK-ZHINXMIN-NEXT:    fcvt.s.h a1, a1
81; CHECK-ZHINXMIN-NEXT:    fcvt.s.h a0, a0
82; CHECK-ZHINXMIN-NEXT:    fsub.s a0, a0, a1
83; CHECK-ZHINXMIN-NEXT:    fcvt.h.s a0, a0
84; CHECK-ZHINXMIN-NEXT:    ret
85  %1 = call half @llvm.experimental.constrained.fsub.f16(half %a, half %b, metadata !"round.dynamic", metadata !"fpexcept.strict") strictfp
86  ret half %1
87}
88declare half @llvm.experimental.constrained.fsub.f16(half, half, metadata, metadata)
89
90define half @fmul_h(half %a, half %b) nounwind strictfp {
91; CHECK-LABEL: fmul_h:
92; CHECK:       # %bb.0:
93; CHECK-NEXT:    fmul.h fa0, fa0, fa1
94; CHECK-NEXT:    ret
95;
96; CHECK-ZHINX-LABEL: fmul_h:
97; CHECK-ZHINX:       # %bb.0:
98; CHECK-ZHINX-NEXT:    fmul.h a0, a0, a1
99; CHECK-ZHINX-NEXT:    ret
100;
101; CHECK-ZFHMIN-LABEL: fmul_h:
102; CHECK-ZFHMIN:       # %bb.0:
103; CHECK-ZFHMIN-NEXT:    fcvt.s.h fa5, fa1
104; CHECK-ZFHMIN-NEXT:    fcvt.s.h fa4, fa0
105; CHECK-ZFHMIN-NEXT:    fmul.s fa5, fa4, fa5
106; CHECK-ZFHMIN-NEXT:    fcvt.h.s fa0, fa5
107; CHECK-ZFHMIN-NEXT:    ret
108;
109; CHECK-ZHINXMIN-LABEL: fmul_h:
110; CHECK-ZHINXMIN:       # %bb.0:
111; CHECK-ZHINXMIN-NEXT:    fcvt.s.h a1, a1
112; CHECK-ZHINXMIN-NEXT:    fcvt.s.h a0, a0
113; CHECK-ZHINXMIN-NEXT:    fmul.s a0, a0, a1
114; CHECK-ZHINXMIN-NEXT:    fcvt.h.s a0, a0
115; CHECK-ZHINXMIN-NEXT:    ret
116  %1 = call half @llvm.experimental.constrained.fmul.f16(half %a, half %b, metadata !"round.dynamic", metadata !"fpexcept.strict") strictfp
117  ret half %1
118}
119declare half @llvm.experimental.constrained.fmul.f16(half, half, metadata, metadata)
120
121define half @fdiv_h(half %a, half %b) nounwind strictfp {
122; CHECK-LABEL: fdiv_h:
123; CHECK:       # %bb.0:
124; CHECK-NEXT:    fdiv.h fa0, fa0, fa1
125; CHECK-NEXT:    ret
126;
127; CHECK-ZHINX-LABEL: fdiv_h:
128; CHECK-ZHINX:       # %bb.0:
129; CHECK-ZHINX-NEXT:    fdiv.h a0, a0, a1
130; CHECK-ZHINX-NEXT:    ret
131;
132; CHECK-ZFHMIN-LABEL: fdiv_h:
133; CHECK-ZFHMIN:       # %bb.0:
134; CHECK-ZFHMIN-NEXT:    fcvt.s.h fa5, fa1
135; CHECK-ZFHMIN-NEXT:    fcvt.s.h fa4, fa0
136; CHECK-ZFHMIN-NEXT:    fdiv.s fa5, fa4, fa5
137; CHECK-ZFHMIN-NEXT:    fcvt.h.s fa0, fa5
138; CHECK-ZFHMIN-NEXT:    ret
139;
140; CHECK-ZHINXMIN-LABEL: fdiv_h:
141; CHECK-ZHINXMIN:       # %bb.0:
142; CHECK-ZHINXMIN-NEXT:    fcvt.s.h a1, a1
143; CHECK-ZHINXMIN-NEXT:    fcvt.s.h a0, a0
144; CHECK-ZHINXMIN-NEXT:    fdiv.s a0, a0, a1
145; CHECK-ZHINXMIN-NEXT:    fcvt.h.s a0, a0
146; CHECK-ZHINXMIN-NEXT:    ret
147  %1 = call half @llvm.experimental.constrained.fdiv.f16(half %a, half %b, metadata !"round.dynamic", metadata !"fpexcept.strict") strictfp
148  ret half %1
149}
150declare half @llvm.experimental.constrained.fdiv.f16(half, half, metadata, metadata)
151
152define half @fsqrt_h(half %a) nounwind strictfp {
153; CHECK-LABEL: fsqrt_h:
154; CHECK:       # %bb.0:
155; CHECK-NEXT:    fsqrt.h fa0, fa0
156; CHECK-NEXT:    ret
157;
158; CHECK-ZHINX-LABEL: fsqrt_h:
159; CHECK-ZHINX:       # %bb.0:
160; CHECK-ZHINX-NEXT:    fsqrt.h a0, a0
161; CHECK-ZHINX-NEXT:    ret
162;
163; CHECK-ZFHMIN-LABEL: fsqrt_h:
164; CHECK-ZFHMIN:       # %bb.0:
165; CHECK-ZFHMIN-NEXT:    fcvt.s.h fa5, fa0
166; CHECK-ZFHMIN-NEXT:    fsqrt.s fa5, fa5
167; CHECK-ZFHMIN-NEXT:    fcvt.h.s fa0, fa5
168; CHECK-ZFHMIN-NEXT:    ret
169;
170; CHECK-ZHINXMIN-LABEL: fsqrt_h:
171; CHECK-ZHINXMIN:       # %bb.0:
172; CHECK-ZHINXMIN-NEXT:    fcvt.s.h a0, a0
173; CHECK-ZHINXMIN-NEXT:    fsqrt.s a0, a0
174; CHECK-ZHINXMIN-NEXT:    fcvt.h.s a0, a0
175; CHECK-ZHINXMIN-NEXT:    ret
176  %1 = call half @llvm.experimental.constrained.sqrt.f16(half %a, metadata !"round.dynamic", metadata !"fpexcept.strict") strictfp
177  ret half %1
178}
179declare half @llvm.experimental.constrained.sqrt.f16(half, metadata, metadata)
180
181; FIXME: fminnum/fmaxnum need libcalls to handle SNaN, but we don't have f16
182; libcalls and don't support promotion yet.
183;define half @fmin_h(half %a, half %b) nounwind strictfp {
184;  %1 = call half @llvm.experimental.constrained.minnum.f16(half %a, half %b, metadata !"fpexcept.strict") strictfp
185;  ret half %1
186;}
187;declare half @llvm.experimental.constrained.minnum.f16(half, half, metadata) strictfp
188;
189;define half @fmax_h(half %a, half %b) nounwind strictfp {
190;  %1 = call half @llvm.experimental.constrained.maxnum.f16(half %a, half %b, metadata !"fpexcept.strict") strictfp
191;  ret half %1
192;}
193;declare half @llvm.experimental.constrained.maxnum.f16(half, half, metadata) strictfp
194
195define half @fmadd_h(half %a, half %b, half %c) nounwind strictfp {
196; CHECK-LABEL: fmadd_h:
197; CHECK:       # %bb.0:
198; CHECK-NEXT:    fmadd.h fa0, fa0, fa1, fa2
199; CHECK-NEXT:    ret
200;
201; CHECK-ZHINX-LABEL: fmadd_h:
202; CHECK-ZHINX:       # %bb.0:
203; CHECK-ZHINX-NEXT:    fmadd.h a0, a0, a1, a2
204; CHECK-ZHINX-NEXT:    ret
205;
206; CHECK-ZFHMIN-LABEL: fmadd_h:
207; CHECK-ZFHMIN:       # %bb.0:
208; CHECK-ZFHMIN-NEXT:    fcvt.s.h fa5, fa2
209; CHECK-ZFHMIN-NEXT:    fcvt.s.h fa4, fa1
210; CHECK-ZFHMIN-NEXT:    fcvt.s.h fa3, fa0
211; CHECK-ZFHMIN-NEXT:    fmadd.s fa5, fa3, fa4, fa5
212; CHECK-ZFHMIN-NEXT:    fcvt.h.s fa0, fa5
213; CHECK-ZFHMIN-NEXT:    ret
214;
215; CHECK-ZHINXMIN-LABEL: fmadd_h:
216; CHECK-ZHINXMIN:       # %bb.0:
217; CHECK-ZHINXMIN-NEXT:    fcvt.s.h a2, a2
218; CHECK-ZHINXMIN-NEXT:    fcvt.s.h a1, a1
219; CHECK-ZHINXMIN-NEXT:    fcvt.s.h a0, a0
220; CHECK-ZHINXMIN-NEXT:    fmadd.s a0, a0, a1, a2
221; CHECK-ZHINXMIN-NEXT:    fcvt.h.s a0, a0
222; CHECK-ZHINXMIN-NEXT:    ret
223  %1 = call half @llvm.experimental.constrained.fma.f16(half %a, half %b, half %c, metadata !"round.dynamic", metadata !"fpexcept.strict") strictfp
224  ret half %1
225}
226declare half @llvm.experimental.constrained.fma.f16(half, half, half, metadata, metadata) strictfp
227
228define half @fmsub_h(half %a, half %b, half %c) nounwind strictfp {
229; CHECK-LABEL: fmsub_h:
230; CHECK:       # %bb.0:
231; CHECK-NEXT:    fmv.h.x fa5, zero
232; CHECK-NEXT:    fadd.h fa5, fa2, fa5
233; CHECK-NEXT:    fmsub.h fa0, fa0, fa1, fa5
234; CHECK-NEXT:    ret
235;
236; CHECK-ZHINX-LABEL: fmsub_h:
237; CHECK-ZHINX:       # %bb.0:
238; CHECK-ZHINX-NEXT:    fadd.h a2, a2, zero
239; CHECK-ZHINX-NEXT:    fmsub.h a0, a0, a1, a2
240; CHECK-ZHINX-NEXT:    ret
241;
242; CHECK-ZFHMIN-LABEL: fmsub_h:
243; CHECK-ZFHMIN:       # %bb.0:
244; CHECK-ZFHMIN-NEXT:    fcvt.s.h fa5, fa2
245; CHECK-ZFHMIN-NEXT:    fmv.w.x fa4, zero
246; CHECK-ZFHMIN-NEXT:    lui a0, 1048568
247; CHECK-ZFHMIN-NEXT:    fcvt.s.h fa3, fa1
248; CHECK-ZFHMIN-NEXT:    fadd.s fa5, fa5, fa4
249; CHECK-ZFHMIN-NEXT:    fcvt.h.s fa5, fa5
250; CHECK-ZFHMIN-NEXT:    fmv.x.h a1, fa5
251; CHECK-ZFHMIN-NEXT:    xor a0, a1, a0
252; CHECK-ZFHMIN-NEXT:    fmv.h.x fa5, a0
253; CHECK-ZFHMIN-NEXT:    fcvt.s.h fa5, fa5
254; CHECK-ZFHMIN-NEXT:    fcvt.s.h fa4, fa0
255; CHECK-ZFHMIN-NEXT:    fmadd.s fa5, fa4, fa3, fa5
256; CHECK-ZFHMIN-NEXT:    fcvt.h.s fa0, fa5
257; CHECK-ZFHMIN-NEXT:    ret
258;
259; CHECK-ZHINXMIN-LABEL: fmsub_h:
260; CHECK-ZHINXMIN:       # %bb.0:
261; CHECK-ZHINXMIN-NEXT:    fcvt.s.h a2, a2
262; CHECK-ZHINXMIN-NEXT:    lui a3, 1048568
263; CHECK-ZHINXMIN-NEXT:    fcvt.s.h a1, a1
264; CHECK-ZHINXMIN-NEXT:    fadd.s a2, a2, zero
265; CHECK-ZHINXMIN-NEXT:    fcvt.h.s a2, a2
266; CHECK-ZHINXMIN-NEXT:    xor a2, a2, a3
267; CHECK-ZHINXMIN-NEXT:    fcvt.s.h a2, a2
268; CHECK-ZHINXMIN-NEXT:    fcvt.s.h a0, a0
269; CHECK-ZHINXMIN-NEXT:    fmadd.s a0, a0, a1, a2
270; CHECK-ZHINXMIN-NEXT:    fcvt.h.s a0, a0
271; CHECK-ZHINXMIN-NEXT:    ret
272  %c_ = fadd half 0.0, %c ; avoid negation using xor
273  %negc = fneg half %c_
274  %1 = call half @llvm.experimental.constrained.fma.f16(half %a, half %b, half %negc, metadata !"round.dynamic", metadata !"fpexcept.strict") strictfp
275  ret half %1
276}
277
278define half @fnmadd_h(half %a, half %b, half %c) nounwind strictfp {
279; CHECK-LABEL: fnmadd_h:
280; CHECK:       # %bb.0:
281; CHECK-NEXT:    fmv.h.x fa5, zero
282; CHECK-NEXT:    fadd.h fa4, fa0, fa5
283; CHECK-NEXT:    fadd.h fa5, fa2, fa5
284; CHECK-NEXT:    fnmadd.h fa0, fa4, fa1, fa5
285; CHECK-NEXT:    ret
286;
287; CHECK-ZHINX-LABEL: fnmadd_h:
288; CHECK-ZHINX:       # %bb.0:
289; CHECK-ZHINX-NEXT:    fadd.h a0, a0, zero
290; CHECK-ZHINX-NEXT:    fadd.h a2, a2, zero
291; CHECK-ZHINX-NEXT:    fnmadd.h a0, a0, a1, a2
292; CHECK-ZHINX-NEXT:    ret
293;
294; CHECK-ZFHMIN-LABEL: fnmadd_h:
295; CHECK-ZFHMIN:       # %bb.0:
296; CHECK-ZFHMIN-NEXT:    fcvt.s.h fa5, fa0
297; CHECK-ZFHMIN-NEXT:    fmv.w.x fa4, zero
298; CHECK-ZFHMIN-NEXT:    fcvt.s.h fa3, fa2
299; CHECK-ZFHMIN-NEXT:    lui a0, 1048568
300; CHECK-ZFHMIN-NEXT:    fadd.s fa5, fa5, fa4
301; CHECK-ZFHMIN-NEXT:    fadd.s fa4, fa3, fa4
302; CHECK-ZFHMIN-NEXT:    fcvt.h.s fa5, fa5
303; CHECK-ZFHMIN-NEXT:    fcvt.h.s fa4, fa4
304; CHECK-ZFHMIN-NEXT:    fmv.x.h a1, fa5
305; CHECK-ZFHMIN-NEXT:    fmv.x.h a2, fa4
306; CHECK-ZFHMIN-NEXT:    xor a1, a1, a0
307; CHECK-ZFHMIN-NEXT:    xor a0, a2, a0
308; CHECK-ZFHMIN-NEXT:    fmv.h.x fa5, a1
309; CHECK-ZFHMIN-NEXT:    fmv.h.x fa4, a0
310; CHECK-ZFHMIN-NEXT:    fcvt.s.h fa4, fa4
311; CHECK-ZFHMIN-NEXT:    fcvt.s.h fa5, fa5
312; CHECK-ZFHMIN-NEXT:    fcvt.s.h fa3, fa1
313; CHECK-ZFHMIN-NEXT:    fmadd.s fa5, fa5, fa3, fa4
314; CHECK-ZFHMIN-NEXT:    fcvt.h.s fa0, fa5
315; CHECK-ZFHMIN-NEXT:    ret
316;
317; CHECK-ZHINXMIN-LABEL: fnmadd_h:
318; CHECK-ZHINXMIN:       # %bb.0:
319; CHECK-ZHINXMIN-NEXT:    fcvt.s.h a0, a0
320; CHECK-ZHINXMIN-NEXT:    fcvt.s.h a2, a2
321; CHECK-ZHINXMIN-NEXT:    lui a3, 1048568
322; CHECK-ZHINXMIN-NEXT:    fadd.s a0, a0, zero
323; CHECK-ZHINXMIN-NEXT:    fadd.s a2, a2, zero
324; CHECK-ZHINXMIN-NEXT:    fcvt.h.s a0, a0
325; CHECK-ZHINXMIN-NEXT:    fcvt.h.s a2, a2
326; CHECK-ZHINXMIN-NEXT:    xor a0, a0, a3
327; CHECK-ZHINXMIN-NEXT:    xor a2, a2, a3
328; CHECK-ZHINXMIN-NEXT:    fcvt.s.h a2, a2
329; CHECK-ZHINXMIN-NEXT:    fcvt.s.h a0, a0
330; CHECK-ZHINXMIN-NEXT:    fcvt.s.h a1, a1
331; CHECK-ZHINXMIN-NEXT:    fmadd.s a0, a0, a1, a2
332; CHECK-ZHINXMIN-NEXT:    fcvt.h.s a0, a0
333; CHECK-ZHINXMIN-NEXT:    ret
334  %a_ = fadd half 0.0, %a
335  %c_ = fadd half 0.0, %c
336  %nega = fneg half %a_
337  %negc = fneg half %c_
338  %1 = call half @llvm.experimental.constrained.fma.f16(half %nega, half %b, half %negc, metadata !"round.dynamic", metadata !"fpexcept.strict") strictfp
339  ret half %1
340}
341
342define half @fnmadd_h_2(half %a, half %b, half %c) nounwind strictfp {
343; CHECK-LABEL: fnmadd_h_2:
344; CHECK:       # %bb.0:
345; CHECK-NEXT:    fmv.h.x fa5, zero
346; CHECK-NEXT:    fadd.h fa4, fa1, fa5
347; CHECK-NEXT:    fadd.h fa5, fa2, fa5
348; CHECK-NEXT:    fnmadd.h fa0, fa4, fa0, fa5
349; CHECK-NEXT:    ret
350;
351; CHECK-ZHINX-LABEL: fnmadd_h_2:
352; CHECK-ZHINX:       # %bb.0:
353; CHECK-ZHINX-NEXT:    fadd.h a1, a1, zero
354; CHECK-ZHINX-NEXT:    fadd.h a2, a2, zero
355; CHECK-ZHINX-NEXT:    fnmadd.h a0, a1, a0, a2
356; CHECK-ZHINX-NEXT:    ret
357;
358; CHECK-ZFHMIN-LABEL: fnmadd_h_2:
359; CHECK-ZFHMIN:       # %bb.0:
360; CHECK-ZFHMIN-NEXT:    fcvt.s.h fa5, fa1
361; CHECK-ZFHMIN-NEXT:    fmv.w.x fa4, zero
362; CHECK-ZFHMIN-NEXT:    fcvt.s.h fa3, fa2
363; CHECK-ZFHMIN-NEXT:    lui a0, 1048568
364; CHECK-ZFHMIN-NEXT:    fadd.s fa5, fa5, fa4
365; CHECK-ZFHMIN-NEXT:    fadd.s fa4, fa3, fa4
366; CHECK-ZFHMIN-NEXT:    fcvt.h.s fa5, fa5
367; CHECK-ZFHMIN-NEXT:    fcvt.h.s fa4, fa4
368; CHECK-ZFHMIN-NEXT:    fmv.x.h a1, fa5
369; CHECK-ZFHMIN-NEXT:    fmv.x.h a2, fa4
370; CHECK-ZFHMIN-NEXT:    xor a1, a1, a0
371; CHECK-ZFHMIN-NEXT:    xor a0, a2, a0
372; CHECK-ZFHMIN-NEXT:    fmv.h.x fa5, a1
373; CHECK-ZFHMIN-NEXT:    fmv.h.x fa4, a0
374; CHECK-ZFHMIN-NEXT:    fcvt.s.h fa4, fa4
375; CHECK-ZFHMIN-NEXT:    fcvt.s.h fa5, fa5
376; CHECK-ZFHMIN-NEXT:    fcvt.s.h fa3, fa0
377; CHECK-ZFHMIN-NEXT:    fmadd.s fa5, fa3, fa5, fa4
378; CHECK-ZFHMIN-NEXT:    fcvt.h.s fa0, fa5
379; CHECK-ZFHMIN-NEXT:    ret
380;
381; CHECK-ZHINXMIN-LABEL: fnmadd_h_2:
382; CHECK-ZHINXMIN:       # %bb.0:
383; CHECK-ZHINXMIN-NEXT:    fcvt.s.h a1, a1
384; CHECK-ZHINXMIN-NEXT:    fcvt.s.h a2, a2
385; CHECK-ZHINXMIN-NEXT:    lui a3, 1048568
386; CHECK-ZHINXMIN-NEXT:    fadd.s a1, a1, zero
387; CHECK-ZHINXMIN-NEXT:    fadd.s a2, a2, zero
388; CHECK-ZHINXMIN-NEXT:    fcvt.h.s a1, a1
389; CHECK-ZHINXMIN-NEXT:    fcvt.h.s a2, a2
390; CHECK-ZHINXMIN-NEXT:    xor a1, a1, a3
391; CHECK-ZHINXMIN-NEXT:    xor a2, a2, a3
392; CHECK-ZHINXMIN-NEXT:    fcvt.s.h a2, a2
393; CHECK-ZHINXMIN-NEXT:    fcvt.s.h a1, a1
394; CHECK-ZHINXMIN-NEXT:    fcvt.s.h a0, a0
395; CHECK-ZHINXMIN-NEXT:    fmadd.s a0, a0, a1, a2
396; CHECK-ZHINXMIN-NEXT:    fcvt.h.s a0, a0
397; CHECK-ZHINXMIN-NEXT:    ret
398  %b_ = fadd half 0.0, %b
399  %c_ = fadd half 0.0, %c
400  %negb = fneg half %b_
401  %negc = fneg half %c_
402  %1 = call half @llvm.experimental.constrained.fma.f16(half %a, half %negb, half %negc, metadata !"round.dynamic", metadata !"fpexcept.strict") strictfp
403  ret half %1
404}
405
406define half @fnmsub_h(half %a, half %b, half %c) nounwind strictfp {
407; CHECK-LABEL: fnmsub_h:
408; CHECK:       # %bb.0:
409; CHECK-NEXT:    fmv.h.x fa5, zero
410; CHECK-NEXT:    fadd.h fa5, fa0, fa5
411; CHECK-NEXT:    fnmsub.h fa0, fa5, fa1, fa2
412; CHECK-NEXT:    ret
413;
414; CHECK-ZHINX-LABEL: fnmsub_h:
415; CHECK-ZHINX:       # %bb.0:
416; CHECK-ZHINX-NEXT:    fadd.h a0, a0, zero
417; CHECK-ZHINX-NEXT:    fnmsub.h a0, a0, a1, a2
418; CHECK-ZHINX-NEXT:    ret
419;
420; CHECK-ZFHMIN-LABEL: fnmsub_h:
421; CHECK-ZFHMIN:       # %bb.0:
422; CHECK-ZFHMIN-NEXT:    fcvt.s.h fa5, fa0
423; CHECK-ZFHMIN-NEXT:    fmv.w.x fa4, zero
424; CHECK-ZFHMIN-NEXT:    lui a0, 1048568
425; CHECK-ZFHMIN-NEXT:    fcvt.s.h fa3, fa2
426; CHECK-ZFHMIN-NEXT:    fadd.s fa5, fa5, fa4
427; CHECK-ZFHMIN-NEXT:    fcvt.h.s fa5, fa5
428; CHECK-ZFHMIN-NEXT:    fmv.x.h a1, fa5
429; CHECK-ZFHMIN-NEXT:    xor a0, a1, a0
430; CHECK-ZFHMIN-NEXT:    fmv.h.x fa5, a0
431; CHECK-ZFHMIN-NEXT:    fcvt.s.h fa5, fa5
432; CHECK-ZFHMIN-NEXT:    fcvt.s.h fa4, fa1
433; CHECK-ZFHMIN-NEXT:    fmadd.s fa5, fa5, fa4, fa3
434; CHECK-ZFHMIN-NEXT:    fcvt.h.s fa0, fa5
435; CHECK-ZFHMIN-NEXT:    ret
436;
437; CHECK-ZHINXMIN-LABEL: fnmsub_h:
438; CHECK-ZHINXMIN:       # %bb.0:
439; CHECK-ZHINXMIN-NEXT:    fcvt.s.h a0, a0
440; CHECK-ZHINXMIN-NEXT:    lui a3, 1048568
441; CHECK-ZHINXMIN-NEXT:    fcvt.s.h a2, a2
442; CHECK-ZHINXMIN-NEXT:    fadd.s a0, a0, zero
443; CHECK-ZHINXMIN-NEXT:    fcvt.h.s a0, a0
444; CHECK-ZHINXMIN-NEXT:    xor a0, a0, a3
445; CHECK-ZHINXMIN-NEXT:    fcvt.s.h a0, a0
446; CHECK-ZHINXMIN-NEXT:    fcvt.s.h a1, a1
447; CHECK-ZHINXMIN-NEXT:    fmadd.s a0, a0, a1, a2
448; CHECK-ZHINXMIN-NEXT:    fcvt.h.s a0, a0
449; CHECK-ZHINXMIN-NEXT:    ret
450  %a_ = fadd half 0.0, %a
451  %nega = fneg half %a_
452  %1 = call half @llvm.experimental.constrained.fma.f16(half %nega, half %b, half %c, metadata !"round.dynamic", metadata !"fpexcept.strict") strictfp
453  ret half %1
454}
455
456define half @fnmsub_h_2(half %a, half %b, half %c) nounwind strictfp {
457; CHECK-LABEL: fnmsub_h_2:
458; CHECK:       # %bb.0:
459; CHECK-NEXT:    fmv.h.x fa5, zero
460; CHECK-NEXT:    fadd.h fa5, fa1, fa5
461; CHECK-NEXT:    fnmsub.h fa0, fa5, fa0, fa2
462; CHECK-NEXT:    ret
463;
464; CHECK-ZHINX-LABEL: fnmsub_h_2:
465; CHECK-ZHINX:       # %bb.0:
466; CHECK-ZHINX-NEXT:    fadd.h a1, a1, zero
467; CHECK-ZHINX-NEXT:    fnmsub.h a0, a1, a0, a2
468; CHECK-ZHINX-NEXT:    ret
469;
470; CHECK-ZFHMIN-LABEL: fnmsub_h_2:
471; CHECK-ZFHMIN:       # %bb.0:
472; CHECK-ZFHMIN-NEXT:    fcvt.s.h fa5, fa1
473; CHECK-ZFHMIN-NEXT:    fmv.w.x fa4, zero
474; CHECK-ZFHMIN-NEXT:    lui a0, 1048568
475; CHECK-ZFHMIN-NEXT:    fcvt.s.h fa3, fa2
476; CHECK-ZFHMIN-NEXT:    fadd.s fa5, fa5, fa4
477; CHECK-ZFHMIN-NEXT:    fcvt.h.s fa5, fa5
478; CHECK-ZFHMIN-NEXT:    fmv.x.h a1, fa5
479; CHECK-ZFHMIN-NEXT:    xor a0, a1, a0
480; CHECK-ZFHMIN-NEXT:    fmv.h.x fa5, a0
481; CHECK-ZFHMIN-NEXT:    fcvt.s.h fa5, fa5
482; CHECK-ZFHMIN-NEXT:    fcvt.s.h fa4, fa0
483; CHECK-ZFHMIN-NEXT:    fmadd.s fa5, fa4, fa5, fa3
484; CHECK-ZFHMIN-NEXT:    fcvt.h.s fa0, fa5
485; CHECK-ZFHMIN-NEXT:    ret
486;
487; CHECK-ZHINXMIN-LABEL: fnmsub_h_2:
488; CHECK-ZHINXMIN:       # %bb.0:
489; CHECK-ZHINXMIN-NEXT:    fcvt.s.h a1, a1
490; CHECK-ZHINXMIN-NEXT:    lui a3, 1048568
491; CHECK-ZHINXMIN-NEXT:    fcvt.s.h a2, a2
492; CHECK-ZHINXMIN-NEXT:    fadd.s a1, a1, zero
493; CHECK-ZHINXMIN-NEXT:    fcvt.h.s a1, a1
494; CHECK-ZHINXMIN-NEXT:    xor a1, a1, a3
495; CHECK-ZHINXMIN-NEXT:    fcvt.s.h a1, a1
496; CHECK-ZHINXMIN-NEXT:    fcvt.s.h a0, a0
497; CHECK-ZHINXMIN-NEXT:    fmadd.s a0, a0, a1, a2
498; CHECK-ZHINXMIN-NEXT:    fcvt.h.s a0, a0
499; CHECK-ZHINXMIN-NEXT:    ret
500  %b_ = fadd half 0.0, %b
501  %negb = fneg half %b_
502  %1 = call half @llvm.experimental.constrained.fma.f16(half %a, half %negb, half %c, metadata !"round.dynamic", metadata !"fpexcept.strict") strictfp
503  ret half %1
504}
505;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
506; CHECK-ZFHMIN-RV32: {{.*}}
507; CHECK-ZFHMIN-RV64: {{.*}}
508; CHECK-ZHINXMIN-RV32: {{.*}}
509; CHECK-ZHINXMIN-RV64: {{.*}}
510