• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc -mtriple=riscv32 -mattr=+d -verify-machineinstrs < %s \
3; RUN:   | FileCheck -check-prefix=RV32IFD %s
4
5define double @fld(double *%a) nounwind {
6; RV32IFD-LABEL: fld:
7; RV32IFD:       # %bb.0:
8; RV32IFD-NEXT:    addi sp, sp, -16
9; RV32IFD-NEXT:    fld ft0, 24(a0)
10; RV32IFD-NEXT:    fld ft1, 0(a0)
11; RV32IFD-NEXT:    fadd.d ft0, ft1, ft0
12; RV32IFD-NEXT:    fsd ft0, 8(sp)
13; RV32IFD-NEXT:    lw a0, 8(sp)
14; RV32IFD-NEXT:    lw a1, 12(sp)
15; RV32IFD-NEXT:    addi sp, sp, 16
16; RV32IFD-NEXT:    ret
17  %1 = load double, double* %a
18  %2 = getelementptr double, double* %a, i32 3
19  %3 = load double, double* %2
20; Use both loaded values in an FP op to ensure an fld is used, even for the
21; soft float ABI
22  %4 = fadd double %1, %3
23  ret double %4
24}
25
26define void @fsd(double *%a, double %b, double %c) nounwind {
27; RV32IFD-LABEL: fsd:
28; RV32IFD:       # %bb.0:
29; RV32IFD-NEXT:    addi sp, sp, -16
30; RV32IFD-NEXT:    sw a3, 8(sp)
31; RV32IFD-NEXT:    sw a4, 12(sp)
32; RV32IFD-NEXT:    fld ft0, 8(sp)
33; RV32IFD-NEXT:    sw a1, 8(sp)
34; RV32IFD-NEXT:    sw a2, 12(sp)
35; RV32IFD-NEXT:    fld ft1, 8(sp)
36; RV32IFD-NEXT:    fadd.d ft0, ft1, ft0
37; RV32IFD-NEXT:    fsd ft0, 64(a0)
38; RV32IFD-NEXT:    fsd ft0, 0(a0)
39; RV32IFD-NEXT:    addi sp, sp, 16
40; RV32IFD-NEXT:    ret
41; Use %b and %c in an FP op to ensure floating point registers are used, even
42; for the soft float ABI
43  %1 = fadd double %b, %c
44  store double %1, double* %a
45  %2 = getelementptr double, double* %a, i32 8
46  store double %1, double* %2
47  ret void
48}
49
50; Check load and store to a global
51@G = global double 0.0
52
53define double @fld_fsd_global(double %a, double %b) nounwind {
54; RV32IFD-LABEL: fld_fsd_global:
55; RV32IFD:       # %bb.0:
56; RV32IFD-NEXT:    addi sp, sp, -16
57; RV32IFD-NEXT:    sw a2, 8(sp)
58; RV32IFD-NEXT:    sw a3, 12(sp)
59; RV32IFD-NEXT:    fld ft0, 8(sp)
60; RV32IFD-NEXT:    sw a0, 8(sp)
61; RV32IFD-NEXT:    sw a1, 12(sp)
62; RV32IFD-NEXT:    fld ft1, 8(sp)
63; RV32IFD-NEXT:    fadd.d ft0, ft1, ft0
64; RV32IFD-NEXT:    lui a0, %hi(G)
65; RV32IFD-NEXT:    fld ft1, %lo(G)(a0)
66; RV32IFD-NEXT:    fsd ft0, %lo(G)(a0)
67; RV32IFD-NEXT:    addi a0, a0, %lo(G)
68; RV32IFD-NEXT:    fld ft1, 72(a0)
69; RV32IFD-NEXT:    fsd ft0, 72(a0)
70; RV32IFD-NEXT:    fsd ft0, 8(sp)
71; RV32IFD-NEXT:    lw a0, 8(sp)
72; RV32IFD-NEXT:    lw a1, 12(sp)
73; RV32IFD-NEXT:    addi sp, sp, 16
74; RV32IFD-NEXT:    ret
75; Use %a and %b in an FP op to ensure floating point registers are used, even
76; for the soft float ABI
77  %1 = fadd double %a, %b
78  %2 = load volatile double, double* @G
79  store double %1, double* @G
80  %3 = getelementptr double, double* @G, i32 9
81  %4 = load volatile double, double* %3
82  store double %1, double* %3
83  ret double %1
84}
85
86; Ensure that 1 is added to the high 20 bits if bit 11 of the low part is 1
87define double @fld_fsd_constant(double %a) nounwind {
88; RV32IFD-LABEL: fld_fsd_constant:
89; RV32IFD:       # %bb.0:
90; RV32IFD-NEXT:    addi sp, sp, -16
91; RV32IFD-NEXT:    sw a0, 8(sp)
92; RV32IFD-NEXT:    sw a1, 12(sp)
93; RV32IFD-NEXT:    fld ft0, 8(sp)
94; RV32IFD-NEXT:    lui a0, 912092
95; RV32IFD-NEXT:    fld ft1, -273(a0)
96; RV32IFD-NEXT:    fadd.d ft0, ft0, ft1
97; RV32IFD-NEXT:    fsd ft0, -273(a0)
98; RV32IFD-NEXT:    fsd ft0, 8(sp)
99; RV32IFD-NEXT:    lw a0, 8(sp)
100; RV32IFD-NEXT:    lw a1, 12(sp)
101; RV32IFD-NEXT:    addi sp, sp, 16
102; RV32IFD-NEXT:    ret
103  %1 = inttoptr i32 3735928559 to double*
104  %2 = load volatile double, double* %1
105  %3 = fadd double %a, %2
106  store double %3, double* %1
107  ret double %3
108}
109
110declare void @notdead(i8*)
111
112define double @fld_stack(double %a) nounwind {
113; RV32IFD-LABEL: fld_stack:
114; RV32IFD:       # %bb.0:
115; RV32IFD-NEXT:    addi sp, sp, -32
116; RV32IFD-NEXT:    sw ra, 28(sp)
117; RV32IFD-NEXT:    sw s1, 24(sp)
118; RV32IFD-NEXT:    sw s2, 20(sp)
119; RV32IFD-NEXT:    mv s2, a1
120; RV32IFD-NEXT:    mv s1, a0
121; RV32IFD-NEXT:    addi a0, sp, 8
122; RV32IFD-NEXT:    call notdead
123; RV32IFD-NEXT:    sw s1, 0(sp)
124; RV32IFD-NEXT:    sw s2, 4(sp)
125; RV32IFD-NEXT:    fld ft0, 0(sp)
126; RV32IFD-NEXT:    fld ft1, 8(sp)
127; RV32IFD-NEXT:    fadd.d ft0, ft1, ft0
128; RV32IFD-NEXT:    fsd ft0, 0(sp)
129; RV32IFD-NEXT:    lw a0, 0(sp)
130; RV32IFD-NEXT:    lw a1, 4(sp)
131; RV32IFD-NEXT:    lw s2, 20(sp)
132; RV32IFD-NEXT:    lw s1, 24(sp)
133; RV32IFD-NEXT:    lw ra, 28(sp)
134; RV32IFD-NEXT:    addi sp, sp, 32
135; RV32IFD-NEXT:    ret
136  %1 = alloca double, align 8
137  %2 = bitcast double* %1 to i8*
138  call void @notdead(i8* %2)
139  %3 = load double, double* %1
140  %4 = fadd double %3, %a ; force load in to FPR64
141  ret double %4
142}
143
144define void @fsd_stack(double %a, double %b) nounwind {
145; RV32IFD-LABEL: fsd_stack:
146; RV32IFD:       # %bb.0:
147; RV32IFD-NEXT:    addi sp, sp, -32
148; RV32IFD-NEXT:    sw ra, 28(sp)
149; RV32IFD-NEXT:    sw a2, 8(sp)
150; RV32IFD-NEXT:    sw a3, 12(sp)
151; RV32IFD-NEXT:    fld ft0, 8(sp)
152; RV32IFD-NEXT:    sw a0, 8(sp)
153; RV32IFD-NEXT:    sw a1, 12(sp)
154; RV32IFD-NEXT:    fld ft1, 8(sp)
155; RV32IFD-NEXT:    fadd.d ft0, ft1, ft0
156; RV32IFD-NEXT:    fsd ft0, 16(sp)
157; RV32IFD-NEXT:    addi a0, sp, 16
158; RV32IFD-NEXT:    call notdead
159; RV32IFD-NEXT:    lw ra, 28(sp)
160; RV32IFD-NEXT:    addi sp, sp, 32
161; RV32IFD-NEXT:    ret
162  %1 = fadd double %a, %b ; force store from FPR64
163  %2 = alloca double, align 8
164  store double %1, double* %2
165  %3 = bitcast double* %2 to i8*
166  call void @notdead(i8* %3)
167  ret void
168}
169
170; Test selection of store<ST4[%a], trunc to f32>, ..
171define void @fsd_trunc(float* %a, double %b) nounwind noinline optnone {
172; RV32IFD-LABEL: fsd_trunc:
173; RV32IFD:       # %bb.0:
174; RV32IFD-NEXT:    addi sp, sp, -16
175; RV32IFD-NEXT:    sw a1, 8(sp)
176; RV32IFD-NEXT:    sw a2, 12(sp)
177; RV32IFD-NEXT:    fld ft0, 8(sp)
178; RV32IFD-NEXT:    fcvt.s.d ft0, ft0
179; RV32IFD-NEXT:    fsw ft0, 0(a0)
180; RV32IFD-NEXT:    addi sp, sp, 16
181; RV32IFD-NEXT:    ret
182  %1 = fptrunc double %b to float
183  store float %1, float* %a, align 4
184  ret void
185}
186