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: lui a1, 524288
37 ; RV32IZFINX-NEXT: xor a0, a0, a1
38 ; RV32IZFINX-NEXT: ret
42 ; RV64I-NEXT: lui a1, 524288
43 ; RV64I-NEXT: xor a0, a0, a1
48 ; RV64IF-NEXT: lui a1, 524288
49 ; RV64IF-NEXT: xor a0, a0, a1
52 ; RV64IZFINX-LABEL: fneg:
53 ; RV64IZFINX: # %bb.0:
54 ; RV64IZFINX-NEXT: lui a1, 524288
55 ; RV64IZFINX-NEXT: xor a0, a0, a1
56 ; RV64IZFINX-NEXT: ret
61 declare float @llvm.fabs.f32(float)
63 define float @fabs(float %a) nounwind {
66 ; RV32I-NEXT: slli a0, a0, 1
67 ; RV32I-NEXT: srli a0, a0, 1
72 ; RV32IF-NEXT: slli a0, a0, 1
73 ; RV32IF-NEXT: srli a0, a0, 1
76 ; RV32IZFINX-LABEL: fabs:
77 ; RV32IZFINX: # %bb.0:
78 ; RV32IZFINX-NEXT: slli a0, a0, 1
79 ; RV32IZFINX-NEXT: srli a0, a0, 1
80 ; RV32IZFINX-NEXT: ret
84 ; RV64I-NEXT: slli a0, a0, 33
85 ; RV64I-NEXT: srli a0, a0, 33
90 ; RV64IF-NEXT: slli a0, a0, 33
91 ; RV64IF-NEXT: srli a0, a0, 33
94 ; RV64IZFINX-LABEL: fabs:
95 ; RV64IZFINX: # %bb.0:
96 ; RV64IZFINX-NEXT: slli a0, a0, 33
97 ; RV64IZFINX-NEXT: srli a0, a0, 33
98 ; RV64IZFINX-NEXT: ret
99 %1 = call float @llvm.fabs.f32(float %a)
103 declare float @llvm.copysign.f32(float, float)
105 ; DAGTypeLegalizer::SoftenFloatRes_FCOPYSIGN will convert to bitwise
106 ; operations if floating point isn't supported. A combine could be written to
107 ; do the same even when f32 is legal.
109 define float @fcopysign_fneg(float %a, float %b) nounwind {
110 ; RV32I-LABEL: fcopysign_fneg:
112 ; RV32I-NEXT: not a1, a1
113 ; RV32I-NEXT: lui a2, 524288
114 ; RV32I-NEXT: and a1, a1, a2
115 ; RV32I-NEXT: slli a0, a0, 1
116 ; RV32I-NEXT: srli a0, a0, 1
117 ; RV32I-NEXT: or a0, a0, a1
120 ; RV32IF-LABEL: fcopysign_fneg:
122 ; RV32IF-NEXT: lui a2, 524288
123 ; RV32IF-NEXT: xor a1, a1, a2
124 ; RV32IF-NEXT: fmv.w.x fa5, a1
125 ; RV32IF-NEXT: fmv.w.x fa4, a0
126 ; RV32IF-NEXT: fsgnj.s fa5, fa4, fa5
127 ; RV32IF-NEXT: fmv.x.w a0, fa5
130 ; RV32IZFINX-LABEL: fcopysign_fneg:
131 ; RV32IZFINX: # %bb.0:
132 ; RV32IZFINX-NEXT: lui a2, 524288
133 ; RV32IZFINX-NEXT: xor a1, a1, a2
134 ; RV32IZFINX-NEXT: fsgnj.s a0, a0, a1
135 ; RV32IZFINX-NEXT: ret
137 ; RV64I-LABEL: fcopysign_fneg:
139 ; RV64I-NEXT: not a1, a1
140 ; RV64I-NEXT: lui a2, 524288
141 ; RV64I-NEXT: and a1, a1, a2
142 ; RV64I-NEXT: slli a0, a0, 33
143 ; RV64I-NEXT: srli a0, a0, 33
144 ; RV64I-NEXT: or a0, a0, a1
147 ; RV64IF-LABEL: fcopysign_fneg:
149 ; RV64IF-NEXT: fmv.w.x fa5, a1
150 ; RV64IF-NEXT: fmv.w.x fa4, a0
151 ; RV64IF-NEXT: fsgnjn.s fa5, fa4, fa5
152 ; RV64IF-NEXT: fmv.x.w a0, fa5
155 ; RV64IZFINX-LABEL: fcopysign_fneg:
156 ; RV64IZFINX: # %bb.0:
157 ; RV64IZFINX-NEXT: fsgnjn.s a0, a0, a1
158 ; RV64IZFINX-NEXT: ret
160 %2 = call float @llvm.copysign.f32(float %a, float %1)