1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc -mtriple=riscv32 -mattr=+f -verify-machineinstrs < %s \
3; RUN:   | FileCheck -check-prefix=RV32IF %s
4
5define float @flw(float *%a) nounwind {
6; RV32IF-LABEL: flw:
7; RV32IF:       # %bb.0:
8; RV32IF-NEXT:    flw ft0, 12(a0)
9; RV32IF-NEXT:    flw ft1, 0(a0)
10; RV32IF-NEXT:    fadd.s ft0, ft1, ft0
11; RV32IF-NEXT:    fmv.x.w a0, ft0
12; RV32IF-NEXT:    ret
13  %1 = load float, float* %a
14  %2 = getelementptr float, float* %a, i32 3
15  %3 = load float, float* %2
16; Use both loaded values in an FP op to ensure an flw is used, even for the
17; soft float ABI
18  %4 = fadd float %1, %3
19  ret float %4
20}
21
22define void @fsw(float *%a, float %b, float %c) nounwind {
23; Use %b and %c in an FP op to ensure floating point registers are used, even
24; for the soft float ABI
25; RV32IF-LABEL: fsw:
26; RV32IF:       # %bb.0:
27; RV32IF-NEXT:    fmv.w.x ft0, a2
28; RV32IF-NEXT:    fmv.w.x ft1, a1
29; RV32IF-NEXT:    fadd.s ft0, ft1, ft0
30; RV32IF-NEXT:    fsw ft0, 32(a0)
31; RV32IF-NEXT:    fsw ft0, 0(a0)
32; RV32IF-NEXT:    ret
33  %1 = fadd float %b, %c
34  store float %1, float* %a
35  %2 = getelementptr float, float* %a, i32 8
36  store float %1, float* %2
37  ret void
38}
39
40; Check load and store to a global
41@G = global float 0.0
42
43define float @flw_fsw_global(float %a, float %b) nounwind {
44; Use %a and %b in an FP op to ensure floating point registers are used, even
45; for the soft float ABI
46; RV32IF-LABEL: flw_fsw_global:
47; RV32IF:       # %bb.0:
48; RV32IF-NEXT:    fmv.w.x ft0, a1
49; RV32IF-NEXT:    fmv.w.x ft1, a0
50; RV32IF-NEXT:    fadd.s ft0, ft1, ft0
51; RV32IF-NEXT:    lui a0, %hi(G)
52; RV32IF-NEXT:    flw ft1, %lo(G)(a0)
53; RV32IF-NEXT:    fsw ft0, %lo(G)(a0)
54; RV32IF-NEXT:    lui a0, %hi(G+36)
55; RV32IF-NEXT:    flw ft1, %lo(G+36)(a0)
56; RV32IF-NEXT:    fsw ft0, %lo(G+36)(a0)
57; RV32IF-NEXT:    fmv.x.w a0, ft0
58; RV32IF-NEXT:    ret
59  %1 = fadd float %a, %b
60  %2 = load volatile float, float* @G
61  store float %1, float* @G
62  %3 = getelementptr float, float* @G, i32 9
63  %4 = load volatile float, float* %3
64  store float %1, float* %3
65  ret float %1
66}
67
68; Ensure that 1 is added to the high 20 bits if bit 11 of the low part is 1
69define float @flw_fsw_constant(float %a) nounwind {
70; RV32IF-LABEL: flw_fsw_constant:
71; RV32IF:       # %bb.0:
72; RV32IF-NEXT:    fmv.w.x ft0, a0
73; RV32IF-NEXT:    lui a0, 912092
74; RV32IF-NEXT:    flw ft1, -273(a0)
75; RV32IF-NEXT:    fadd.s ft0, ft0, ft1
76; RV32IF-NEXT:    fsw ft0, -273(a0)
77; RV32IF-NEXT:    fmv.x.w a0, ft0
78; RV32IF-NEXT:    ret
79  %1 = inttoptr i32 3735928559 to float*
80  %2 = load volatile float, float* %1
81  %3 = fadd float %a, %2
82  store float %3, float* %1
83  ret float %3
84}
85
86declare void @notdead(i8*)
87
88define float @flw_stack(float %a) nounwind {
89; RV32IF-LABEL: flw_stack:
90; RV32IF:       # %bb.0:
91; RV32IF-NEXT:    addi sp, sp, -16
92; RV32IF-NEXT:    sw ra, 12(sp)
93; RV32IF-NEXT:    sw s1, 8(sp)
94; RV32IF-NEXT:    mv s1, a0
95; RV32IF-NEXT:    lui a0, %hi(notdead)
96; RV32IF-NEXT:    addi a1, a0, %lo(notdead)
97; RV32IF-NEXT:    addi a0, sp, 4
98; RV32IF-NEXT:    jalr a1
99; RV32IF-NEXT:    fmv.w.x ft0, s1
100; RV32IF-NEXT:    flw ft1, 4(sp)
101; RV32IF-NEXT:    fadd.s ft0, ft1, ft0
102; RV32IF-NEXT:    fmv.x.w a0, ft0
103; RV32IF-NEXT:    lw s1, 8(sp)
104; RV32IF-NEXT:    lw ra, 12(sp)
105; RV32IF-NEXT:    addi sp, sp, 16
106; RV32IF-NEXT:    ret
107  %1 = alloca float, align 4
108  %2 = bitcast float* %1 to i8*
109  call void @notdead(i8* %2)
110  %3 = load float, float* %1
111  %4 = fadd float %3, %a ; force load in to FPR32
112  ret float %4
113}
114
115define void @fsw_stack(float %a, float %b) nounwind {
116; RV32IF-LABEL: fsw_stack:
117; RV32IF:       # %bb.0:
118; RV32IF-NEXT:    addi sp, sp, -16
119; RV32IF-NEXT:    sw ra, 12(sp)
120; RV32IF-NEXT:    fmv.w.x ft0, a1
121; RV32IF-NEXT:    fmv.w.x ft1, a0
122; RV32IF-NEXT:    fadd.s ft0, ft1, ft0
123; RV32IF-NEXT:    fsw ft0, 8(sp)
124; RV32IF-NEXT:    lui a0, %hi(notdead)
125; RV32IF-NEXT:    addi a1, a0, %lo(notdead)
126; RV32IF-NEXT:    addi a0, sp, 8
127; RV32IF-NEXT:    jalr a1
128; RV32IF-NEXT:    lw ra, 12(sp)
129; RV32IF-NEXT:    addi sp, sp, 16
130; RV32IF-NEXT:    ret
131  %1 = fadd float %a, %b ; force store from FPR32
132  %2 = alloca float, align 4
133  store float %1, float* %2
134  %3 = bitcast float* %2 to i8*
135  call void @notdead(i8* %3)
136  ret void
137}
138