Reworking the stack layout that the MicroBlaze backend generates.

The MicroBlaze backend was generating stack layouts that did not
conform correctly to the ABI. This update generates stack layouts
which are closer to what GCC does.

Variable arguments support was added as well but the stack layout
for varargs has not been finalized.



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@97807 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Wesley Peck 2010-03-05 15:26:02 +00:00
parent c84a9566cb
commit c4155d591b
6 changed files with 257 additions and 61 deletions

View File

@ -129,15 +129,15 @@ SelectAddrRegReg(SDNode *Op, SDValue N, SDValue &Base, SDValue &Index) {
N.getOpcode() == ISD::TargetGlobalAddress)
return false; // direct calls.
if (N.getOperand(0).getOpcode() == ISD::TargetJumpTable ||
N.getOperand(1).getOpcode() == ISD::TargetJumpTable)
return false; // jump tables.
int32_t imm = 0;
if (N.getOpcode() == ISD::ADD || N.getOpcode() == ISD::OR) {
if (isIntS32Immediate(N.getOperand(1), imm))
return false; // r+i
if (N.getOperand(0).getOpcode() == ISD::TargetJumpTable ||
N.getOperand(1).getOpcode() == ISD::TargetJumpTable)
return false; // jump tables.
Base = N.getOperand(1);
Index = N.getOperand(0);
return true;

View File

@ -138,6 +138,13 @@ MBlazeTargetLowering::MBlazeTargetLowering(MBlazeTargetMachine &TM)
setOperationAction(ISD::JumpTable, MVT::i32, Custom);
setOperationAction(ISD::ConstantPool, MVT::i32, Custom);
// Variable Argument support
setOperationAction(ISD::VASTART, MVT::Other, Custom);
setOperationAction(ISD::VAEND, MVT::Other, Expand);
setOperationAction(ISD::VAARG, MVT::Other, Expand);
setOperationAction(ISD::VACOPY, MVT::Other, Expand);
// Operations not directly supported by MBlaze.
setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Expand);
setOperationAction(ISD::BR_JT, MVT::Other, Expand);
@ -186,6 +193,7 @@ SDValue MBlazeTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) {
case ISD::GlobalTLSAddress: return LowerGlobalTLSAddress(Op, DAG);
case ISD::JumpTable: return LowerJumpTable(Op, DAG);
case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG);
case ISD::VASTART: return LowerVASTART(Op, DAG);
}
return SDValue();
}
@ -440,7 +448,6 @@ LowerConstantPool(SDValue Op, SelectionDAG &DAG) {
ConstantPoolSDNode *N = cast<ConstantPoolSDNode>(Op);
Constant *C = N->getConstVal();
SDValue Zero = DAG.getConstant(0, PtrVT);
// FIXME there isn't actually debug info here
DebugLoc dl = Op.getDebugLoc();
SDValue CP = DAG.getTargetConstantPool(C, MVT::i32, N->getAlignment(),
@ -448,12 +455,121 @@ LowerConstantPool(SDValue Op, SelectionDAG &DAG) {
return DAG.getNode(MBlazeISD::Wrap, dl, MVT::i32, CP);
}
SDValue MBlazeTargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG) {
DebugLoc dl = Op.getDebugLoc();
SDValue FI = DAG.getFrameIndex(VarArgsFrameIndex, getPointerTy());
// vastart just stores the address of the VarArgsFrameIndex slot into the
// memory location argument.
const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
return DAG.getStore(Op.getOperand(0), dl, FI, Op.getOperand(1), SV, 0,
false, false, 0);
}
//===----------------------------------------------------------------------===//
// Calling Convention Implementation
//===----------------------------------------------------------------------===//
#include "MBlazeGenCallingConv.inc"
static bool CC_MBlaze2(unsigned ValNo, EVT ValVT,
EVT LocVT, CCValAssign::LocInfo LocInfo,
ISD::ArgFlagsTy ArgFlags, CCState &State) {
static const unsigned RegsSize=6;
static const unsigned IntRegs[] = {
MBlaze::R5, MBlaze::R6, MBlaze::R7,
MBlaze::R8, MBlaze::R9, MBlaze::R10
};
static const unsigned FltRegs[] = {
MBlaze::F5, MBlaze::F6, MBlaze::F7,
MBlaze::F8, MBlaze::F9, MBlaze::F10
};
unsigned Reg=0;
//unsigned UnallocIntReg = State.getFirstUnallocated(IntRegs, RegsSize);
// Promote i8 and i16
if (LocVT == MVT::i8 || LocVT == MVT::i16) {
LocVT = MVT::i32;
if (ArgFlags.isSExt())
LocInfo = CCValAssign::SExt;
else if (ArgFlags.isZExt())
LocInfo = CCValAssign::ZExt;
else
LocInfo = CCValAssign::AExt;
}
if (ValVT == MVT::i32) {
Reg = State.AllocateReg(IntRegs, RegsSize);
LocVT = MVT::i32;
} else if (ValVT == MVT::f32) {
Reg = State.AllocateReg(FltRegs, RegsSize);
LocVT = MVT::f32;
}
if (!Reg) {
unsigned SizeInBytes = ValVT.getSizeInBits() >> 3;
unsigned Offset = State.AllocateStack(SizeInBytes, SizeInBytes);
State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
} else {
unsigned SizeInBytes = ValVT.getSizeInBits() >> 3;
unsigned Offset = State.AllocateStack(SizeInBytes, SizeInBytes);
State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
}
return false; // CC must always match
}
static bool CC_MBlaze_VarArg(unsigned ValNo, EVT ValVT,
EVT LocVT, CCValAssign::LocInfo LocInfo,
ISD::ArgFlagsTy ArgFlags, CCState &State) {
static const unsigned RegsSize=6;
static const unsigned IntRegs[] = {
MBlaze::R5, MBlaze::R6, MBlaze::R7,
MBlaze::R8, MBlaze::R9, MBlaze::R10
};
static const unsigned FltRegs[] = {
MBlaze::F5, MBlaze::F6, MBlaze::F7,
MBlaze::F8, MBlaze::F9, MBlaze::F10
};
// Promote i8 and i16
if (LocVT == MVT::i8 || LocVT == MVT::i16) {
LocVT = MVT::i32;
if (ArgFlags.isSExt())
LocInfo = CCValAssign::SExt;
else if (ArgFlags.isZExt())
LocInfo = CCValAssign::ZExt;
else
LocInfo = CCValAssign::AExt;
}
if (ValVT == MVT::i32) {
if (unsigned Reg = State.AllocateReg(IntRegs, RegsSize)) {
unsigned SizeInBytes = ValVT.getSizeInBits() >> 3;
State.AllocateStack(SizeInBytes, SizeInBytes);
State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, MVT::i32, LocInfo));
return false;
}
} else if (ValVT == MVT::f32) {
if (unsigned Reg = State.AllocateReg(FltRegs, RegsSize)) {
unsigned SizeInBytes = ValVT.getSizeInBits() >> 3;
State.AllocateStack(SizeInBytes, SizeInBytes);
State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, MVT::i32, LocInfo));
return false;
}
}
unsigned SizeInBytes = ValVT.getSizeInBits() >> 3;
unsigned Off = State.AllocateStack(SizeInBytes, SizeInBytes);
State.addLoc(CCValAssign::getMem(ValNo, ValVT, Off, LocVT, LocInfo));
return false;
}
//===----------------------------------------------------------------------===//
// Call Calling Convention Implementation
//===----------------------------------------------------------------------===//
@ -468,6 +584,9 @@ LowerCall(SDValue Chain, SDValue Callee, CallingConv::ID CallConv,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) {
// MBlaze does not yet support tail call optimization
isTailCall = false;
MachineFunction &MF = DAG.getMachineFunction();
MachineFrameInfo *MFI = MF.getFrameInfo();
@ -475,7 +594,7 @@ LowerCall(SDValue Chain, SDValue Callee, CallingConv::ID CallConv,
SmallVector<CCValAssign, 16> ArgLocs;
CCState CCInfo(CallConv, isVarArg, getTargetMachine(), ArgLocs,
*DAG.getContext());
CCInfo.AnalyzeCallOperands(Outs, CC_MBlaze);
CCInfo.AnalyzeCallOperands(Outs, CC_MBlaze2);
// Get a count of how many bytes are to be pushed on the stack.
unsigned NumBytes = CCInfo.getNextStackOffset();
@ -487,7 +606,7 @@ LowerCall(SDValue Chain, SDValue Callee, CallingConv::ID CallConv,
// First/LastArgStackLoc contains the first/last
// "at stack" argument location.
int LastArgStackLoc = 0;
unsigned FirstStackArgLoc = 4;
unsigned FirstStackArgLoc = 0;
// Walk the register/memloc assignments, inserting copies/loads.
for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
@ -508,9 +627,6 @@ LowerCall(SDValue Chain, SDValue Callee, CallingConv::ID CallConv,
case CCValAssign::AExt:
Arg = DAG.getNode(ISD::ANY_EXTEND, dl, RegVT, Arg);
break;
case CCValAssign::BCvt:
Arg = DAG.getNode(ISD::BIT_CONVERT, dl, RegVT, Arg);
break;
}
// Arguments that can be passed on register must be kept at
@ -629,7 +745,6 @@ LowerCallResult(SDValue Chain, SDValue InFlag, CallingConv::ID CallConv,
/// LowerFormalArguments - transform physical registers into
/// virtual registers and generate load operations for
/// arguments places on the stack.
/// TODO: isVarArg
SDValue MBlazeTargetLowering::
LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins,
@ -640,16 +755,23 @@ LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>();
unsigned StackReg = MF.getTarget().getRegisterInfo()->getFrameRegister(MF);
VarArgsFrameIndex = 0;
// Used with vargs to acumulate store chains.
std::vector<SDValue> OutChains;
// Keep track of the last register used for arguments
unsigned ArgRegEnd = 0;
// Assign locations to all of the incoming arguments.
SmallVector<CCValAssign, 16> ArgLocs;
CCState CCInfo(CallConv, isVarArg, getTargetMachine(),
ArgLocs, *DAG.getContext());
CCInfo.AnalyzeFormalArguments(Ins, CC_MBlaze);
CCInfo.AnalyzeFormalArguments(Ins, CC_MBlaze2);
SDValue StackPtr;
unsigned FirstStackArgLoc = 4;
unsigned FirstStackArgLoc = 0;
for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
CCValAssign &VA = ArgLocs[i];
@ -657,6 +779,7 @@ LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
// Arguments stored on registers
if (VA.isRegLoc()) {
EVT RegVT = VA.getLocVT();
ArgRegEnd = VA.getLocReg();
TargetRegisterClass *RC = 0;
if (RegVT == MVT::i32)
@ -668,12 +791,13 @@ LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
// Transform the arguments stored on
// physical registers into virtual ones
unsigned Reg = MF.addLiveIn(VA.getLocReg(), RC);
unsigned Reg = MF.addLiveIn(ArgRegEnd, RC);
SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, Reg, RegVT);
// If this is an 8 or 16-bit value, it has been passed promoted
// to 32 bits. Insert an assert[sz]ext to capture this, then
// truncate to the right size.
// truncate to the right size. If if is a floating point value
// then convert to the correct type.
if (VA.getLocInfo() != CCValAssign::Full) {
unsigned Opcode = 0;
if (VA.getLocInfo() == CCValAssign::SExt)
@ -688,35 +812,14 @@ LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
InVals.push_back(ArgValue);
// To meet ABI, when VARARGS are passed on registers, the registers
// must have their values written to the caller stack frame.
if (isVarArg) {
if (StackPtr.getNode() == 0)
StackPtr = DAG.getRegister(StackReg, getPointerTy());
// The stack pointer offset is relative to the caller stack frame.
// Since the real stack size is unknown here, a negative SPOffset
// is used so there's a way to adjust these offsets when the stack
// size get known (on EliminateFrameIndex). A dummy SPOffset is
// used instead of a direct negative address (which is recorded to
// be used on emitPrologue) to avoid mis-calc of the first stack
// offset on PEI::calculateFrameObjectOffsets.
// Arguments are always 32-bit.
int FI = MFI->CreateFixedObject(4, 0, true, false);
MBlazeFI->recordStoreVarArgsFI(FI, -(FirstStackArgLoc+(i*4)));
SDValue PtrOff = DAG.getFrameIndex(FI, getPointerTy());
// emit ISD::STORE whichs stores the
// parameter value to a stack Location
InVals.push_back(DAG.getStore(Chain, dl, ArgValue, PtrOff, NULL, 0,
false, false, 0));
}
} else { // VA.isRegLoc()
// sanity check
assert(VA.isMemLoc());
// The last argument is not a register
ArgRegEnd = 0;
// The stack pointer offset is relative to the caller stack frame.
// Since the real stack size is unknown here, a negative SPOffset
// is used so there's a way to adjust these offsets when the stack
@ -737,6 +840,47 @@ LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
}
}
// To meet ABI, when VARARGS are passed on registers, the registers
// must have their values written to the caller stack frame. If the last
// argument was placed in the stack, there's no need to save any register.
if ((isVarArg) && ArgRegEnd) {
if (StackPtr.getNode() == 0)
StackPtr = DAG.getRegister(StackReg, getPointerTy());
// The last register argument that must be saved is MBlaze::R10
TargetRegisterClass *RC = MBlaze::CPURegsRegisterClass;
unsigned Begin = MBlazeRegisterInfo::getRegisterNumbering(MBlaze::R5);
unsigned Start = MBlazeRegisterInfo::getRegisterNumbering(ArgRegEnd+1);
unsigned End = MBlazeRegisterInfo::getRegisterNumbering(MBlaze::R10);
unsigned StackLoc = ArgLocs.size()-1 + (Start - Begin);
for (; Start <= End; ++Start, ++StackLoc) {
unsigned Reg = MBlazeRegisterInfo::getRegisterFromNumbering(Start);
unsigned LiveReg = MF.addLiveIn(Reg, RC);
SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, LiveReg, MVT::i32);
int FI = MFI->CreateFixedObject(4, 0, true, false);
MBlazeFI->recordStoreVarArgsFI(FI, -(4+(StackLoc*4)));
SDValue PtrOff = DAG.getFrameIndex(FI, getPointerTy());
OutChains.push_back(DAG.getStore(Chain, dl, ArgValue, PtrOff, NULL, 0,
false, false, 0));
// Record the frame index of the first variable argument
// which is a value necessary to VASTART.
if (!VarArgsFrameIndex)
VarArgsFrameIndex = FI;
}
}
// All stores are grouped in one node to allow the matching between
// the size of Ins and InVals. This only happens when on varg functions
if (!OutChains.empty()) {
OutChains.push_back(Chain);
Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
&OutChains[0], OutChains.size());
}
return Chain;
}

View File

@ -63,6 +63,8 @@ namespace llvm {
//===--------------------------------------------------------------------===//
class MBlazeTargetLowering : public TargetLowering {
int VarArgsFrameIndex; // FrameIndex for start of varargs area.
public:
explicit MBlazeTargetLowering(MBlazeTargetMachine &TM);
@ -96,6 +98,7 @@ namespace llvm {
SDValue LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG);
SDValue LowerJumpTable(SDValue Op, SelectionDAG &DAG);
SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG);
SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG);
virtual SDValue
LowerFormalArguments(SDValue Chain,

View File

@ -85,6 +85,47 @@ unsigned MBlazeRegisterInfo::getRegisterNumbering(unsigned RegEnum) {
return 0; // Not reached
}
/// getRegisterFromNumbering - Given the enum value for some register, e.g.
/// MBlaze::R0, return the number that it corresponds to (e.g. 0).
unsigned MBlazeRegisterInfo::getRegisterFromNumbering(unsigned Reg) {
switch (Reg) {
case 0 : return MBlaze::R0;
case 1 : return MBlaze::R1;
case 2 : return MBlaze::R2;
case 3 : return MBlaze::R3;
case 4 : return MBlaze::R4;
case 5 : return MBlaze::R5;
case 6 : return MBlaze::R6;
case 7 : return MBlaze::R7;
case 8 : return MBlaze::R8;
case 9 : return MBlaze::R9;
case 10 : return MBlaze::R10;
case 11 : return MBlaze::R11;
case 12 : return MBlaze::R12;
case 13 : return MBlaze::R13;
case 14 : return MBlaze::R14;
case 15 : return MBlaze::R15;
case 16 : return MBlaze::R16;
case 17 : return MBlaze::R17;
case 18 : return MBlaze::R18;
case 19 : return MBlaze::R19;
case 20 : return MBlaze::R20;
case 21 : return MBlaze::R21;
case 22 : return MBlaze::R22;
case 23 : return MBlaze::R23;
case 24 : return MBlaze::R24;
case 25 : return MBlaze::R25;
case 26 : return MBlaze::R26;
case 27 : return MBlaze::R27;
case 28 : return MBlaze::R28;
case 29 : return MBlaze::R29;
case 30 : return MBlaze::R30;
case 31 : return MBlaze::R31;
default: llvm_unreachable("Unknown register number!");
}
return 0; // Not reached
}
unsigned MBlazeRegisterInfo::getPICCallReg() {
return MBlaze::R20;
}
@ -180,9 +221,9 @@ void MBlazeRegisterInfo::adjustMBlazeStackFrame(MachineFunction &MF) const {
}
if (MFI->hasCalls()) {
MBlazeFI->setRAStackOffset(0);
MFI->setObjectOffset(MFI->CreateStackObject(RegSize, RegSize, true),
StackOffset);
MBlazeFI->setRAStackOffset(StackOffset);
TopCPUSavedRegOff = StackOffset;
StackOffset += RegSize;
}
@ -245,7 +286,7 @@ eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj,
// as explained on LowerFormalArguments, detect negative offsets
// and adjust SPOffsets considering the final stack size.
int Offset = ((spOffset < 0) ? (stackSize + (-(spOffset+4))) : (spOffset));
int Offset = (spOffset < 0) ? (stackSize - spOffset) : (spOffset + 4);
Offset += MI.getOperand(oi).getImm();
DEBUG(errs() << "Offset : " << Offset << "\n" << "<--------->\n");
@ -272,6 +313,7 @@ emitPrologue(MachineFunction &MF) const {
// No need to allocate space on the stack.
if (StackSize == 0 && !MFI->hasCalls()) return;
if (StackSize < 28 && MFI->hasCalls()) StackSize = 28;
int FPOffset = MBlazeFI->getFPStackOffset();
int RAOffset = MBlazeFI->getRAStackOffset();
@ -307,9 +349,6 @@ emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const {
MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>();
DebugLoc dl = MBBI->getDebugLoc();
// Get the number of bytes from FrameInfo
int NumBytes = (int) MFI->getStackSize();
// Get the FI's where RA and FP are saved.
int FPOffset = MBlazeFI->getFPStackOffset();
int RAOffset = MBlazeFI->getRAStackOffset();
@ -333,11 +372,15 @@ emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const {
.addImm(RAOffset).addReg(MBlaze::R1);
}
// Get the number of bytes from FrameInfo
int StackSize = (int) MFI->getStackSize();
if (StackSize < 28 && MFI->hasCalls()) StackSize = 28;
// adjust stack.
// addi R1, R1, imm
if (NumBytes) {
if (StackSize) {
BuildMI(MBB, MBBI, dl, TII.get(MBlaze::ADDI), MBlaze::R1)
.addReg(MBlaze::R1).addImm(NumBytes);
.addReg(MBlaze::R1).addImm(StackSize);
}
}

View File

@ -43,6 +43,7 @@ struct MBlazeRegisterInfo : public MBlazeGenRegisterInfo {
/// getRegisterNumbering - Given the enum value for some register, e.g.
/// MBlaze::RA, return the number that it corresponds to (e.g. 31).
static unsigned getRegisterNumbering(unsigned RegEnum);
static unsigned getRegisterFromNumbering(unsigned RegEnum);
/// Get PIC indirect call register
static unsigned getPICCallReg();
@ -82,6 +83,11 @@ struct MBlazeRegisterInfo : public MBlazeGenRegisterInfo {
unsigned getEHExceptionRegister() const;
unsigned getEHHandlerRegister() const;
/// targetHandlesStackFrameRounding - Returns true if the target is
/// responsible for rounding up the stack frame (probably at emitPrologue
/// time).
bool targetHandlesStackFrameRounding() const { return true; }
int getDwarfRegNum(unsigned RegNum, bool isEH) const;
};

View File

@ -101,7 +101,7 @@ define i32 @params7_32bitret(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f,
i32 %g) {
; CHECK: params7_32bitret:
ret i32 %g
; CHECK: {{lwi? r3, r1, 8}}
; CHECK: {{lwi? r3, r1, 32}}
; CHECK-NOT: {{.* r4, .*, .*}}
; CHECK: rtsd
}
@ -110,7 +110,7 @@ define i32 @params8_32bitret(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f,
i32 %g, i32 %h) {
; CHECK: params8_32bitret:
ret i32 %h
; CHECK: {{lwi? r3, r1, 12}}
; CHECK: {{lwi? r3, r1, 36}}
; CHECK-NOT: {{.* r4, .*, .*}}
; CHECK: rtsd
}
@ -119,7 +119,7 @@ define i32 @params9_32bitret(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f,
i32 %g, i32 %h, i32 %i) {
; CHECK: params9_32bitret:
ret i32 %i
; CHECK: {{lwi? r3, r1, 16}}
; CHECK: {{lwi? r3, r1, 40}}
; CHECK-NOT: {{.* r4, .*, .*}}
; CHECK: rtsd
}
@ -128,7 +128,7 @@ define i32 @params10_32bitret(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f,
i32 %g, i32 %h, i32 %i, i32 %j) {
; CHECK: params10_32bitret:
ret i32 %j
; CHECK: {{lwi? r3, r1, 20}}
; CHECK: {{lwi? r3, r1, 44}}
; CHECK-NOT: {{.* r4, .*, .*}}
; CHECK: rtsd
}
@ -243,7 +243,7 @@ define void @testing() {
%tmp.11 = call i32 @params7_32bitret(i32 1, i32 2, i32 3, i32 4, i32 5,
i32 6, i32 7)
; CHECK: {{swi? .*, r1, 4}}
; CHECK: {{swi? .*, r1, 28}}
; CHECK: {{.* r5, .*, .*}}
; CHECK: {{.* r6, .*, .*}}
; CHECK: {{.* r7, .*, .*}}
@ -259,8 +259,8 @@ define void @testing() {
%tmp.12 = call i32 @params8_32bitret(i32 1, i32 2, i32 3, i32 4, i32 5,
i32 6, i32 7, i32 8)
; CHECK: {{swi? .*, r1, 4}}
; CHECK: {{swi? .*, r1, 8}}
; CHECK: {{swi? .*, r1, 28}}
; CHECK: {{swi? .*, r1, 32}}
; CHECK: {{.* r5, .*, .*}}
; CHECK: {{.* r6, .*, .*}}
; CHECK: {{.* r7, .*, .*}}
@ -276,9 +276,9 @@ define void @testing() {
%tmp.13 = call i32 @params9_32bitret(i32 1, i32 2, i32 3, i32 4, i32 5,
i32 6, i32 7, i32 8, i32 9)
; CHECK: {{swi? .*, r1, 4}}
; CHECK: {{swi? .*, r1, 8}}
; CHECK: {{swi? .*, r1, 12}}
; CHECK: {{swi? .*, r1, 28}}
; CHECK: {{swi? .*, r1, 32}}
; CHECK: {{swi? .*, r1, 36}}
; CHECK: {{.* r5, .*, .*}}
; CHECK: {{.* r6, .*, .*}}
; CHECK: {{.* r7, .*, .*}}
@ -294,10 +294,10 @@ define void @testing() {
%tmp.14 = call i32 @params10_32bitret(i32 1, i32 2, i32 3, i32 4, i32 5,
i32 6, i32 7, i32 8, i32 9, i32 10)
; CHECK: {{swi? .*, r1, 4}}
; CHECK: {{swi? .*, r1, 8}}
; CHECK: {{swi? .*, r1, 12}}
; CHECK: {{swi? .*, r1, 16}}
; CHECK: {{swi? .*, r1, 28}}
; CHECK: {{swi? .*, r1, 32}}
; CHECK: {{swi? .*, r1, 36}}
; CHECK: {{swi? .*, r1, 40}}
; CHECK: {{.* r5, .*, .*}}
; CHECK: {{.* r6, .*, .*}}
; CHECK: {{.* r7, .*, .*}}