xref: /llvm-project/llvm/test/CodeGen/RISCV/float-bitmanip-dagcombines.ll (revision 9122c5235ec85ce0c0ad337e862b006e7b349d84)
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
14
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).
20
21define float @fneg(float %a) nounwind {
22; RV32I-LABEL: fneg:
23; RV32I:       # %bb.0:
24; RV32I-NEXT:    lui a1, 524288
25; RV32I-NEXT:    xor a0, a0, a1
26; RV32I-NEXT:    ret
27;
28; RV32IF-LABEL: fneg:
29; RV32IF:       # %bb.0:
30; RV32IF-NEXT:    lui a1, 524288
31; RV32IF-NEXT:    xor a0, a0, a1
32; RV32IF-NEXT:    ret
33;
34; RV32IZFINX-LABEL: fneg:
35; RV32IZFINX:       # %bb.0:
36; RV32IZFINX-NEXT:    fneg.s a0, a0
37; RV32IZFINX-NEXT:    ret
38;
39; RV64I-LABEL: fneg:
40; RV64I:       # %bb.0:
41; RV64I-NEXT:    lui a1, 524288
42; RV64I-NEXT:    xor a0, a0, a1
43; RV64I-NEXT:    ret
44;
45; RV64IF-LABEL: fneg:
46; RV64IF:       # %bb.0:
47; RV64IF-NEXT:    lui a1, 524288
48; RV64IF-NEXT:    xor a0, a0, a1
49; RV64IF-NEXT:    ret
50;
51; RV64IZFINX-LABEL: fneg:
52; RV64IZFINX:       # %bb.0:
53; RV64IZFINX-NEXT:    fneg.s a0, a0
54; RV64IZFINX-NEXT:    ret
55  %1 = fneg float %a
56  ret float %1
57}
58
59declare float @llvm.fabs.f32(float)
60
61define float @fabs(float %a) nounwind {
62; RV32I-LABEL: fabs:
63; RV32I:       # %bb.0:
64; RV32I-NEXT:    slli a0, a0, 1
65; RV32I-NEXT:    srli a0, a0, 1
66; RV32I-NEXT:    ret
67;
68; RV32IF-LABEL: fabs:
69; RV32IF:       # %bb.0:
70; RV32IF-NEXT:    slli a0, a0, 1
71; RV32IF-NEXT:    srli a0, a0, 1
72; RV32IF-NEXT:    ret
73;
74; RV32IZFINX-LABEL: fabs:
75; RV32IZFINX:       # %bb.0:
76; RV32IZFINX-NEXT:    fabs.s a0, a0
77; RV32IZFINX-NEXT:    ret
78;
79; RV64I-LABEL: fabs:
80; RV64I:       # %bb.0:
81; RV64I-NEXT:    slli a0, a0, 33
82; RV64I-NEXT:    srli a0, a0, 33
83; RV64I-NEXT:    ret
84;
85; RV64IF-LABEL: fabs:
86; RV64IF:       # %bb.0:
87; RV64IF-NEXT:    slli a0, a0, 33
88; RV64IF-NEXT:    srli a0, a0, 33
89; RV64IF-NEXT:    ret
90;
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)
96  ret float %1
97}
98
99declare float @llvm.copysign.f32(float, float)
100
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.
104
105define float @fcopysign_fneg(float %a, float %b) nounwind {
106; RV32I-LABEL: fcopysign_fneg:
107; RV32I:       # %bb.0:
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
114; RV32I-NEXT:    ret
115;
116; RV32IF-LABEL: fcopysign_fneg:
117; RV32IF:       # %bb.0:
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
123; RV32IF-NEXT:    ret
124;
125; RV32IZFINX-LABEL: fcopysign_fneg:
126; RV32IZFINX:       # %bb.0:
127; RV32IZFINX-NEXT:    fsgnjn.s a0, a0, a1
128; RV32IZFINX-NEXT:    ret
129;
130; RV64I-LABEL: fcopysign_fneg:
131; RV64I:       # %bb.0:
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
138; RV64I-NEXT:    ret
139;
140; RV64IF-LABEL: fcopysign_fneg:
141; RV64IF:       # %bb.0:
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
146; RV64IF-NEXT:    ret
147;
148; RV64IZFINX-LABEL: fcopysign_fneg:
149; RV64IZFINX:       # %bb.0:
150; RV64IZFINX-NEXT:    fsgnjn.s a0, a0, a1
151; RV64IZFINX-NEXT:    ret
152  %1 = fneg float %b
153  %2 = call float @llvm.copysign.f32(float %a, float %1)
154  ret float %2
155}
156