• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:    lui a1, 524288
51; RV32I-NEXT:    addi a1, a1, -1
52; RV32I-NEXT:    and a0, a0, a1
53; RV32I-NEXT:    ret
54;
55; RV32IF-LABEL: fabs:
56; RV32IF:       # %bb.0:
57; RV32IF-NEXT:    lui a1, 524288
58; RV32IF-NEXT:    addi a1, a1, -1
59; RV32IF-NEXT:    and a0, a0, a1
60; RV32IF-NEXT:    ret
61;
62; RV64I-LABEL: fabs:
63; RV64I:       # %bb.0:
64; RV64I-NEXT:    lui a1, 524288
65; RV64I-NEXT:    addiw a1, a1, -1
66; RV64I-NEXT:    and a0, a0, a1
67; RV64I-NEXT:    ret
68;
69; RV64IF-LABEL: fabs:
70; RV64IF:       # %bb.0:
71; RV64IF-NEXT:    lui a1, 524288
72; RV64IF-NEXT:    addiw a1, a1, -1
73; RV64IF-NEXT:    and a0, a0, a1
74; RV64IF-NEXT:    ret
75  %1 = call float @llvm.fabs.f32(float %a)
76  ret float %1
77}
78
79declare float @llvm.copysign.f32(float, float)
80
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.
84
85define float @fcopysign_fneg(float %a, float %b) nounwind {
86; RV32I-LABEL: fcopysign_fneg:
87; RV32I:       # %bb.0:
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
94; RV32I-NEXT:    ret
95;
96; RV32IF-LABEL: fcopysign_fneg:
97; RV32IF:       # %bb.0:
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
104; RV32IF-NEXT:    ret
105;
106; RV64I-LABEL: fcopysign_fneg:
107; RV64I:       # %bb.0:
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
114; RV64I-NEXT:    ret
115;
116; RV64IF-LABEL: fcopysign_fneg:
117; RV64IF:       # %bb.0:
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
122; RV64IF-NEXT:    ret
123  %1 = fneg float %b
124  %2 = call float @llvm.copysign.f32(float %a, float %1)
125  ret float %2
126}
127