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=+f -verify-machineinstrs < %s \
5 ; RUN: | FileCheck -check-prefix=RV32IF %s
6 ; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \
7 ; RUN: | FileCheck -check-prefix=RV64I %s
8 ; RUN: llc -mtriple=riscv64 -mattr=+f -verify-machineinstrs < %s \
9 ; RUN: | FileCheck -check-prefix=RV64IF %s
11 ; This file tests cases where simple floating point operations can be
12 ; profitably handled though bit manipulation if a soft-float ABI is being used
13 ; (e.g. fneg implemented by XORing the sign bit). This is typically handled in
14 ; DAGCombiner::visitBITCAST, but this target-independent code may not trigger
15 ; in cases where we perform custom legalisation (e.g. RV64F).
17 define float @fneg(float %a) nounwind {
20 ; RV32I-NEXT: lui a1, 524288
21 ; RV32I-NEXT: xor a0, a0, a1
26 ; RV32IF-NEXT: lui a1, 524288
27 ; RV32IF-NEXT: xor a0, a0, a1
32 ; RV64I-NEXT: lui a1, 524288
33 ; RV64I-NEXT: xor a0, a0, a1
38 ; RV64IF-NEXT: lui a1, 524288
39 ; RV64IF-NEXT: xor a0, a0, a1
45 declare float @llvm.fabs.f32(float)
47 define float @fabs(float %a) nounwind {
50 ; RV32I-NEXT: lui a1, 524288
51 ; RV32I-NEXT: addi a1, a1, -1
52 ; RV32I-NEXT: and a0, a0, a1
57 ; RV32IF-NEXT: lui a1, 524288
58 ; RV32IF-NEXT: addi a1, a1, -1
59 ; RV32IF-NEXT: and a0, a0, a1
64 ; RV64I-NEXT: lui a1, 524288
65 ; RV64I-NEXT: addiw a1, a1, -1
66 ; RV64I-NEXT: and a0, a0, a1
71 ; RV64IF-NEXT: lui a1, 524288
72 ; RV64IF-NEXT: addiw a1, a1, -1
73 ; RV64IF-NEXT: and a0, a0, a1
75 %1 = call float @llvm.fabs.f32(float %a)
79 declare float @llvm.copysign.f32(float, float)
81 ; DAGTypeLegalizer::SoftenFloatRes_FCOPYSIGN will convert to bitwise
82 ; operations if floating point isn't supported. A combine could be written to
83 ; do the same even when f32 is legal.
85 define float @fcopysign_fneg(float %a, float %b) nounwind {
86 ; RV32I-LABEL: fcopysign_fneg:
88 ; RV32I-NEXT: not a1, a1
89 ; RV32I-NEXT: lui a2, 524288
90 ; RV32I-NEXT: and a1, a1, a2
91 ; RV32I-NEXT: addi a2, a2, -1
92 ; RV32I-NEXT: and a0, a0, a2
93 ; RV32I-NEXT: or a0, a0, a1
96 ; RV32IF-LABEL: fcopysign_fneg:
98 ; RV32IF-NEXT: lui a2, 524288
99 ; RV32IF-NEXT: xor a1, a1, a2
100 ; RV32IF-NEXT: fmv.w.x ft0, a1
101 ; RV32IF-NEXT: fmv.w.x ft1, a0
102 ; RV32IF-NEXT: fsgnj.s ft0, ft1, ft0
103 ; RV32IF-NEXT: fmv.x.w a0, ft0
106 ; RV64I-LABEL: fcopysign_fneg:
108 ; RV64I-NEXT: not a1, a1
109 ; RV64I-NEXT: lui a2, 524288
110 ; RV64I-NEXT: and a1, a1, a2
111 ; RV64I-NEXT: addiw a2, a2, -1
112 ; RV64I-NEXT: and a0, a0, a2
113 ; RV64I-NEXT: or a0, a0, a1
116 ; RV64IF-LABEL: fcopysign_fneg:
118 ; RV64IF-NEXT: fmv.w.x ft0, a1
119 ; RV64IF-NEXT: fmv.w.x ft1, a0
120 ; RV64IF-NEXT: fsgnjn.s ft0, ft1, ft0
121 ; RV64IF-NEXT: fmv.x.w a0, ft0
124 %2 = call float @llvm.copysign.f32(float %a, float %1)