blob: 25364cf4e48d3ce263f0aa93349cfd378ca9ad34 [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:
Alex Bradbury0092df02019-01-25 21:55:48 +000027; RV32IFD-NEXT: lui a2, 524288
28; RV32IFD-NEXT: xor a1, a1, a2
Alex Bradbury38c4ec32019-01-25 14:33:08 +000029; RV32IFD-NEXT: ret
30;
31; RV64I-LABEL: fneg:
32; RV64I: # %bb.0:
33; RV64I-NEXT: addi a1, zero, -1
34; RV64I-NEXT: slli a1, a1, 63
35; RV64I-NEXT: xor a0, a0, a1
36; RV64I-NEXT: ret
37 %1 = fneg double %a
38 ret double %1
39}
40
41declare double @llvm.fabs.f64(double)
42
43define double @fabs(double %a) nounwind {
44; RV32I-LABEL: fabs:
45; RV32I: # %bb.0:
46; RV32I-NEXT: lui a2, 524288
47; RV32I-NEXT: addi a2, a2, -1
48; RV32I-NEXT: and a1, a1, a2
49; RV32I-NEXT: ret
50;
51; RV32IFD-LABEL: fabs:
52; RV32IFD: # %bb.0:
Alex Bradbury0092df02019-01-25 21:55:48 +000053; RV32IFD-NEXT: lui a2, 524288
54; RV32IFD-NEXT: addi a2, a2, -1
55; RV32IFD-NEXT: and a1, a1, a2
Alex Bradbury38c4ec32019-01-25 14:33:08 +000056; RV32IFD-NEXT: ret
57;
58; RV64I-LABEL: fabs:
59; RV64I: # %bb.0:
60; RV64I-NEXT: addi a1, zero, -1
61; RV64I-NEXT: slli a1, a1, 63
62; RV64I-NEXT: addi a1, a1, -1
63; RV64I-NEXT: and a0, a0, a1
64; RV64I-NEXT: ret
65 %1 = call double @llvm.fabs.f64(double %a)
66 ret double %1
67}
Alex Bradburyd7609102019-01-25 21:06:47 +000068
69declare double @llvm.copysign.f64(double, double)
70
71; DAGTypeLegalizer::SoftenFloatRes_FCOPYSIGN will convert to bitwise
72; operations if floating point isn't supported. A combine could be written to
73; do the same even when f64 is legal.
74
75define double @fcopysign_fneg(double %a, double %b) nounwind {
76; RV32I-LABEL: fcopysign_fneg:
77; RV32I: # %bb.0:
78; RV32I-NEXT: not a2, a3
79; RV32I-NEXT: lui a3, 524288
80; RV32I-NEXT: and a2, a2, a3
81; RV32I-NEXT: addi a3, a3, -1
82; RV32I-NEXT: and a1, a1, a3
83; RV32I-NEXT: or a1, a1, a2
84; RV32I-NEXT: ret
85;
86; RV32IFD-LABEL: fcopysign_fneg:
87; RV32IFD: # %bb.0:
88; RV32IFD-NEXT: addi sp, sp, -16
89; RV32IFD-NEXT: sw a2, 8(sp)
90; RV32IFD-NEXT: sw a3, 12(sp)
91; RV32IFD-NEXT: fld ft0, 8(sp)
92; RV32IFD-NEXT: sw a0, 8(sp)
93; RV32IFD-NEXT: sw a1, 12(sp)
94; RV32IFD-NEXT: fld ft1, 8(sp)
95; RV32IFD-NEXT: fsgnjn.d ft0, ft1, ft0
96; RV32IFD-NEXT: fsd ft0, 8(sp)
97; RV32IFD-NEXT: lw a0, 8(sp)
98; RV32IFD-NEXT: lw a1, 12(sp)
99; RV32IFD-NEXT: addi sp, sp, 16
100; RV32IFD-NEXT: ret
101;
102; RV64I-LABEL: fcopysign_fneg:
103; RV64I: # %bb.0:
104; RV64I-NEXT: addi a2, zero, -1
105; RV64I-NEXT: slli a2, a2, 63
106; RV64I-NEXT: not a1, a1
107; RV64I-NEXT: and a1, a1, a2
108; RV64I-NEXT: addi a2, a2, -1
109; RV64I-NEXT: and a0, a0, a2
110; RV64I-NEXT: or a0, a0, a1
111; RV64I-NEXT: ret
112 %1 = fneg double %b
113 %2 = call double @llvm.copysign.f64(double %a, double %1)
114 ret double %2
115}