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 -target-abi ilp32 -mattr=+f -verify-machineinstrs < %s \
5 ; RUN: | FileCheck -check-prefix=RV32IF %s
6 ; RUN: llc -mtriple=riscv32 -target-abi ilp32 -mattr=+zfinx -verify-machineinstrs < %s \
7 ; RUN: | FileCheck -check-prefix=RV32IZFINX %s
8 ; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \
9 ; RUN: | FileCheck -check-prefix=RV64I %s
10 ; RUN: llc -mtriple=riscv64 -target-abi lp64 -mattr=+f -verify-machineinstrs < %s \
11 ; RUN: | FileCheck -check-prefix=RV64IF %s
12 ; RUN: llc -mtriple=riscv64 -target-abi lp64 -mattr=+zfinx -verify-machineinstrs < %s \
13 ; RUN: | FileCheck -check-prefix=RV64IZFINX %s
15 ; This file tests cases where simple floating point operations can be
16 ; profitably handled though bit manipulation if a soft-float ABI is being used
17 ; (e.g. fneg implemented by XORing the sign bit). This is typically handled in
18 ; DAGCombiner::visitBITCAST, but this target-independent code may not trigger
19 ; in cases where we perform custom legalisation (e.g. RV64F).
21 define float @fneg(float %a) nounwind {
24 ; RV32I-NEXT: lui a1, 524288
25 ; RV32I-NEXT: xor a0, a0, a1
30 ; RV32IF-NEXT: lui a1, 524288
31 ; RV32IF-NEXT: xor a0, a0, a1
34 ; RV32IZFINX-LABEL: fneg:
35 ; RV32IZFINX: # %bb.0:
36 ; RV32IZFINX-NEXT: fneg.s a0, a0
37 ; RV32IZFINX-NEXT: ret
41 ; RV64I-NEXT: lui a1, 524288
42 ; RV64I-NEXT: xor a0, a0, a1
47 ; RV64IF-NEXT: lui a1, 524288
48 ; RV64IF-NEXT: xor a0, a0, a1
51 ; RV64IZFINX-LABEL: fneg:
52 ; RV64IZFINX: # %bb.0:
53 ; RV64IZFINX-NEXT: fneg.s a0, a0
54 ; RV64IZFINX-NEXT: ret
59 declare float @llvm.fabs.f32(float)
61 define float @fabs(float %a) nounwind {
64 ; RV32I-NEXT: slli a0, a0, 1
65 ; RV32I-NEXT: srli a0, a0, 1
70 ; RV32IF-NEXT: slli a0, a0, 1
71 ; RV32IF-NEXT: srli a0, a0, 1
74 ; RV32IZFINX-LABEL: fabs:
75 ; RV32IZFINX: # %bb.0:
76 ; RV32IZFINX-NEXT: fabs.s a0, a0
77 ; RV32IZFINX-NEXT: ret
81 ; RV64I-NEXT: slli a0, a0, 33
82 ; RV64I-NEXT: srli a0, a0, 33
87 ; RV64IF-NEXT: slli a0, a0, 33
88 ; RV64IF-NEXT: srli a0, a0, 33
91 ; RV64IZFINX-LABEL: fabs:
92 ; RV64IZFINX: # %bb.0:
93 ; RV64IZFINX-NEXT: fabs.s a0, a0
94 ; RV64IZFINX-NEXT: ret
95 %1 = call float @llvm.fabs.f32(float %a)
99 declare float @llvm.copysign.f32(float, float)
101 ; DAGTypeLegalizer::SoftenFloatRes_FCOPYSIGN will convert to bitwise
102 ; operations if floating point isn't supported. A combine could be written to
103 ; do the same even when f32 is legal.
105 define float @fcopysign_fneg(float %a, float %b) nounwind {
106 ; RV32I-LABEL: fcopysign_fneg:
108 ; RV32I-NEXT: not a1, a1
109 ; RV32I-NEXT: lui a2, 524288
110 ; RV32I-NEXT: slli a0, a0, 1
111 ; RV32I-NEXT: and a1, a1, a2
112 ; RV32I-NEXT: srli a0, a0, 1
113 ; RV32I-NEXT: or a0, a0, a1
116 ; RV32IF-LABEL: fcopysign_fneg:
118 ; RV32IF-NEXT: fmv.w.x fa5, a0
119 ; RV32IF-NEXT: not a0, a1
120 ; RV32IF-NEXT: fmv.w.x fa4, a0
121 ; RV32IF-NEXT: fsgnj.s fa5, fa5, fa4
122 ; RV32IF-NEXT: fmv.x.w a0, fa5
125 ; RV32IZFINX-LABEL: fcopysign_fneg:
126 ; RV32IZFINX: # %bb.0:
127 ; RV32IZFINX-NEXT: fsgnjn.s a0, a0, a1
128 ; RV32IZFINX-NEXT: ret
130 ; RV64I-LABEL: fcopysign_fneg:
132 ; RV64I-NEXT: not a1, a1
133 ; RV64I-NEXT: lui a2, 524288
134 ; RV64I-NEXT: slli a0, a0, 33
135 ; RV64I-NEXT: and a1, a1, a2
136 ; RV64I-NEXT: srli a0, a0, 33
137 ; RV64I-NEXT: or a0, a0, a1
140 ; RV64IF-LABEL: fcopysign_fneg:
142 ; RV64IF-NEXT: fmv.w.x fa5, a1
143 ; RV64IF-NEXT: fmv.w.x fa4, a0
144 ; RV64IF-NEXT: fsgnjn.s fa5, fa4, fa5
145 ; RV64IF-NEXT: fmv.x.w a0, fa5
148 ; RV64IZFINX-LABEL: fcopysign_fneg:
149 ; RV64IZFINX: # %bb.0:
150 ; RV64IZFINX-NEXT: fsgnjn.s a0, a0, a1
151 ; RV64IZFINX-NEXT: ret
153 %2 = call float @llvm.copysign.f32(float %a, float %1)