blob: 4e0fbbd35d674dbf49f0e34861c7cac4116c7ea3 [file] [log] [blame]
Alex Bradbury38c4ec32019-01-25 14:33:08 +00001; 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=+d -verify-machineinstrs < %s \
5; RUN: | FileCheck -check-prefix=RV32IFD %s
6; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \
7; RUN: | FileCheck -check-prefix=RV64I %s
8;
9; This file tests cases where simple floating point operations can be
10; profitably handled though bit manipulation if a soft-float ABI is being used
11; (e.g. fneg implemented by XORing the sign bit). This is typically handled in
12; DAGCombiner::visitBITCAST, but this target-independent code may not trigger
13; in cases where we perform custom legalisation (e.g. RV32IFD).
14
15; TODO: Add an appropriate target-specific DAG combine that can handle
16; RISCVISD::SplitF64/BuildPairF64 used for RV32IFD.
17
18define double @fneg(double %a) nounwind {
19; RV32I-LABEL: fneg:
20; RV32I: # %bb.0:
21; RV32I-NEXT: lui a2, 524288
22; RV32I-NEXT: xor a1, a1, a2
23; RV32I-NEXT: ret
24;
25; RV32IFD-LABEL: fneg:
26; RV32IFD: # %bb.0:
27; RV32IFD-NEXT: addi sp, sp, -16
28; RV32IFD-NEXT: sw a0, 8(sp)
29; RV32IFD-NEXT: sw a1, 12(sp)
30; RV32IFD-NEXT: fld ft0, 8(sp)
31; RV32IFD-NEXT: fneg.d ft0, ft0
32; RV32IFD-NEXT: fsd ft0, 8(sp)
33; RV32IFD-NEXT: lw a0, 8(sp)
34; RV32IFD-NEXT: lw a1, 12(sp)
35; RV32IFD-NEXT: addi sp, sp, 16
36; RV32IFD-NEXT: ret
37;
38; RV64I-LABEL: fneg:
39; RV64I: # %bb.0:
40; RV64I-NEXT: addi a1, zero, -1
41; RV64I-NEXT: slli a1, a1, 63
42; RV64I-NEXT: xor a0, a0, a1
43; RV64I-NEXT: ret
44 %1 = fneg double %a
45 ret double %1
46}
47
48declare double @llvm.fabs.f64(double)
49
50define double @fabs(double %a) nounwind {
51; RV32I-LABEL: fabs:
52; RV32I: # %bb.0:
53; RV32I-NEXT: lui a2, 524288
54; RV32I-NEXT: addi a2, a2, -1
55; RV32I-NEXT: and a1, a1, a2
56; RV32I-NEXT: ret
57;
58; RV32IFD-LABEL: fabs:
59; RV32IFD: # %bb.0:
60; RV32IFD-NEXT: addi sp, sp, -16
61; RV32IFD-NEXT: sw a0, 8(sp)
62; RV32IFD-NEXT: sw a1, 12(sp)
63; RV32IFD-NEXT: fld ft0, 8(sp)
64; RV32IFD-NEXT: fabs.d ft0, ft0
65; RV32IFD-NEXT: fsd ft0, 8(sp)
66; RV32IFD-NEXT: lw a0, 8(sp)
67; RV32IFD-NEXT: lw a1, 12(sp)
68; RV32IFD-NEXT: addi sp, sp, 16
69; RV32IFD-NEXT: ret
70;
71; RV64I-LABEL: fabs:
72; RV64I: # %bb.0:
73; RV64I-NEXT: addi a1, zero, -1
74; RV64I-NEXT: slli a1, a1, 63
75; RV64I-NEXT: addi a1, a1, -1
76; RV64I-NEXT: and a0, a0, a1
77; RV64I-NEXT: ret
78 %1 = call double @llvm.fabs.f64(double %a)
79 ret double %1
80}
Alex Bradburyd7609102019-01-25 21:06:47 +000081
82declare double @llvm.copysign.f64(double, double)
83
84; DAGTypeLegalizer::SoftenFloatRes_FCOPYSIGN will convert to bitwise
85; operations if floating point isn't supported. A combine could be written to
86; do the same even when f64 is legal.
87
88define double @fcopysign_fneg(double %a, double %b) nounwind {
89; RV32I-LABEL: fcopysign_fneg:
90; RV32I: # %bb.0:
91; RV32I-NEXT: not a2, a3
92; RV32I-NEXT: lui a3, 524288
93; RV32I-NEXT: and a2, a2, a3
94; RV32I-NEXT: addi a3, a3, -1
95; RV32I-NEXT: and a1, a1, a3
96; RV32I-NEXT: or a1, a1, a2
97; RV32I-NEXT: ret
98;
99; RV32IFD-LABEL: fcopysign_fneg:
100; RV32IFD: # %bb.0:
101; RV32IFD-NEXT: addi sp, sp, -16
102; RV32IFD-NEXT: sw a2, 8(sp)
103; RV32IFD-NEXT: sw a3, 12(sp)
104; RV32IFD-NEXT: fld ft0, 8(sp)
105; RV32IFD-NEXT: sw a0, 8(sp)
106; RV32IFD-NEXT: sw a1, 12(sp)
107; RV32IFD-NEXT: fld ft1, 8(sp)
108; RV32IFD-NEXT: fsgnjn.d ft0, ft1, ft0
109; RV32IFD-NEXT: fsd ft0, 8(sp)
110; RV32IFD-NEXT: lw a0, 8(sp)
111; RV32IFD-NEXT: lw a1, 12(sp)
112; RV32IFD-NEXT: addi sp, sp, 16
113; RV32IFD-NEXT: ret
114;
115; RV64I-LABEL: fcopysign_fneg:
116; RV64I: # %bb.0:
117; RV64I-NEXT: addi a2, zero, -1
118; RV64I-NEXT: slli a2, a2, 63
119; RV64I-NEXT: not a1, a1
120; RV64I-NEXT: and a1, a1, a2
121; RV64I-NEXT: addi a2, a2, -1
122; RV64I-NEXT: and a0, a0, a2
123; RV64I-NEXT: or a0, a0, a1
124; RV64I-NEXT: ret
125 %1 = fneg double %b
126 %2 = call double @llvm.copysign.f64(double %a, double %1)
127 ret double %2
128}