1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \
3 ; RUN: | FileCheck -check-prefix=RV32I %s
4 ; RUN: llc -mtriple=riscv32 -mattr=+zfh -verify-machineinstrs \
5 ; RUN: < %s | FileCheck -check-prefix=RV32IZFH %s
6 ; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \
7 ; RUN: | FileCheck -check-prefix=RV64I %s
8 ; RUN: llc -mtriple=riscv64 -mattr=+zfh -verify-machineinstrs \
9 ; RUN: < %s | FileCheck -check-prefix=RV64IZFH %s
10 ; RUN: llc -mtriple=riscv32 -mattr=+zhinx -verify-machineinstrs \
11 ; RUN: < %s | FileCheck -check-prefix=RV32IZHINX %s
12 ; RUN: llc -mtriple=riscv64 -mattr=+zhinx -verify-machineinstrs \
13 ; RUN: < %s | FileCheck -check-prefix=RV64IZHINX %s
14 ; RUN: llc -mtriple=riscv32 -mattr=+zfhmin -verify-machineinstrs \
15 ; RUN: < %s | FileCheck -check-prefix=RV32IZFHMIN %s
16 ; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \
17 ; RUN: | FileCheck -check-prefix=RV64I %s
18 ; RUN: llc -mtriple=riscv64 -mattr=+zfhmin -verify-machineinstrs \
19 ; RUN: < %s | FileCheck -check-prefix=RV64IZFHMIN %s
20 ; RUN: llc -mtriple=riscv32 -mattr=+zhinxmin -verify-machineinstrs \
21 ; RUN: < %s | FileCheck --check-prefixes=RVIZHINXMIN,RV32IZHINXMIN %s
22 ; RUN: llc -mtriple=riscv64 -mattr=+zhinxmin -verify-machineinstrs \
23 ; RUN: < %s | FileCheck --check-prefixes=RVIZHINXMIN,RV64IZHINXMIN %s
25 ; This file tests cases where simple floating point operations can be
26 ; profitably handled though bit manipulation if a soft-float ABI is being used
27 ; (e.g. fneg implemented by XORing the sign bit). This is typically handled in
28 ; DAGCombiner::visitBITCAST, but this target-independent code may not trigger
29 ; in cases where we perform custom legalisation (e.g. RV64F).
31 define half @fneg(half %a) nounwind {
34 ; RV32I-NEXT: lui a1, 1048568
35 ; RV32I-NEXT: xor a0, a0, a1
38 ; RV32IZFH-LABEL: fneg:
40 ; RV32IZFH-NEXT: lui a1, 1048568
41 ; RV32IZFH-NEXT: xor a0, a0, a1
46 ; RV64I-NEXT: lui a1, 1048568
47 ; RV64I-NEXT: xor a0, a0, a1
50 ; RV64IZFH-LABEL: fneg:
52 ; RV64IZFH-NEXT: lui a1, 1048568
53 ; RV64IZFH-NEXT: xor a0, a0, a1
56 ; RV32IZHINX-LABEL: fneg:
57 ; RV32IZHINX: # %bb.0:
58 ; RV32IZHINX-NEXT: lui a1, 1048568
59 ; RV32IZHINX-NEXT: xor a0, a0, a1
60 ; RV32IZHINX-NEXT: ret
62 ; RV64IZHINX-LABEL: fneg:
63 ; RV64IZHINX: # %bb.0:
64 ; RV64IZHINX-NEXT: lui a1, 1048568
65 ; RV64IZHINX-NEXT: xor a0, a0, a1
66 ; RV64IZHINX-NEXT: ret
68 ; RV32IZFHMIN-LABEL: fneg:
69 ; RV32IZFHMIN: # %bb.0:
70 ; RV32IZFHMIN-NEXT: lui a1, 1048568
71 ; RV32IZFHMIN-NEXT: xor a0, a0, a1
72 ; RV32IZFHMIN-NEXT: ret
74 ; RV64IZFHMIN-LABEL: fneg:
75 ; RV64IZFHMIN: # %bb.0:
76 ; RV64IZFHMIN-NEXT: lui a1, 1048568
77 ; RV64IZFHMIN-NEXT: xor a0, a0, a1
78 ; RV64IZFHMIN-NEXT: ret
80 ; RVIZHINXMIN-LABEL: fneg:
81 ; RVIZHINXMIN: # %bb.0:
82 ; RVIZHINXMIN-NEXT: lui a1, 1048568
83 ; RVIZHINXMIN-NEXT: xor a0, a0, a1
84 ; RVIZHINXMIN-NEXT: ret
89 declare half @llvm.fabs.f16(half)
91 define half @fabs(half %a) nounwind {
94 ; RV32I-NEXT: slli a0, a0, 17
95 ; RV32I-NEXT: srli a0, a0, 17
98 ; RV32IZFH-LABEL: fabs:
100 ; RV32IZFH-NEXT: slli a0, a0, 17
101 ; RV32IZFH-NEXT: srli a0, a0, 17
106 ; RV64I-NEXT: slli a0, a0, 49
107 ; RV64I-NEXT: srli a0, a0, 49
110 ; RV64IZFH-LABEL: fabs:
112 ; RV64IZFH-NEXT: slli a0, a0, 49
113 ; RV64IZFH-NEXT: srli a0, a0, 49
116 ; RV32IZHINX-LABEL: fabs:
117 ; RV32IZHINX: # %bb.0:
118 ; RV32IZHINX-NEXT: slli a0, a0, 17
119 ; RV32IZHINX-NEXT: srli a0, a0, 17
120 ; RV32IZHINX-NEXT: ret
122 ; RV64IZHINX-LABEL: fabs:
123 ; RV64IZHINX: # %bb.0:
124 ; RV64IZHINX-NEXT: slli a0, a0, 49
125 ; RV64IZHINX-NEXT: srli a0, a0, 49
126 ; RV64IZHINX-NEXT: ret
128 ; RV32IZFHMIN-LABEL: fabs:
129 ; RV32IZFHMIN: # %bb.0:
130 ; RV32IZFHMIN-NEXT: slli a0, a0, 17
131 ; RV32IZFHMIN-NEXT: srli a0, a0, 17
132 ; RV32IZFHMIN-NEXT: ret
134 ; RV64IZFHMIN-LABEL: fabs:
135 ; RV64IZFHMIN: # %bb.0:
136 ; RV64IZFHMIN-NEXT: slli a0, a0, 49
137 ; RV64IZFHMIN-NEXT: srli a0, a0, 49
138 ; RV64IZFHMIN-NEXT: ret
140 ; RV32IZHINXMIN-LABEL: fabs:
141 ; RV32IZHINXMIN: # %bb.0:
142 ; RV32IZHINXMIN-NEXT: slli a0, a0, 17
143 ; RV32IZHINXMIN-NEXT: srli a0, a0, 17
144 ; RV32IZHINXMIN-NEXT: ret
146 ; RV64IZHINXMIN-LABEL: fabs:
147 ; RV64IZHINXMIN: # %bb.0:
148 ; RV64IZHINXMIN-NEXT: slli a0, a0, 49
149 ; RV64IZHINXMIN-NEXT: srli a0, a0, 49
150 ; RV64IZHINXMIN-NEXT: ret
151 %1 = call half @llvm.fabs.f16(half %a)
155 declare half @llvm.copysign.f16(half, half)
157 ; DAGTypeLegalizer::SoftenFloatRes_FCOPYSIGN will convert to bitwise
158 ; operations if half precision floating point isn't supported. A combine could
159 ; be written to do the same even when f16 is legal.
161 define half @fcopysign_fneg(half %a, half %b) nounwind {
162 ; RV32I-LABEL: fcopysign_fneg:
164 ; RV32I-NEXT: not a1, a1
165 ; RV32I-NEXT: lui a2, 1048568
166 ; RV32I-NEXT: and a1, a1, a2
167 ; RV32I-NEXT: slli a0, a0, 17
168 ; RV32I-NEXT: srli a0, a0, 17
169 ; RV32I-NEXT: or a0, a0, a1
172 ; RV32IZFH-LABEL: fcopysign_fneg:
174 ; RV32IZFH-NEXT: fmv.h.x fa5, a1
175 ; RV32IZFH-NEXT: fmv.h.x fa4, a0
176 ; RV32IZFH-NEXT: fsgnjn.h fa5, fa4, fa5
177 ; RV32IZFH-NEXT: fmv.x.h a0, fa5
180 ; RV64I-LABEL: fcopysign_fneg:
182 ; RV64I-NEXT: not a1, a1
183 ; RV64I-NEXT: lui a2, 1048568
184 ; RV64I-NEXT: and a1, a1, a2
185 ; RV64I-NEXT: slli a0, a0, 49
186 ; RV64I-NEXT: srli a0, a0, 49
187 ; RV64I-NEXT: or a0, a0, a1
190 ; RV64IZFH-LABEL: fcopysign_fneg:
192 ; RV64IZFH-NEXT: fmv.h.x fa5, a1
193 ; RV64IZFH-NEXT: fmv.h.x fa4, a0
194 ; RV64IZFH-NEXT: fsgnjn.h fa5, fa4, fa5
195 ; RV64IZFH-NEXT: fmv.x.h a0, fa5
198 ; RV32IZHINX-LABEL: fcopysign_fneg:
199 ; RV32IZHINX: # %bb.0:
200 ; RV32IZHINX-NEXT: fsgnjn.h a0, a0, a1
201 ; RV32IZHINX-NEXT: ret
203 ; RV64IZHINX-LABEL: fcopysign_fneg:
204 ; RV64IZHINX: # %bb.0:
205 ; RV64IZHINX-NEXT: fsgnjn.h a0, a0, a1
206 ; RV64IZHINX-NEXT: ret
208 ; RV32IZFHMIN-LABEL: fcopysign_fneg:
209 ; RV32IZFHMIN: # %bb.0:
210 ; RV32IZFHMIN-NEXT: addi sp, sp, -16
211 ; RV32IZFHMIN-NEXT: fmv.h.x fa5, a0
212 ; RV32IZFHMIN-NEXT: fmv.h.x fa4, a1
213 ; RV32IZFHMIN-NEXT: fcvt.s.h fa4, fa4
214 ; RV32IZFHMIN-NEXT: fneg.s fa4, fa4
215 ; RV32IZFHMIN-NEXT: fcvt.h.s fa4, fa4
216 ; RV32IZFHMIN-NEXT: fsh fa5, 8(sp)
217 ; RV32IZFHMIN-NEXT: fsh fa4, 12(sp)
218 ; RV32IZFHMIN-NEXT: lbu a0, 9(sp)
219 ; RV32IZFHMIN-NEXT: lbu a1, 13(sp)
220 ; RV32IZFHMIN-NEXT: andi a0, a0, 127
221 ; RV32IZFHMIN-NEXT: andi a1, a1, 128
222 ; RV32IZFHMIN-NEXT: or a0, a0, a1
223 ; RV32IZFHMIN-NEXT: sb a0, 9(sp)
224 ; RV32IZFHMIN-NEXT: flh fa5, 8(sp)
225 ; RV32IZFHMIN-NEXT: fmv.x.h a0, fa5
226 ; RV32IZFHMIN-NEXT: addi sp, sp, 16
227 ; RV32IZFHMIN-NEXT: ret
229 ; RV64IZFHMIN-LABEL: fcopysign_fneg:
230 ; RV64IZFHMIN: # %bb.0:
231 ; RV64IZFHMIN-NEXT: addi sp, sp, -16
232 ; RV64IZFHMIN-NEXT: fmv.h.x fa5, a0
233 ; RV64IZFHMIN-NEXT: fmv.h.x fa4, a1
234 ; RV64IZFHMIN-NEXT: fcvt.s.h fa4, fa4
235 ; RV64IZFHMIN-NEXT: fneg.s fa4, fa4
236 ; RV64IZFHMIN-NEXT: fcvt.h.s fa4, fa4
237 ; RV64IZFHMIN-NEXT: fsh fa5, 0(sp)
238 ; RV64IZFHMIN-NEXT: fsh fa4, 8(sp)
239 ; RV64IZFHMIN-NEXT: lbu a0, 1(sp)
240 ; RV64IZFHMIN-NEXT: lbu a1, 9(sp)
241 ; RV64IZFHMIN-NEXT: andi a0, a0, 127
242 ; RV64IZFHMIN-NEXT: andi a1, a1, 128
243 ; RV64IZFHMIN-NEXT: or a0, a0, a1
244 ; RV64IZFHMIN-NEXT: sb a0, 1(sp)
245 ; RV64IZFHMIN-NEXT: flh fa5, 0(sp)
246 ; RV64IZFHMIN-NEXT: fmv.x.h a0, fa5
247 ; RV64IZFHMIN-NEXT: addi sp, sp, 16
248 ; RV64IZFHMIN-NEXT: ret
250 ; RV32IZHINXMIN-LABEL: fcopysign_fneg:
251 ; RV32IZHINXMIN: # %bb.0:
252 ; RV32IZHINXMIN-NEXT: addi sp, sp, -16
253 ; RV32IZHINXMIN-NEXT: fcvt.s.h a1, a1
254 ; RV32IZHINXMIN-NEXT: fneg.s a1, a1
255 ; RV32IZHINXMIN-NEXT: fcvt.h.s a1, a1
256 ; RV32IZHINXMIN-NEXT: sh a0, 8(sp)
257 ; RV32IZHINXMIN-NEXT: sh a1, 12(sp)
258 ; RV32IZHINXMIN-NEXT: lbu a0, 9(sp)
259 ; RV32IZHINXMIN-NEXT: lbu a1, 13(sp)
260 ; RV32IZHINXMIN-NEXT: andi a0, a0, 127
261 ; RV32IZHINXMIN-NEXT: andi a1, a1, 128
262 ; RV32IZHINXMIN-NEXT: or a0, a0, a1
263 ; RV32IZHINXMIN-NEXT: sb a0, 9(sp)
264 ; RV32IZHINXMIN-NEXT: lh a0, 8(sp)
265 ; RV32IZHINXMIN-NEXT: addi sp, sp, 16
266 ; RV32IZHINXMIN-NEXT: ret
268 ; RV64IZHINXMIN-LABEL: fcopysign_fneg:
269 ; RV64IZHINXMIN: # %bb.0:
270 ; RV64IZHINXMIN-NEXT: addi sp, sp, -16
271 ; RV64IZHINXMIN-NEXT: fcvt.s.h a1, a1
272 ; RV64IZHINXMIN-NEXT: fneg.s a1, a1
273 ; RV64IZHINXMIN-NEXT: fcvt.h.s a1, a1
274 ; RV64IZHINXMIN-NEXT: sh a0, 0(sp)
275 ; RV64IZHINXMIN-NEXT: sh a1, 8(sp)
276 ; RV64IZHINXMIN-NEXT: lbu a0, 1(sp)
277 ; RV64IZHINXMIN-NEXT: lbu a1, 9(sp)
278 ; RV64IZHINXMIN-NEXT: andi a0, a0, 127
279 ; RV64IZHINXMIN-NEXT: andi a1, a1, 128
280 ; RV64IZHINXMIN-NEXT: or a0, a0, a1
281 ; RV64IZHINXMIN-NEXT: sb a0, 1(sp)
282 ; RV64IZHINXMIN-NEXT: lh a0, 0(sp)
283 ; RV64IZHINXMIN-NEXT: addi sp, sp, 16
284 ; RV64IZHINXMIN-NEXT: ret
286 %2 = call half @llvm.copysign.f16(half %a, half %1)