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: -target-abi=ilp32f | FileCheck -check-prefixes=CHECKIF,RV32IF %s 4; RUN: llc -mtriple=riscv64 -mattr=+f -verify-machineinstrs < %s \ 5; RUN: -target-abi=lp64f | FileCheck -check-prefixes=CHECKIF,RV64IF %s 6; RUN: llc -mtriple=riscv32 -mattr=+zfinx -verify-machineinstrs < %s \ 7; RUN: -target-abi=ilp32 | FileCheck -check-prefixes=CHECKIZFINX,RV32IZFINX %s 8; RUN: llc -mtriple=riscv64 -mattr=+zfinx -verify-machineinstrs < %s \ 9; RUN: -target-abi=lp64 | FileCheck -check-prefixes=CHECKIZFINX,RV64IZFINX %s 10 11define dso_local float @flw(ptr %a) nounwind { 12; CHECKIF-LABEL: flw: 13; CHECKIF: # %bb.0: 14; CHECKIF-NEXT: flw fa5, 0(a0) 15; CHECKIF-NEXT: flw fa4, 12(a0) 16; CHECKIF-NEXT: fadd.s fa0, fa5, fa4 17; CHECKIF-NEXT: ret 18; 19; CHECKIZFINX-LABEL: flw: 20; CHECKIZFINX: # %bb.0: 21; CHECKIZFINX-NEXT: lw a1, 0(a0) 22; CHECKIZFINX-NEXT: lw a0, 12(a0) 23; CHECKIZFINX-NEXT: fadd.s a0, a1, a0 24; CHECKIZFINX-NEXT: ret 25 %1 = load float, ptr %a 26 %2 = getelementptr float, ptr %a, i32 3 27 %3 = load float, ptr %2 28; Use both loaded values in an FP op to ensure an flw is used, even for the 29; soft float ABI 30 %4 = fadd float %1, %3 31 ret float %4 32} 33 34define dso_local void @fsw(ptr %a, float %b, float %c) nounwind { 35; Use %b and %c in an FP op to ensure floating point registers are used, even 36; for the soft float ABI 37; CHECKIF-LABEL: fsw: 38; CHECKIF: # %bb.0: 39; CHECKIF-NEXT: fadd.s fa5, fa0, fa1 40; CHECKIF-NEXT: fsw fa5, 0(a0) 41; CHECKIF-NEXT: fsw fa5, 32(a0) 42; CHECKIF-NEXT: ret 43; 44; CHECKIZFINX-LABEL: fsw: 45; CHECKIZFINX: # %bb.0: 46; CHECKIZFINX-NEXT: fadd.s a1, a1, a2 47; CHECKIZFINX-NEXT: sw a1, 0(a0) 48; CHECKIZFINX-NEXT: sw a1, 32(a0) 49; CHECKIZFINX-NEXT: ret 50 %1 = fadd float %b, %c 51 store float %1, ptr %a 52 %2 = getelementptr float, ptr %a, i32 8 53 store float %1, ptr %2 54 ret void 55} 56 57; Check load and store to a global 58@G = dso_local global float 0.0 59 60define dso_local float @flw_fsw_global(float %a, float %b) nounwind { 61; Use %a and %b in an FP op to ensure floating point registers are used, even 62; for the soft float ABI 63; CHECKIF-LABEL: flw_fsw_global: 64; CHECKIF: # %bb.0: 65; CHECKIF-NEXT: fadd.s fa0, fa0, fa1 66; CHECKIF-NEXT: lui a0, %hi(G) 67; CHECKIF-NEXT: flw fa5, %lo(G)(a0) 68; CHECKIF-NEXT: addi a1, a0, %lo(G) 69; CHECKIF-NEXT: fsw fa0, %lo(G)(a0) 70; CHECKIF-NEXT: flw fa5, 36(a1) 71; CHECKIF-NEXT: fsw fa0, 36(a1) 72; CHECKIF-NEXT: ret 73; 74; CHECKIZFINX-LABEL: flw_fsw_global: 75; CHECKIZFINX: # %bb.0: 76; CHECKIZFINX-NEXT: fadd.s a0, a0, a1 77; CHECKIZFINX-NEXT: lui a1, %hi(G) 78; CHECKIZFINX-NEXT: lw zero, %lo(G)(a1) 79; CHECKIZFINX-NEXT: addi a2, a1, %lo(G) 80; CHECKIZFINX-NEXT: sw a0, %lo(G)(a1) 81; CHECKIZFINX-NEXT: lw zero, 36(a2) 82; CHECKIZFINX-NEXT: sw a0, 36(a2) 83; CHECKIZFINX-NEXT: ret 84 %1 = fadd float %a, %b 85 %2 = load volatile float, ptr @G 86 store float %1, ptr @G 87 %3 = getelementptr float, ptr @G, i32 9 88 %4 = load volatile float, ptr %3 89 store float %1, ptr %3 90 ret float %1 91} 92 93; Ensure that 1 is added to the high 20 bits if bit 11 of the low part is 1 94define dso_local float @flw_fsw_constant(float %a) nounwind { 95; RV32IF-LABEL: flw_fsw_constant: 96; RV32IF: # %bb.0: 97; RV32IF-NEXT: lui a0, 912092 98; RV32IF-NEXT: flw fa5, -273(a0) 99; RV32IF-NEXT: fadd.s fa0, fa0, fa5 100; RV32IF-NEXT: fsw fa0, -273(a0) 101; RV32IF-NEXT: ret 102; 103; RV64IF-LABEL: flw_fsw_constant: 104; RV64IF: # %bb.0: 105; RV64IF-NEXT: lui a0, 228023 106; RV64IF-NEXT: slli a0, a0, 2 107; RV64IF-NEXT: flw fa5, -273(a0) 108; RV64IF-NEXT: fadd.s fa0, fa0, fa5 109; RV64IF-NEXT: fsw fa0, -273(a0) 110; RV64IF-NEXT: ret 111; 112; RV32IZFINX-LABEL: flw_fsw_constant: 113; RV32IZFINX: # %bb.0: 114; RV32IZFINX-NEXT: lui a1, 912092 115; RV32IZFINX-NEXT: lw a2, -273(a1) 116; RV32IZFINX-NEXT: fadd.s a0, a0, a2 117; RV32IZFINX-NEXT: sw a0, -273(a1) 118; RV32IZFINX-NEXT: ret 119; 120; RV64IZFINX-LABEL: flw_fsw_constant: 121; RV64IZFINX: # %bb.0: 122; RV64IZFINX-NEXT: lui a1, 228023 123; RV64IZFINX-NEXT: slli a1, a1, 2 124; RV64IZFINX-NEXT: lw a2, -273(a1) 125; RV64IZFINX-NEXT: fadd.s a0, a0, a2 126; RV64IZFINX-NEXT: sw a0, -273(a1) 127; RV64IZFINX-NEXT: ret 128 %1 = inttoptr i32 3735928559 to ptr 129 %2 = load volatile float, ptr %1 130 %3 = fadd float %a, %2 131 store float %3, ptr %1 132 ret float %3 133} 134 135declare void @notdead(ptr) 136 137define dso_local float @flw_stack(float %a) nounwind { 138; RV32IF-LABEL: flw_stack: 139; RV32IF: # %bb.0: 140; RV32IF-NEXT: addi sp, sp, -16 141; RV32IF-NEXT: sw ra, 12(sp) # 4-byte Folded Spill 142; RV32IF-NEXT: fsw fs0, 8(sp) # 4-byte Folded Spill 143; RV32IF-NEXT: fmv.s fs0, fa0 144; RV32IF-NEXT: addi a0, sp, 4 145; RV32IF-NEXT: call notdead 146; RV32IF-NEXT: flw fa5, 4(sp) 147; RV32IF-NEXT: fadd.s fa0, fa5, fs0 148; RV32IF-NEXT: lw ra, 12(sp) # 4-byte Folded Reload 149; RV32IF-NEXT: flw fs0, 8(sp) # 4-byte Folded Reload 150; RV32IF-NEXT: addi sp, sp, 16 151; RV32IF-NEXT: ret 152; 153; RV64IF-LABEL: flw_stack: 154; RV64IF: # %bb.0: 155; RV64IF-NEXT: addi sp, sp, -16 156; RV64IF-NEXT: sd ra, 8(sp) # 8-byte Folded Spill 157; RV64IF-NEXT: fsw fs0, 4(sp) # 4-byte Folded Spill 158; RV64IF-NEXT: fmv.s fs0, fa0 159; RV64IF-NEXT: mv a0, sp 160; RV64IF-NEXT: call notdead 161; RV64IF-NEXT: flw fa5, 0(sp) 162; RV64IF-NEXT: fadd.s fa0, fa5, fs0 163; RV64IF-NEXT: ld ra, 8(sp) # 8-byte Folded Reload 164; RV64IF-NEXT: flw fs0, 4(sp) # 4-byte Folded Reload 165; RV64IF-NEXT: addi sp, sp, 16 166; RV64IF-NEXT: ret 167; 168; RV32IZFINX-LABEL: flw_stack: 169; RV32IZFINX: # %bb.0: 170; RV32IZFINX-NEXT: addi sp, sp, -16 171; RV32IZFINX-NEXT: sw ra, 12(sp) # 4-byte Folded Spill 172; RV32IZFINX-NEXT: sw s0, 8(sp) # 4-byte Folded Spill 173; RV32IZFINX-NEXT: mv s0, a0 174; RV32IZFINX-NEXT: addi a0, sp, 4 175; RV32IZFINX-NEXT: call notdead 176; RV32IZFINX-NEXT: lw a0, 4(sp) 177; RV32IZFINX-NEXT: fadd.s a0, a0, s0 178; RV32IZFINX-NEXT: lw ra, 12(sp) # 4-byte Folded Reload 179; RV32IZFINX-NEXT: lw s0, 8(sp) # 4-byte Folded Reload 180; RV32IZFINX-NEXT: addi sp, sp, 16 181; RV32IZFINX-NEXT: ret 182; 183; RV64IZFINX-LABEL: flw_stack: 184; RV64IZFINX: # %bb.0: 185; RV64IZFINX-NEXT: addi sp, sp, -32 186; RV64IZFINX-NEXT: sd ra, 24(sp) # 8-byte Folded Spill 187; RV64IZFINX-NEXT: sd s0, 16(sp) # 8-byte Folded Spill 188; RV64IZFINX-NEXT: mv s0, a0 189; RV64IZFINX-NEXT: addi a0, sp, 12 190; RV64IZFINX-NEXT: call notdead 191; RV64IZFINX-NEXT: lw a0, 12(sp) 192; RV64IZFINX-NEXT: fadd.s a0, a0, s0 193; RV64IZFINX-NEXT: ld ra, 24(sp) # 8-byte Folded Reload 194; RV64IZFINX-NEXT: ld s0, 16(sp) # 8-byte Folded Reload 195; RV64IZFINX-NEXT: addi sp, sp, 32 196; RV64IZFINX-NEXT: ret 197 %1 = alloca float, align 4 198 call void @notdead(ptr %1) 199 %2 = load float, ptr %1 200 %3 = fadd float %2, %a ; force load in to FPR32 201 ret float %3 202} 203 204define dso_local void @fsw_stack(float %a, float %b) nounwind { 205; RV32IF-LABEL: fsw_stack: 206; RV32IF: # %bb.0: 207; RV32IF-NEXT: addi sp, sp, -16 208; RV32IF-NEXT: sw ra, 12(sp) # 4-byte Folded Spill 209; RV32IF-NEXT: fadd.s fa5, fa0, fa1 210; RV32IF-NEXT: fsw fa5, 8(sp) 211; RV32IF-NEXT: addi a0, sp, 8 212; RV32IF-NEXT: call notdead 213; RV32IF-NEXT: lw ra, 12(sp) # 4-byte Folded Reload 214; RV32IF-NEXT: addi sp, sp, 16 215; RV32IF-NEXT: ret 216; 217; RV64IF-LABEL: fsw_stack: 218; RV64IF: # %bb.0: 219; RV64IF-NEXT: addi sp, sp, -16 220; RV64IF-NEXT: sd ra, 8(sp) # 8-byte Folded Spill 221; RV64IF-NEXT: fadd.s fa5, fa0, fa1 222; RV64IF-NEXT: fsw fa5, 4(sp) 223; RV64IF-NEXT: addi a0, sp, 4 224; RV64IF-NEXT: call notdead 225; RV64IF-NEXT: ld ra, 8(sp) # 8-byte Folded Reload 226; RV64IF-NEXT: addi sp, sp, 16 227; RV64IF-NEXT: ret 228; 229; RV32IZFINX-LABEL: fsw_stack: 230; RV32IZFINX: # %bb.0: 231; RV32IZFINX-NEXT: addi sp, sp, -16 232; RV32IZFINX-NEXT: sw ra, 12(sp) # 4-byte Folded Spill 233; RV32IZFINX-NEXT: fadd.s a0, a0, a1 234; RV32IZFINX-NEXT: sw a0, 8(sp) 235; RV32IZFINX-NEXT: addi a0, sp, 8 236; RV32IZFINX-NEXT: call notdead 237; RV32IZFINX-NEXT: lw ra, 12(sp) # 4-byte Folded Reload 238; RV32IZFINX-NEXT: addi sp, sp, 16 239; RV32IZFINX-NEXT: ret 240; 241; RV64IZFINX-LABEL: fsw_stack: 242; RV64IZFINX: # %bb.0: 243; RV64IZFINX-NEXT: addi sp, sp, -16 244; RV64IZFINX-NEXT: sd ra, 8(sp) # 8-byte Folded Spill 245; RV64IZFINX-NEXT: fadd.s a0, a0, a1 246; RV64IZFINX-NEXT: sw a0, 4(sp) 247; RV64IZFINX-NEXT: addi a0, sp, 4 248; RV64IZFINX-NEXT: call notdead 249; RV64IZFINX-NEXT: ld ra, 8(sp) # 8-byte Folded Reload 250; RV64IZFINX-NEXT: addi sp, sp, 16 251; RV64IZFINX-NEXT: ret 252 %1 = fadd float %a, %b ; force store from FPR32 253 %2 = alloca float, align 4 254 store float %1, ptr %2 255 call void @notdead(ptr %2) 256 ret void 257} 258