Skip to content

Commit 0b2803e

Browse files
committed
[RISCV] Add codegen support for ilp32f, ilp32d, lp64f, and lp64d ("hard float") ABIs
This patch adds support for the RISC-V hard float ABIs, building on top of rL355771, which added basic target-abi parsing and MC layer support. It also builds on some re-organisations and expansion of the upstream ABI and calling convention tests which were recently committed directly upstream. A number of aspects of the RISC-V float hard float ABIs require frontend support (e.g. flattening of structs and passing int+fp for fp+fp structs in a pair of registers), and will be addressed in a Clang patch. As can be seen from the tests, it would be worthwhile extending RISCVMergeBaseOffsets to handle constant pool as well as global accesses. Differential Revision: https://reviews.llvm.org/D59357 llvm-svn: 357352
1 parent 10c9032 commit 0b2803e

14 files changed

+869
-39
lines changed

llvm/lib/Target/RISCV/RISCVCallingConv.td

+8
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,14 @@
1616
def CSR_ILP32_LP64
1717
: CalleeSavedRegs<(add X1, X3, X4, X8, X9, (sequence "X%u", 18, 27))>;
1818

19+
def CSR_ILP32F_LP64F
20+
: CalleeSavedRegs<(add CSR_ILP32_LP64,
21+
F8_32, F9_32, (sequence "F%u_32", 18, 27))>;
22+
23+
def CSR_ILP32D_LP64D
24+
: CalleeSavedRegs<(add CSR_ILP32_LP64,
25+
F8_64, F9_64, (sequence "F%u_64", 18, 27))>;
26+
1927
// Needed for implementation of RISCVRegisterInfo::getNoPreservedMask()
2028
def CSR_NoRegs : CalleeSavedRegs<(add)>;
2129

llvm/lib/Target/RISCV/RISCVISelLowering.cpp

+92-15
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,17 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
4949
RISCVABI::ABI ABI = Subtarget.getTargetABI();
5050
assert(ABI != RISCVABI::ABI_Unknown && "Improperly initialised target ABI");
5151

52-
if (ABI != RISCVABI::ABI_ILP32 && ABI != RISCVABI::ABI_LP64)
52+
switch (ABI) {
53+
default:
5354
report_fatal_error("Don't know how to lower this ABI");
55+
case RISCVABI::ABI_ILP32:
56+
case RISCVABI::ABI_ILP32F:
57+
case RISCVABI::ABI_ILP32D:
58+
case RISCVABI::ABI_LP64:
59+
case RISCVABI::ABI_LP64F:
60+
case RISCVABI::ABI_LP64D:
61+
break;
62+
}
5463

5564
MVT XLenVT = Subtarget.getXLenVT();
5665

@@ -981,6 +990,14 @@ static const MCPhysReg ArgGPRs[] = {
981990
RISCV::X10, RISCV::X11, RISCV::X12, RISCV::X13,
982991
RISCV::X14, RISCV::X15, RISCV::X16, RISCV::X17
983992
};
993+
static const MCPhysReg ArgFPR32s[] = {
994+
RISCV::F10_32, RISCV::F11_32, RISCV::F12_32, RISCV::F13_32,
995+
RISCV::F14_32, RISCV::F15_32, RISCV::F16_32, RISCV::F17_32
996+
};
997+
static const MCPhysReg ArgFPR64s[] = {
998+
RISCV::F10_64, RISCV::F11_64, RISCV::F12_64, RISCV::F13_64,
999+
RISCV::F14_64, RISCV::F15_64, RISCV::F16_64, RISCV::F17_64
1000+
};
9841001

9851002
// Pass a 2*XLEN argument that has been split into two XLEN values through
9861003
// registers or the stack as necessary.
@@ -1021,9 +1038,10 @@ static bool CC_RISCVAssign2XLen(unsigned XLen, CCState &State, CCValAssign VA1,
10211038
}
10221039

10231040
// Implements the RISC-V calling convention. Returns true upon failure.
1024-
static bool CC_RISCV(const DataLayout &DL, unsigned ValNo, MVT ValVT, MVT LocVT,
1025-
CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags,
1026-
CCState &State, bool IsFixed, bool IsRet, Type *OrigTy) {
1041+
static bool CC_RISCV(const DataLayout &DL, RISCVABI::ABI ABI, unsigned ValNo,
1042+
MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo,
1043+
ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsFixed,
1044+
bool IsRet, Type *OrigTy) {
10271045
unsigned XLen = DL.getLargestLegalIntTypeSizeInBits();
10281046
assert(XLen == 32 || XLen == 64);
10291047
MVT XLenVT = XLen == 32 ? MVT::i32 : MVT::i64;
@@ -1033,10 +1051,42 @@ static bool CC_RISCV(const DataLayout &DL, unsigned ValNo, MVT ValVT, MVT LocVT,
10331051
if (IsRet && ValNo > 1)
10341052
return true;
10351053

1036-
if (ValVT == MVT::f32) {
1054+
// UseGPRForF32 if targeting one of the soft-float ABIs, if passing a
1055+
// variadic argument, or if no F32 argument registers are available.
1056+
bool UseGPRForF32 = true;
1057+
// UseGPRForF64 if targeting soft-float ABIs or an FLEN=32 ABI, if passing a
1058+
// variadic argument, or if no F64 argument registers are available.
1059+
bool UseGPRForF64 = true;
1060+
1061+
switch (ABI) {
1062+
default:
1063+
llvm_unreachable("Unexpected ABI");
1064+
case RISCVABI::ABI_ILP32:
1065+
case RISCVABI::ABI_LP64:
1066+
break;
1067+
case RISCVABI::ABI_ILP32F:
1068+
case RISCVABI::ABI_LP64F:
1069+
UseGPRForF32 = !IsFixed;
1070+
break;
1071+
case RISCVABI::ABI_ILP32D:
1072+
case RISCVABI::ABI_LP64D:
1073+
UseGPRForF32 = !IsFixed;
1074+
UseGPRForF64 = !IsFixed;
1075+
break;
1076+
}
1077+
1078+
if (State.getFirstUnallocated(ArgFPR32s) == array_lengthof(ArgFPR32s))
1079+
UseGPRForF32 = true;
1080+
if (State.getFirstUnallocated(ArgFPR64s) == array_lengthof(ArgFPR64s))
1081+
UseGPRForF64 = true;
1082+
1083+
// From this point on, rely on UseGPRForF32, UseGPRForF64 and similar local
1084+
// variables rather than directly checking against the target ABI.
1085+
1086+
if (UseGPRForF32 && ValVT == MVT::f32) {
10371087
LocVT = XLenVT;
10381088
LocInfo = CCValAssign::BCvt;
1039-
} else if (XLen == 64 && ValVT == MVT::f64) {
1089+
} else if (UseGPRForF64 && XLen == 64 && ValVT == MVT::f64) {
10401090
LocVT = MVT::i64;
10411091
LocInfo = CCValAssign::BCvt;
10421092
}
@@ -1064,8 +1114,9 @@ static bool CC_RISCV(const DataLayout &DL, unsigned ValNo, MVT ValVT, MVT LocVT,
10641114
assert(PendingLocs.size() == PendingArgFlags.size() &&
10651115
"PendingLocs and PendingArgFlags out of sync");
10661116

1067-
// Handle passing f64 on RV32D with a soft float ABI.
1068-
if (XLen == 32 && ValVT == MVT::f64) {
1117+
// Handle passing f64 on RV32D with a soft float ABI or when floating point
1118+
// registers are exhausted.
1119+
if (UseGPRForF64 && XLen == 32 && ValVT == MVT::f64) {
10691120
assert(!ArgFlags.isSplit() && PendingLocs.empty() &&
10701121
"Can't lower f64 if it is split");
10711122
// Depending on available argument GPRS, f64 may be passed in a pair of
@@ -1114,7 +1165,13 @@ static bool CC_RISCV(const DataLayout &DL, unsigned ValNo, MVT ValVT, MVT LocVT,
11141165
}
11151166

11161167
// Allocate to a register if possible, or else a stack slot.
1117-
unsigned Reg = State.AllocateReg(ArgGPRs);
1168+
unsigned Reg;
1169+
if (ValVT == MVT::f32 && !UseGPRForF32)
1170+
Reg = State.AllocateReg(ArgFPR32s, ArgFPR64s);
1171+
else if (ValVT == MVT::f64 && !UseGPRForF64)
1172+
Reg = State.AllocateReg(ArgFPR64s, ArgFPR32s);
1173+
else
1174+
Reg = Reg = State.AllocateReg(ArgGPRs);
11181175
unsigned StackOffset = Reg ? 0 : State.AllocateStack(XLen / 8, XLen / 8);
11191176

11201177
// If we reach this point and PendingLocs is non-empty, we must be at the
@@ -1135,7 +1192,8 @@ static bool CC_RISCV(const DataLayout &DL, unsigned ValNo, MVT ValVT, MVT LocVT,
11351192
return false;
11361193
}
11371194

1138-
assert(LocVT == XLenVT && "Expected an XLenVT at this stage");
1195+
assert((!UseGPRForF32 || !UseGPRForF64 || LocVT == XLenVT) &&
1196+
"Expected an XLenVT at this stage");
11391197

11401198
if (Reg) {
11411199
State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
@@ -1167,7 +1225,8 @@ void RISCVTargetLowering::analyzeInputArgs(
11671225
else if (Ins[i].isOrigArg())
11681226
ArgTy = FType->getParamType(Ins[i].getOrigArgIndex());
11691227

1170-
if (CC_RISCV(MF.getDataLayout(), i, ArgVT, ArgVT, CCValAssign::Full,
1228+
RISCVABI::ABI ABI = MF.getSubtarget<RISCVSubtarget>().getTargetABI();
1229+
if (CC_RISCV(MF.getDataLayout(), ABI, i, ArgVT, ArgVT, CCValAssign::Full,
11711230
ArgFlags, CCInfo, /*IsRet=*/true, IsRet, ArgTy)) {
11721231
LLVM_DEBUG(dbgs() << "InputArg #" << i << " has unhandled type "
11731232
<< EVT(ArgVT).getEVTString() << '\n');
@@ -1187,7 +1246,8 @@ void RISCVTargetLowering::analyzeOutputArgs(
11871246
ISD::ArgFlagsTy ArgFlags = Outs[i].Flags;
11881247
Type *OrigTy = CLI ? CLI->getArgs()[Outs[i].OrigArgIndex].Ty : nullptr;
11891248

1190-
if (CC_RISCV(MF.getDataLayout(), i, ArgVT, ArgVT, CCValAssign::Full,
1249+
RISCVABI::ABI ABI = MF.getSubtarget<RISCVSubtarget>().getTargetABI();
1250+
if (CC_RISCV(MF.getDataLayout(), ABI, i, ArgVT, ArgVT, CCValAssign::Full,
11911251
ArgFlags, CCInfo, Outs[i].IsFixed, IsRet, OrigTy)) {
11921252
LLVM_DEBUG(dbgs() << "OutputArg #" << i << " has unhandled type "
11931253
<< EVT(ArgVT).getEVTString() << "\n");
@@ -1224,8 +1284,24 @@ static SDValue unpackFromRegLoc(SelectionDAG &DAG, SDValue Chain,
12241284
MachineRegisterInfo &RegInfo = MF.getRegInfo();
12251285
EVT LocVT = VA.getLocVT();
12261286
SDValue Val;
1287+
const TargetRegisterClass *RC;
1288+
1289+
switch (LocVT.getSimpleVT().SimpleTy) {
1290+
default:
1291+
llvm_unreachable("Unexpected register type");
1292+
case MVT::i32:
1293+
case MVT::i64:
1294+
RC = &RISCV::GPRRegClass;
1295+
break;
1296+
case MVT::f32:
1297+
RC = &RISCV::FPR32RegClass;
1298+
break;
1299+
case MVT::f64:
1300+
RC = &RISCV::FPR64RegClass;
1301+
break;
1302+
}
12271303

1228-
unsigned VReg = RegInfo.createVirtualRegister(&RISCV::GPRRegClass);
1304+
unsigned VReg = RegInfo.createVirtualRegister(RC);
12291305
RegInfo.addLiveIn(VA.getLocReg(), VReg);
12301306
Val = DAG.getCopyFromReg(Chain, DL, VReg, LocVT);
12311307

@@ -1802,8 +1878,9 @@ bool RISCVTargetLowering::CanLowerReturn(
18021878
for (unsigned i = 0, e = Outs.size(); i != e; ++i) {
18031879
MVT VT = Outs[i].VT;
18041880
ISD::ArgFlagsTy ArgFlags = Outs[i].Flags;
1805-
if (CC_RISCV(MF.getDataLayout(), i, VT, VT, CCValAssign::Full, ArgFlags,
1806-
CCInfo, /*IsFixed=*/true, /*IsRet=*/true, nullptr))
1881+
RISCVABI::ABI ABI = MF.getSubtarget<RISCVSubtarget>().getTargetABI();
1882+
if (CC_RISCV(MF.getDataLayout(), ABI, i, VT, VT, CCValAssign::Full,
1883+
ArgFlags, CCInfo, /*IsFixed=*/true, /*IsRet=*/true, nullptr))
18071884
return false;
18081885
}
18091886
return true;

llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp

+28-2
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,20 @@ RISCVRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
4040
return CSR_XLEN_F32_Interrupt_SaveList;
4141
return CSR_Interrupt_SaveList;
4242
}
43-
return CSR_ILP32_LP64_SaveList;
43+
44+
switch (Subtarget.getTargetABI()) {
45+
default:
46+
llvm_unreachable("Unrecognized ABI");
47+
case RISCVABI::ABI_ILP32:
48+
case RISCVABI::ABI_LP64:
49+
return CSR_ILP32_LP64_SaveList;
50+
case RISCVABI::ABI_ILP32F:
51+
case RISCVABI::ABI_LP64F:
52+
return CSR_ILP32F_LP64F_SaveList;
53+
case RISCVABI::ABI_ILP32D:
54+
case RISCVABI::ABI_LP64D:
55+
return CSR_ILP32D_LP64D_SaveList;
56+
}
4457
}
4558

4659
BitVector RISCVRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
@@ -127,5 +140,18 @@ RISCVRegisterInfo::getCallPreservedMask(const MachineFunction & MF,
127140
return CSR_XLEN_F32_Interrupt_RegMask;
128141
return CSR_Interrupt_RegMask;
129142
}
130-
return CSR_ILP32_LP64_RegMask;
143+
144+
switch (Subtarget.getTargetABI()) {
145+
default:
146+
llvm_unreachable("Unrecognized ABI");
147+
case RISCVABI::ABI_ILP32:
148+
case RISCVABI::ABI_LP64:
149+
return CSR_ILP32_LP64_RegMask;
150+
case RISCVABI::ABI_ILP32F:
151+
case RISCVABI::ABI_LP64F:
152+
return CSR_ILP32F_LP64F_RegMask;
153+
case RISCVABI::ABI_ILP32D:
154+
case RISCVABI::ABI_LP64D:
155+
return CSR_ILP32D_LP64D_RegMask;
156+
}
131157
}

llvm/test/CodeGen/RISCV/callee-saved-fpr32s.ll

+105-2
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,19 @@
22
; RUN: | FileCheck %s -check-prefix=ILP32-LP64
33
; RUN: llc -mtriple=riscv64 -mattr=+f -verify-machineinstrs < %s \
44
; RUN: | FileCheck %s -check-prefix=ILP32-LP64
5+
; RUN: llc -mtriple=riscv32 -mattr=+f -target-abi ilp32f -verify-machineinstrs < %s \
6+
; RUN: | FileCheck %s -check-prefix=ILP32F-LP64F
7+
; RUN: llc -mtriple=riscv64 -mattr=+f -target-abi lp64f -verify-machineinstrs < %s \
8+
; RUN: | FileCheck %s -check-prefix=ILP32F-LP64F
9+
; RUN: llc -mtriple=riscv32 -mattr=+d -target-abi ilp32d -verify-machineinstrs < %s \
10+
; RUN: | FileCheck %s -check-prefix=ILP32D-LP64D
11+
; RUN: llc -mtriple=riscv64 -mattr=+d -target-abi lp64d -verify-machineinstrs < %s \
12+
; RUN: | FileCheck %s -check-prefix=ILP32D-LP64D
513

614
@var = global [32 x float] zeroinitializer
715

816
; All floating point registers are temporaries for the ilp32 and lp64 ABIs.
17+
; fs0-fs11 are callee-saved for the ilp32f, ilp32d, lp64f, and lp64d ABIs.
918

1019
; This function tests that RISCVRegisterInfo::getCalleeSavedRegs returns
1120
; something appropriate.
@@ -80,6 +89,42 @@ define void @callee() {
8089
; ILP32-LP64-NEXT: fsw ft1, 4(a1)
8190
; ILP32-LP64-NEXT: fsw ft0, %lo(var)(a0)
8291
; ILP32-LP64-NEXT: ret
92+
;
93+
; ILP32F-LP64F-LABEL: callee:
94+
; ILP32F-LP64F: # %bb.0:
95+
; ILP32F-LP64F-NEXT: addi sp, sp, -48
96+
; ILP32F-LP64F-NEXT: fsw fs0, 44(sp)
97+
; ILP32F-LP64F-NEXT: fsw fs1, 40(sp)
98+
; ILP32F-LP64F-NEXT: fsw fs2, 36(sp)
99+
; ILP32F-LP64F-NEXT: fsw fs3, 32(sp)
100+
; ILP32F-LP64F-NEXT: fsw fs4, 28(sp)
101+
; ILP32F-LP64F-NEXT: fsw fs5, 24(sp)
102+
; ILP32F-LP64F-NEXT: fsw fs6, 20(sp)
103+
; ILP32F-LP64F-NEXT: fsw fs7, 16(sp)
104+
; ILP32F-LP64F-NEXT: fsw fs8, 12(sp)
105+
; ILP32F-LP64F-NEXT: fsw fs9, 8(sp)
106+
; ILP32F-LP64F-NEXT: fsw fs10, 4(sp)
107+
; ILP32F-LP64F-NEXT: fsw fs11, 0(sp)
108+
; ILP32F-LP64F-NEXT: lui a0, %hi(var)
109+
; ILP32F-LP64F-NEXT: addi a1, a0, %lo(var)
110+
;
111+
; ILP32D-LP64D-LABEL: callee:
112+
; ILP32D-LP64D: # %bb.0:
113+
; ILP32D-LP64D-NEXT: addi sp, sp, -96
114+
; ILP32D-LP64D-NEXT: fsd fs0, 88(sp)
115+
; ILP32D-LP64D-NEXT: fsd fs1, 80(sp)
116+
; ILP32D-LP64D-NEXT: fsd fs2, 72(sp)
117+
; ILP32D-LP64D-NEXT: fsd fs3, 64(sp)
118+
; ILP32D-LP64D-NEXT: fsd fs4, 56(sp)
119+
; ILP32D-LP64D-NEXT: fsd fs5, 48(sp)
120+
; ILP32D-LP64D-NEXT: fsd fs6, 40(sp)
121+
; ILP32D-LP64D-NEXT: fsd fs7, 32(sp)
122+
; ILP32D-LP64D-NEXT: fsd fs8, 24(sp)
123+
; ILP32D-LP64D-NEXT: fsd fs9, 16(sp)
124+
; ILP32D-LP64D-NEXT: fsd fs10, 8(sp)
125+
; ILP32D-LP64D-NEXT: fsd fs11, 0(sp)
126+
; ILP32D-LP64D-NEXT: lui a0, %hi(var)
127+
; ILP32D-LP64D-NEXT: addi a1, a0, %lo(var)
83128
%val = load [32 x float], [32 x float]* @var
84129
store volatile [32 x float] %val, [32 x float]* @var
85130
ret void
@@ -89,17 +134,75 @@ define void @callee() {
89134
; something appropriate.
90135
;
91136
; For the soft float ABIs, no floating point registers are preserved, and
92-
; codegen will use only ft0 in the body of caller.
137+
; codegen will use only ft0 in the body of caller. For the 'f' and 'd ABIs,
138+
; fs0-fs11 are preserved across calls.
93139

94140
define void @caller() {
95141
; ILP32-LP64-LABEL: caller:
96142
; ILP32-LP64-NOT: ft{{[1-9][0-9]*}}
97143
; ILP32-LP64-NOT: fs{{[0-9]+}}
98144
; ILP32-LP64-NOT: fa{{[0-9]+}}
99-
; ILP32-LP64: ret
145+
; ILP32-LP64: call callee
100146
; ILP32-LP64-NOT: ft{{[1-9][0-9]*}}
101147
; ILP32-LP64-NOT: fs{{[0-9]+}}
102148
; ILP32-LP64-NOT: fa{{[0-9]+}}
149+
; ILP32-LP64: ret
150+
;
151+
; ILP32F-LP64F-LABEL: caller:
152+
; ILP32F-LP64F: flw fs8, 80(s1)
153+
; ILP32F-LP64F-NEXT: flw fs9, 84(s1)
154+
; ILP32F-LP64F-NEXT: flw fs10, 88(s1)
155+
; ILP32F-LP64F-NEXT: flw fs11, 92(s1)
156+
; ILP32F-LP64F-NEXT: flw fs0, 96(s1)
157+
; ILP32F-LP64F-NEXT: flw fs1, 100(s1)
158+
; ILP32F-LP64F-NEXT: flw fs2, 104(s1)
159+
; ILP32F-LP64F-NEXT: flw fs3, 108(s1)
160+
; ILP32F-LP64F-NEXT: flw fs4, 112(s1)
161+
; ILP32F-LP64F-NEXT: flw fs5, 116(s1)
162+
; ILP32F-LP64F-NEXT: flw fs6, 120(s1)
163+
; ILP32F-LP64F-NEXT: flw fs7, 124(s1)
164+
; ILP32F-LP64F-NEXT: call callee
165+
; ILP32F-LP64F-NEXT: fsw fs7, 124(s1)
166+
; ILP32F-LP64F-NEXT: fsw fs6, 120(s1)
167+
; ILP32F-LP64F-NEXT: fsw fs5, 116(s1)
168+
; ILP32F-LP64F-NEXT: fsw fs4, 112(s1)
169+
; ILP32F-LP64F-NEXT: fsw fs3, 108(s1)
170+
; ILP32F-LP64F-NEXT: fsw fs2, 104(s1)
171+
; ILP32F-LP64F-NEXT: fsw fs1, 100(s1)
172+
; ILP32F-LP64F-NEXT: fsw fs0, 96(s1)
173+
; ILP32F-LP64F-NEXT: fsw fs11, 92(s1)
174+
; ILP32F-LP64F-NEXT: fsw fs10, 88(s1)
175+
; ILP32F-LP64F-NEXT: fsw fs9, 84(s1)
176+
; ILP32F-LP64F-NEXT: fsw fs8, 80(s1)
177+
; ILP32F-LP64F-NEXT: lw ft0, {{[0-9]+}}(sp)
178+
;
179+
; ILP32D-LP64D-LABEL: caller:
180+
; ILP32D-LP64D: flw fs8, 80(s1)
181+
; ILP32D-LP64D-NEXT: flw fs9, 84(s1)
182+
; ILP32D-LP64D-NEXT: flw fs10, 88(s1)
183+
; ILP32D-LP64D-NEXT: flw fs11, 92(s1)
184+
; ILP32D-LP64D-NEXT: flw fs0, 96(s1)
185+
; ILP32D-LP64D-NEXT: flw fs1, 100(s1)
186+
; ILP32D-LP64D-NEXT: flw fs2, 104(s1)
187+
; ILP32D-LP64D-NEXT: flw fs3, 108(s1)
188+
; ILP32D-LP64D-NEXT: flw fs4, 112(s1)
189+
; ILP32D-LP64D-NEXT: flw fs5, 116(s1)
190+
; ILP32D-LP64D-NEXT: flw fs6, 120(s1)
191+
; ILP32D-LP64D-NEXT: flw fs7, 124(s1)
192+
; ILP32D-LP64D-NEXT: call callee
193+
; ILP32D-LP64D-NEXT: fsw fs7, 124(s1)
194+
; ILP32D-LP64D-NEXT: fsw fs6, 120(s1)
195+
; ILP32D-LP64D-NEXT: fsw fs5, 116(s1)
196+
; ILP32D-LP64D-NEXT: fsw fs4, 112(s1)
197+
; ILP32D-LP64D-NEXT: fsw fs3, 108(s1)
198+
; ILP32D-LP64D-NEXT: fsw fs2, 104(s1)
199+
; ILP32D-LP64D-NEXT: fsw fs1, 100(s1)
200+
; ILP32D-LP64D-NEXT: fsw fs0, 96(s1)
201+
; ILP32D-LP64D-NEXT: fsw fs11, 92(s1)
202+
; ILP32D-LP64D-NEXT: fsw fs10, 88(s1)
203+
; ILP32D-LP64D-NEXT: fsw fs9, 84(s1)
204+
; ILP32D-LP64D-NEXT: fsw fs8, 80(s1)
205+
; ILP32D-LP64D-NEXT: flw ft0, {{[0-9]+}}(sp)
103206
%val = load [32 x float], [32 x float]* @var
104207
call void @callee()
105208
store volatile [32 x float] %val, [32 x float]* @var

0 commit comments

Comments
 (0)