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
10
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).
16
17define float @fneg(float %a) nounwind {
18; RV32I-LABEL: fneg:
19; RV32I:       # %bb.0:
20; RV32I-NEXT:    lui a1, 524288
21; RV32I-NEXT:    xor a0, a0, a1
22; RV32I-NEXT:    ret
23;
24; RV32IF-LABEL: fneg:
25; RV32IF:       # %bb.0:
26; RV32IF-NEXT:    lui a1, 524288
27; RV32IF-NEXT:    xor a0, a0, a1
28; RV32IF-NEXT:    ret
29;
30; RV64I-LABEL: fneg:
31; RV64I:       # %bb.0:
32; RV64I-NEXT:    lui a1, 524288
33; RV64I-NEXT:    xor a0, a0, a1
34; RV64I-NEXT:    ret
35;
36; RV64IF-LABEL: fneg:
37; RV64IF:       # %bb.0:
38; RV64IF-NEXT:    lui a1, 524288
39; RV64IF-NEXT:    xor a0, a0, a1
40; RV64IF-NEXT:    ret
41  %1 = fneg float %a
42  ret float %1
43}
44
45declare float @llvm.fabs.f32(float)
46
47define float @fabs(float %a) nounwind {
48; RV32I-LABEL: fabs:
49; RV32I:       # %bb.0:
50; RV32I-NEXT:    slli a0, a0, 1
51; RV32I-NEXT:    srli a0, a0, 1
52; RV32I-NEXT:    ret
53;
54; RV32IF-LABEL: fabs:
55; RV32IF:       # %bb.0:
56; RV32IF-NEXT:    slli a0, a0, 1
57; RV32IF-NEXT:    srli a0, a0, 1
58; RV32IF-NEXT:    ret
59;
60; RV64I-LABEL: fabs:
61; RV64I:       # %bb.0:
62; RV64I-NEXT:    slli a0, a0, 33
63; RV64I-NEXT:    srli a0, a0, 33
64; RV64I-NEXT:    ret
65;
66; RV64IF-LABEL: fabs:
67; RV64IF:       # %bb.0:
68; RV64IF-NEXT:    slli a0, a0, 33
69; RV64IF-NEXT:    srli a0, a0, 33
70; RV64IF-NEXT:    ret
71  %1 = call float @llvm.fabs.f32(float %a)
72  ret float %1
73}
74
75declare float @llvm.copysign.f32(float, float)
76
77; DAGTypeLegalizer::SoftenFloatRes_FCOPYSIGN will convert to bitwise
78; operations if floating point isn't supported. A combine could be written to
79; do the same even when f32 is legal.
80
81define float @fcopysign_fneg(float %a, float %b) nounwind {
82; RV32I-LABEL: fcopysign_fneg:
83; RV32I:       # %bb.0:
84; RV32I-NEXT:    not a1, a1
85; RV32I-NEXT:    lui a2, 524288
86; RV32I-NEXT:    and a1, a1, a2
87; RV32I-NEXT:    slli a0, a0, 1
88; RV32I-NEXT:    srli a0, a0, 1
89; RV32I-NEXT:    or a0, a0, a1
90; RV32I-NEXT:    ret
91;
92; RV32IF-LABEL: fcopysign_fneg:
93; RV32IF:       # %bb.0:
94; RV32IF-NEXT:    lui a2, 524288
95; RV32IF-NEXT:    xor a1, a1, a2
96; RV32IF-NEXT:    fmv.w.x ft0, a1
97; RV32IF-NEXT:    fmv.w.x ft1, a0
98; RV32IF-NEXT:    fsgnj.s ft0, ft1, ft0
99; RV32IF-NEXT:    fmv.x.w a0, ft0
100; RV32IF-NEXT:    ret
101;
102; RV64I-LABEL: fcopysign_fneg:
103; RV64I:       # %bb.0:
104; RV64I-NEXT:    not a1, a1
105; RV64I-NEXT:    lui a2, 524288
106; RV64I-NEXT:    and a1, a1, a2
107; RV64I-NEXT:    slli a0, a0, 33
108; RV64I-NEXT:    srli a0, a0, 33
109; RV64I-NEXT:    or a0, a0, a1
110; RV64I-NEXT:    ret
111;
112; RV64IF-LABEL: fcopysign_fneg:
113; RV64IF:       # %bb.0:
114; RV64IF-NEXT:    fmv.w.x ft0, a1
115; RV64IF-NEXT:    fmv.w.x ft1, a0
116; RV64IF-NEXT:    fsgnjn.s ft0, ft1, ft0
117; RV64IF-NEXT:    fmv.x.w a0, ft0
118; RV64IF-NEXT:    ret
119  %1 = fneg float %b
120  %2 = call float @llvm.copysign.f32(float %a, float %1)
121  ret float %2
122}
123