Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / llvm / test / CodeGen / RISCV / half-bitmanip-dagcombines.ll
blobdb35a55e9f59fc25dddc38072617662fe594c0a3
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 {
32 ; RV32I-LABEL: fneg:
33 ; RV32I:       # %bb.0:
34 ; RV32I-NEXT:    lui a1, 1048568
35 ; RV32I-NEXT:    xor a0, a0, a1
36 ; RV32I-NEXT:    ret
38 ; RV32IZFH-LABEL: fneg:
39 ; RV32IZFH:       # %bb.0:
40 ; RV32IZFH-NEXT:    lui a1, 1048568
41 ; RV32IZFH-NEXT:    xor a0, a0, a1
42 ; RV32IZFH-NEXT:    ret
44 ; RV64I-LABEL: fneg:
45 ; RV64I:       # %bb.0:
46 ; RV64I-NEXT:    lui a1, 1048568
47 ; RV64I-NEXT:    xor a0, a0, a1
48 ; RV64I-NEXT:    ret
50 ; RV64IZFH-LABEL: fneg:
51 ; RV64IZFH:       # %bb.0:
52 ; RV64IZFH-NEXT:    lui a1, 1048568
53 ; RV64IZFH-NEXT:    xor a0, a0, a1
54 ; RV64IZFH-NEXT:    ret
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
85   %1 = fneg half %a
86   ret half %1
89 declare half @llvm.fabs.f16(half)
91 define half @fabs(half %a) nounwind {
92 ; RV32I-LABEL: fabs:
93 ; RV32I:       # %bb.0:
94 ; RV32I-NEXT:    slli a0, a0, 17
95 ; RV32I-NEXT:    srli a0, a0, 17
96 ; RV32I-NEXT:    ret
98 ; RV32IZFH-LABEL: fabs:
99 ; RV32IZFH:       # %bb.0:
100 ; RV32IZFH-NEXT:    slli a0, a0, 17
101 ; RV32IZFH-NEXT:    srli a0, a0, 17
102 ; RV32IZFH-NEXT:    ret
104 ; RV64I-LABEL: fabs:
105 ; RV64I:       # %bb.0:
106 ; RV64I-NEXT:    slli a0, a0, 49
107 ; RV64I-NEXT:    srli a0, a0, 49
108 ; RV64I-NEXT:    ret
110 ; RV64IZFH-LABEL: fabs:
111 ; RV64IZFH:       # %bb.0:
112 ; RV64IZFH-NEXT:    slli a0, a0, 49
113 ; RV64IZFH-NEXT:    srli a0, a0, 49
114 ; RV64IZFH-NEXT:    ret
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)
152   ret half %1
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:
163 ; RV32I:       # %bb.0:
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
170 ; RV32I-NEXT:    ret
172 ; RV32IZFH-LABEL: fcopysign_fneg:
173 ; RV32IZFH:       # %bb.0:
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
178 ; RV32IZFH-NEXT:    ret
180 ; RV64I-LABEL: fcopysign_fneg:
181 ; RV64I:       # %bb.0:
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
188 ; RV64I-NEXT:    ret
190 ; RV64IZFH-LABEL: fcopysign_fneg:
191 ; RV64IZFH:       # %bb.0:
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
196 ; RV64IZFH-NEXT:    ret
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
285   %1 = fneg half %b
286   %2 = call half @llvm.copysign.f16(half %a, half %1)
287   ret half %2