[GlobalISel] Accept multiple vregs for lowerCall's args

Change the interface of CallLowering::lowerCall to accept several
virtual registers for each argument, instead of just one.  This is a
follow-up to D46018.

CallLowering::lowerReturn was similarly refactored in D49660 and
lowerFormalArguments in D63549.

With this change, we no longer pack the virtual registers generated for
aggregates into one big lump before delegating to the target. Therefore,
the target can decide itself whether it wants to handle them as separate
pieces or use one big register.

ARM and AArch64 have been updated to use the passed in virtual registers
directly, which means we no longer need to generate so many
merge/extract instructions.

NFCI for AMDGPU, Mips and X86.

Differential Revision: https://reviews.llvm.org/D63551

llvm-svn: 364512
This commit is contained in:
Diana Picus 2019-06-27 09:18:03 +00:00
parent 0d78943f2c
commit 54d3122693
10 changed files with 29 additions and 100 deletions

View File

@ -262,8 +262,10 @@ public:
/// stored (or 0 if there is no return value). There will be one register for /// stored (or 0 if there is no return value). There will be one register for
/// each non-aggregate type, as returned by \c computeValueLLTs. /// each non-aggregate type, as returned by \c computeValueLLTs.
/// ///
/// \p ArgRegs is a list of virtual registers containing each argument that /// \p ArgRegs is a list of lists of virtual registers containing each
/// needs to be passed. /// argument that needs to be passed (argument \c i should be placed in \c
/// ArgRegs[i]). For each argument, there will be one register for each
/// non-aggregate type, as returned by \c computeValueLLTs.
/// ///
/// \p SwiftErrorVReg is non-zero if the call has a swifterror inout /// \p SwiftErrorVReg is non-zero if the call has a swifterror inout
/// parameter, and contains the vreg that the swifterror should be copied into /// parameter, and contains the vreg that the swifterror should be copied into
@ -276,8 +278,8 @@ public:
/// ///
/// \return true if the lowering succeeded, false otherwise. /// \return true if the lowering succeeded, false otherwise.
bool lowerCall(MachineIRBuilder &MIRBuilder, ImmutableCallSite CS, bool lowerCall(MachineIRBuilder &MIRBuilder, ImmutableCallSite CS,
ArrayRef<Register> ResRegs, ArrayRef<Register> ArgRegs, ArrayRef<Register> ResRegs,
Register SwiftErrorVReg, ArrayRef<ArrayRef<Register>> ArgRegs, Register SwiftErrorVReg,
std::function<unsigned()> GetCalleeReg) const; std::function<unsigned()> GetCalleeReg) const;
}; };

View File

@ -29,7 +29,7 @@ void CallLowering::anchor() {}
bool CallLowering::lowerCall(MachineIRBuilder &MIRBuilder, ImmutableCallSite CS, bool CallLowering::lowerCall(MachineIRBuilder &MIRBuilder, ImmutableCallSite CS,
ArrayRef<Register> ResRegs, ArrayRef<Register> ResRegs,
ArrayRef<Register> ArgRegs, ArrayRef<ArrayRef<Register>> ArgRegs,
Register SwiftErrorVReg, Register SwiftErrorVReg,
std::function<unsigned()> GetCalleeReg) const { std::function<unsigned()> GetCalleeReg) const {
auto &DL = CS.getParent()->getParent()->getParent()->getDataLayout(); auto &DL = CS.getParent()->getParent()->getParent()->getDataLayout();

View File

@ -1587,8 +1587,8 @@ bool IRTranslator::translateCall(const User &U, MachineIRBuilder &MIRBuilder) {
if (!F || !F->isIntrinsic() || ID == Intrinsic::not_intrinsic) { if (!F || !F->isIntrinsic() || ID == Intrinsic::not_intrinsic) {
ArrayRef<Register> Res = getOrCreateVRegs(CI); ArrayRef<Register> Res = getOrCreateVRegs(CI);
SmallVector<Register, 8> Args; SmallVector<ArrayRef<Register>, 8> Args;
Register SwiftErrorVReg; Register SwiftErrorVReg = 0;
for (auto &Arg: CI.arg_operands()) { for (auto &Arg: CI.arg_operands()) {
if (CLI->supportSwiftError() && isSwiftError(Arg)) { if (CLI->supportSwiftError() && isSwiftError(Arg)) {
LLT Ty = getLLTForType(*Arg->getType(), *DL); LLT Ty = getLLTForType(*Arg->getType(), *DL);
@ -1600,7 +1600,7 @@ bool IRTranslator::translateCall(const User &U, MachineIRBuilder &MIRBuilder) {
SwiftError.getOrCreateVRegDefAt(&CI, &MIRBuilder.getMBB(), Arg); SwiftError.getOrCreateVRegDefAt(&CI, &MIRBuilder.getMBB(), Arg);
continue; continue;
} }
Args.push_back(packRegs(*Arg, MIRBuilder)); Args.push_back(getOrCreateVRegs(*Arg));
} }
MF->getFrameInfo().setHasCalls(true); MF->getFrameInfo().setHasCalls(true);
@ -1684,7 +1684,7 @@ bool IRTranslator::translateInvoke(const User &U,
ArrayRef<Register> Res; ArrayRef<Register> Res;
if (!I.getType()->isVoidTy()) if (!I.getType()->isVoidTy())
Res = getOrCreateVRegs(I); Res = getOrCreateVRegs(I);
SmallVector<Register, 8> Args; SmallVector<ArrayRef<Register>, 8> Args;
Register SwiftErrorVReg = 0; Register SwiftErrorVReg = 0;
for (auto &Arg : I.arg_operands()) { for (auto &Arg : I.arg_operands()) {
if (CLI->supportSwiftError() && isSwiftError(Arg)) { if (CLI->supportSwiftError() && isSwiftError(Arg)) {
@ -1698,7 +1698,7 @@ bool IRTranslator::translateInvoke(const User &U,
continue; continue;
} }
Args.push_back(packRegs(*Arg, MIRBuilder)); Args.push_back(getOrCreateVRegs(*Arg));
} }
if (!CLI->lowerCall(MIRBuilder, &I, Res, Args, SwiftErrorVReg, if (!CLI->lowerCall(MIRBuilder, &I, Res, Args, SwiftErrorVReg,

View File

@ -441,10 +441,9 @@ bool AArch64CallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
SmallVector<ArgInfo, 8> SplitArgs; SmallVector<ArgInfo, 8> SplitArgs;
for (auto &OrigArg : OrigArgs) { for (auto &OrigArg : OrigArgs) {
assert(OrigArg.Regs.size() == 1 && "Can't handle multple regs yet");
splitToValueTypes(OrigArg, SplitArgs, DL, MRI, CallConv, splitToValueTypes(OrigArg, SplitArgs, DL, MRI, CallConv,
[&](Register Reg, uint64_t Offset) { [&](Register Reg, uint64_t Offset) {
MIRBuilder.buildExtract(Reg, OrigArg.Regs[0], Offset); llvm_unreachable("Call params should already be split");
}); });
// AAPCS requires that we zero-extend i1 to 8 bits by the caller. // AAPCS requires that we zero-extend i1 to 8 bits by the caller.
if (OrigArg.Ty->isIntegerTy(1)) if (OrigArg.Ty->isIntegerTy(1))

View File

@ -596,14 +596,9 @@ bool ARMCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
if (Arg.Flags.isByVal()) if (Arg.Flags.isByVal())
return false; return false;
assert(Arg.Regs.size() == 1 && "Can't handle multple regs yet"); splitToValueTypes(Arg, ArgInfos, MF, [&](Register Reg) {
llvm_unreachable("Function args should already be split");
SmallVector<Register, 8> Regs; });
splitToValueTypes(Arg, ArgInfos, MF,
[&](unsigned Reg) { Regs.push_back(Reg); });
if (Regs.size() > 1)
MIRBuilder.buildUnmerge(Regs, Arg.Regs[0]);
} }
auto ArgAssignFn = TLI.CCAssignFnForCall(CallConv, IsVarArg); auto ArgAssignFn = TLI.CCAssignFnForCall(CallConv, IsVarArg);

View File

@ -409,7 +409,9 @@ bool X86CallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
if (OrigArg.Flags.isByVal()) if (OrigArg.Flags.isByVal())
return false; return false;
assert(OrigArg.Regs.size() == 1 && "Can't handle multple regs yet"); if (OrigArg.Regs.size() > 1)
return false;
if (!splitToValueTypes(OrigArg, SplitArgs, DL, MRI, if (!splitToValueTypes(OrigArg, SplitArgs, DL, MRI,
[&](ArrayRef<Register> Regs) { [&](ArrayRef<Register> Regs) {
MIRBuilder.buildUnmerge(Regs, OrigArg.Regs[0]); MIRBuilder.buildUnmerge(Regs, OrigArg.Regs[0]);

View File

@ -7,20 +7,14 @@
; CHECK: [[GEP:%[0-9]+]]:_(p0) = G_GEP [[ADDR]], [[CST]](s64) ; CHECK: [[GEP:%[0-9]+]]:_(p0) = G_GEP [[ADDR]], [[CST]](s64)
; CHECK: [[HI:%[0-9]+]]:_(s64) = G_LOAD [[GEP]](p0) :: (load 8 from %ir.ptr + 8) ; CHECK: [[HI:%[0-9]+]]:_(s64) = G_LOAD [[GEP]](p0) :: (load 8 from %ir.ptr + 8)
; CHECK: [[IMPDEF:%[0-9]+]]:_(s128) = G_IMPLICIT_DEF
; CHECK: [[INS1:%[0-9]+]]:_(s128) = G_INSERT [[IMPDEF]], [[LO]](s64), 0
; CHECK: [[INS2:%[0-9]+]]:_(s128) = G_INSERT [[INS1]], [[HI]](s64), 64
; CHECK: [[EXTLO:%[0-9]+]]:_(s64) = G_EXTRACT [[INS2]](s128), 0
; CHECK: [[EXTHI:%[0-9]+]]:_(s64) = G_EXTRACT [[INS2]](s128), 64
; CHECK: [[SP:%[0-9]+]]:_(p0) = COPY $sp ; CHECK: [[SP:%[0-9]+]]:_(p0) = COPY $sp
; CHECK: [[CST2:%[0-9]+]]:_(s64) = G_CONSTANT i64 0 ; CHECK: [[CST2:%[0-9]+]]:_(s64) = G_CONSTANT i64 0
; CHECK: [[GEP2:%[0-9]+]]:_(p0) = G_GEP [[SP]], [[CST2]](s64) ; CHECK: [[GEP2:%[0-9]+]]:_(p0) = G_GEP [[SP]], [[CST2]](s64)
; CHECK: G_STORE [[EXTLO]](s64), [[GEP2]](p0) :: (store 8 into stack, align 1) ; CHECK: G_STORE [[LO]](s64), [[GEP2]](p0) :: (store 8 into stack, align 1)
; CHECK: [[SP:%[0-9]+]]:_(p0) = COPY $sp ; CHECK: [[SP:%[0-9]+]]:_(p0) = COPY $sp
; CHECK: [[CST3:%[0-9]+]]:_(s64) = COPY [[CST]] ; CHECK: [[CST3:%[0-9]+]]:_(s64) = COPY [[CST]]
; CHECK: [[GEP3:%[0-9]+]]:_(p0) = G_GEP [[SP]], [[CST3]](s64) ; CHECK: [[GEP3:%[0-9]+]]:_(p0) = G_GEP [[SP]], [[CST3]](s64)
; CHECK: G_STORE [[EXTHI]](s64), [[GEP3]](p0) :: (store 8 into stack + 8, align 1) ; CHECK: G_STORE [[HI]](s64), [[GEP3]](p0) :: (store 8 into stack + 8, align 1)
define void @test_split_struct([2 x i64]* %ptr) { define void @test_split_struct([2 x i64]* %ptr) {
%struct = load [2 x i64], [2 x i64]* %ptr %struct = load [2 x i64], [2 x i64]* %ptr
call void @take_split_struct([2 x i64]* null, i64 1, i64 2, i64 3, call void @take_split_struct([2 x i64]* null, i64 1, i64 2, i64 3,

View File

@ -59,21 +59,16 @@ define void @take_128bit_struct([2 x i64]* %ptr, [2 x i64] %in) {
; CHECK: [[CST:%[0-9]+]]:_(s64) = G_CONSTANT i64 8 ; CHECK: [[CST:%[0-9]+]]:_(s64) = G_CONSTANT i64 8
; CHECK: [[GEP:%[0-9]+]]:_(p0) = G_GEP %0, [[CST]](s64) ; CHECK: [[GEP:%[0-9]+]]:_(p0) = G_GEP %0, [[CST]](s64)
; CHECK: [[LD2:%[0-9]+]]:_(s64) = G_LOAD %3(p0) :: (load 8 from %ir.ptr + 8) ; CHECK: [[LD2:%[0-9]+]]:_(s64) = G_LOAD %3(p0) :: (load 8 from %ir.ptr + 8)
; CHECK: [[IMPDEF:%[0-9]+]]:_(s128) = G_IMPLICIT_DEF
; CHECK: [[INS1:%[0-9]+]]:_(s128) = G_INSERT [[IMPDEF]], [[LD1]](s64), 0
; CHECK: [[INS2:%[0-9]+]]:_(s128) = G_INSERT [[INS1]], [[LD2]](s64), 64
; CHECK: [[EXT1:%[0-9]+]]:_(s64) = G_EXTRACT [[INS2]](s128), 0
; CHECK: [[EXT2:%[0-9]+]]:_(s64) = G_EXTRACT [[INS2]](s128), 64
; CHECK: [[SP:%[0-9]+]]:_(p0) = COPY $sp ; CHECK: [[SP:%[0-9]+]]:_(p0) = COPY $sp
; CHECK: [[OFF:%[0-9]+]]:_(s64) = G_CONSTANT i64 0 ; CHECK: [[OFF:%[0-9]+]]:_(s64) = G_CONSTANT i64 0
; CHECK: [[ADDR:%[0-9]+]]:_(p0) = G_GEP [[SP]], [[OFF]](s64) ; CHECK: [[ADDR:%[0-9]+]]:_(p0) = G_GEP [[SP]], [[OFF]](s64)
; CHECK: G_STORE [[EXT1]](s64), [[ADDR]](p0) :: (store 8 into stack, align 1) ; CHECK: G_STORE [[LD1]](s64), [[ADDR]](p0) :: (store 8 into stack, align 1)
; CHECK: [[SP:%[0-9]+]]:_(p0) = COPY $sp ; CHECK: [[SP:%[0-9]+]]:_(p0) = COPY $sp
; CHECK: [[OFF:%[0-9]+]]:_(s64) = COPY [[CST]] ; CHECK: [[OFF:%[0-9]+]]:_(s64) = COPY [[CST]]
; CHECK: [[ADDR:%[0-9]+]]:_(p0) = G_GEP [[SP]], [[OFF]] ; CHECK: [[ADDR:%[0-9]+]]:_(p0) = G_GEP [[SP]], [[OFF]]
; CHECK: G_STORE [[EXT2]](s64), [[ADDR]](p0) :: (store 8 into stack + 8, align 1) ; CHECK: G_STORE [[LD2]](s64), [[ADDR]](p0) :: (store 8 into stack + 8, align 1)
define void @test_split_struct([2 x i64]* %ptr) { define void @test_split_struct([2 x i64]* %ptr) {
%struct = load [2 x i64], [2 x i64]* %ptr %struct = load [2 x i64], [2 x i64]* %ptr
call void @take_split_struct([2 x i64]* null, i64 1, i64 2, i64 3, call void @take_split_struct([2 x i64]* null, i64 1, i64 2, i64 3,

View File

@ -112,20 +112,11 @@ define {double, i64, i32} @test_struct_return({double, i64, i32}* %addr) {
; CHECK: [[CST3:%[0-9]+]]:_(s64) = G_CONSTANT i64 24 ; CHECK: [[CST3:%[0-9]+]]:_(s64) = G_CONSTANT i64 24
; CHECK: [[GEP3:%[0-9]+]]:_(p0) = G_GEP %0, [[CST3]](s64) ; CHECK: [[GEP3:%[0-9]+]]:_(p0) = G_GEP %0, [[CST3]](s64)
; CHECK: [[LD4:%[0-9]+]]:_(s64) = G_LOAD [[GEP3]](p0) :: (load 8 from %ir.addr + 24) ; CHECK: [[LD4:%[0-9]+]]:_(s64) = G_LOAD [[GEP3]](p0) :: (load 8 from %ir.addr + 24)
; CHECK: [[IMPDEF:%[0-9]+]]:_(s256) = G_IMPLICIT_DEF
; CHECK: [[INS1:%[0-9]+]]:_(s256) = G_INSERT [[IMPDEF]], [[LD1]](s64), 0
; CHECK: [[INS2:%[0-9]+]]:_(s256) = G_INSERT [[INS1]], [[LD2]](s64), 64
; CHECK: [[INS3:%[0-9]+]]:_(s256) = G_INSERT [[INS2]], [[LD3]](s64), 128
; CHECK: [[ARG:%[0-9]+]]:_(s256) = G_INSERT [[INS3]], [[LD4]](s64), 192
; CHECK: [[E0:%[0-9]+]]:_(s64) = G_EXTRACT [[ARG]](s256), 0
; CHECK: [[E1:%[0-9]+]]:_(s64) = G_EXTRACT [[ARG]](s256), 64
; CHECK: [[E2:%[0-9]+]]:_(s64) = G_EXTRACT [[ARG]](s256), 128
; CHECK: [[E3:%[0-9]+]]:_(s64) = G_EXTRACT [[ARG]](s256), 192
; CHECK: $x0 = COPY [[E0]](s64) ; CHECK: $x0 = COPY [[LD1]](s64)
; CHECK: $x1 = COPY [[E1]](s64) ; CHECK: $x1 = COPY [[LD2]](s64)
; CHECK: $x2 = COPY [[E2]](s64) ; CHECK: $x2 = COPY [[LD3]](s64)
; CHECK: $x3 = COPY [[E3]](s64) ; CHECK: $x3 = COPY [[LD4]](s64)
; CHECK: BL @arr_callee, csr_aarch64_aapcs, implicit-def $lr, implicit $sp, implicit $x0, implicit $x1, implicit $x2, implicit $x3, implicit-def $x0, implicit-def $x1, implicit-def $x2, implicit-def $x3 ; CHECK: BL @arr_callee, csr_aarch64_aapcs, implicit-def $lr, implicit $sp, implicit $x0, implicit $x1, implicit $x2, implicit $x3, implicit-def $x0, implicit-def $x1, implicit-def $x2, implicit-def $x3
; CHECK: [[E0:%[0-9]+]]:_(s64) = COPY $x0 ; CHECK: [[E0:%[0-9]+]]:_(s64) = COPY $x0
; CHECK: [[E1:%[0-9]+]]:_(s64) = COPY $x1 ; CHECK: [[E1:%[0-9]+]]:_(s64) = COPY $x1
@ -262,20 +253,14 @@ define void @take_128bit_struct([2 x i64]* %ptr, [2 x i64] %in) {
; CHECK: [[GEP:%[0-9]+]]:_(p0) = G_GEP [[ADDR]], [[CST]](s64) ; CHECK: [[GEP:%[0-9]+]]:_(p0) = G_GEP [[ADDR]], [[CST]](s64)
; CHECK: [[HI:%[0-9]+]]:_(s64) = G_LOAD [[GEP]](p0) :: (load 8 from %ir.ptr + 8) ; CHECK: [[HI:%[0-9]+]]:_(s64) = G_LOAD [[GEP]](p0) :: (load 8 from %ir.ptr + 8)
; CHECK: [[IMPDEF:%[0-9]+]]:_(s128) = G_IMPLICIT_DEF
; CHECK: [[INS1:%[0-9]+]]:_(s128) = G_INSERT [[IMPDEF]], [[LO]](s64), 0
; CHECK: [[INS2:%[0-9]+]]:_(s128) = G_INSERT [[INS1]], [[HI]](s64), 64
; CHECK: [[EXTLO:%[0-9]+]]:_(s64) = G_EXTRACT [[INS2]](s128), 0
; CHECK: [[EXTHI:%[0-9]+]]:_(s64) = G_EXTRACT [[INS2]](s128), 64
; CHECK: [[SP:%[0-9]+]]:_(p0) = COPY $sp ; CHECK: [[SP:%[0-9]+]]:_(p0) = COPY $sp
; CHECK: [[CST2:%[0-9]+]]:_(s64) = G_CONSTANT i64 0 ; CHECK: [[CST2:%[0-9]+]]:_(s64) = G_CONSTANT i64 0
; CHECK: [[GEP2:%[0-9]+]]:_(p0) = G_GEP [[SP]], [[CST2]](s64) ; CHECK: [[GEP2:%[0-9]+]]:_(p0) = G_GEP [[SP]], [[CST2]](s64)
; CHECK: G_STORE [[EXTLO]](s64), [[GEP2]](p0) :: (store 8 into stack, align 1) ; CHECK: G_STORE [[LO]](s64), [[GEP2]](p0) :: (store 8 into stack, align 1)
; CHECK: [[SP:%[0-9]+]]:_(p0) = COPY $sp ; CHECK: [[SP:%[0-9]+]]:_(p0) = COPY $sp
; CHECK: [[CST3:%[0-9]+]]:_(s64) = COPY [[CST]] ; CHECK: [[CST3:%[0-9]+]]:_(s64) = COPY [[CST]]
; CHECK: [[GEP3:%[0-9]+]]:_(p0) = G_GEP [[SP]], [[CST3]](s64) ; CHECK: [[GEP3:%[0-9]+]]:_(p0) = G_GEP [[SP]], [[CST3]](s64)
; CHECK: G_STORE [[EXTHI]](s64), [[GEP3]](p0) :: (store 8 into stack + 8, align 1) ; CHECK: G_STORE [[HI]](s64), [[GEP3]](p0) :: (store 8 into stack + 8, align 1)
define void @test_split_struct([2 x i64]* %ptr) { define void @test_split_struct([2 x i64]* %ptr) {
%struct = load [2 x i64], [2 x i64]* %ptr %struct = load [2 x i64], [2 x i64]* %ptr
call void @take_split_struct([2 x i64]* null, i64 1, i64 2, i64 3, call void @take_split_struct([2 x i64]* null, i64 1, i64 2, i64 3,

View File

@ -202,11 +202,7 @@ define arm_aapcscc [3 x i32] @test_tiny_int_arrays([2 x i32] %arr) {
; CHECK: liveins: $r0, $r1 ; CHECK: liveins: $r0, $r1
; CHECK: [[R0:%[0-9]+]]:_(s32) = COPY $r0 ; CHECK: [[R0:%[0-9]+]]:_(s32) = COPY $r0
; CHECK: [[R1:%[0-9]+]]:_(s32) = COPY $r1 ; CHECK: [[R1:%[0-9]+]]:_(s32) = COPY $r1
; CHECK: [[IMPDEF:%[0-9]+]]:_(s64) = G_IMPLICIT_DEF
; CHECK: [[INS1:%[0-9]+]]:_(s64) = G_INSERT [[IMPDEF]], [[R0]](s32), 0
; CHECK: [[INS2:%[0-9]+]]:_(s64) = G_INSERT [[INS1]], [[R1]](s32), 32
; CHECK: ADJCALLSTACKDOWN 0, 0, 14, $noreg, implicit-def $sp, implicit $sp ; CHECK: ADJCALLSTACKDOWN 0, 0, 14, $noreg, implicit-def $sp, implicit $sp
; CHECK: [[R0:%[0-9]+]]:_(s32), [[R1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[INS2]](s64)
; CHECK: $r0 = COPY [[R0]] ; CHECK: $r0 = COPY [[R0]]
; CHECK: $r1 = COPY [[R1]] ; CHECK: $r1 = COPY [[R1]]
; ARM: BL @tiny_int_arrays_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $r0, implicit $r1, implicit-def $r0, implicit-def $r1 ; ARM: BL @tiny_int_arrays_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $r0, implicit $r1, implicit-def $r0, implicit-def $r1
@ -237,15 +233,7 @@ define arm_aapcscc void @test_multiple_int_arrays([2 x i32] %arr0, [2 x i32] %ar
; CHECK: [[R1:%[0-9]+]]:_(s32) = COPY $r1 ; CHECK: [[R1:%[0-9]+]]:_(s32) = COPY $r1
; CHECK: [[R2:%[0-9]+]]:_(s32) = COPY $r2 ; CHECK: [[R2:%[0-9]+]]:_(s32) = COPY $r2
; CHECK: [[R3:%[0-9]+]]:_(s32) = COPY $r3 ; CHECK: [[R3:%[0-9]+]]:_(s32) = COPY $r3
; CHECK: [[IMPDEF:%[0-9]+]]:_(s64) = G_IMPLICIT_DEF
; CHECK: [[INS1:%[0-9]+]]:_(s64) = G_INSERT [[IMPDEF]], [[R0]](s32), 0
; CHECK: [[INS2:%[0-9]+]]:_(s64) = G_INSERT [[INS1]], [[R1]](s32), 32
; CHECK: [[IMPDEF2:%[0-9]+]]:_(s64) = G_IMPLICIT_DEF
; CHECK: [[INS3:%[0-9]+]]:_(s64) = G_INSERT [[IMPDEF2]], [[R2]](s32), 0
; CHECK: [[INS4:%[0-9]+]]:_(s64) = G_INSERT [[INS3]], [[R3]](s32), 32
; CHECK: ADJCALLSTACKDOWN 0, 0, 14, $noreg, implicit-def $sp, implicit $sp ; CHECK: ADJCALLSTACKDOWN 0, 0, 14, $noreg, implicit-def $sp, implicit $sp
; CHECK: [[R0:%[0-9]+]]:_(s32), [[R1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[INS2]](s64)
; CHECK: [[R2:%[0-9]+]]:_(s32), [[R3:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[INS4]](s64)
; CHECK: $r0 = COPY [[R0]] ; CHECK: $r0 = COPY [[R0]]
; CHECK: $r1 = COPY [[R1]] ; CHECK: $r1 = COPY [[R1]]
; CHECK: $r2 = COPY [[R2]] ; CHECK: $r2 = COPY [[R2]]
@ -278,11 +266,7 @@ define arm_aapcscc void @test_large_int_arrays([20 x i32] %arr) {
; CHECK: [[FIRST_STACK_ELEMENT:%[0-9]+]]:_(s32) = G_LOAD [[FIRST_STACK_ELEMENT_FI]]{{.*}}load 4 from %fixed-stack.[[FIRST_STACK_ID]] ; CHECK: [[FIRST_STACK_ELEMENT:%[0-9]+]]:_(s32) = G_LOAD [[FIRST_STACK_ELEMENT_FI]]{{.*}}load 4 from %fixed-stack.[[FIRST_STACK_ID]]
; CHECK: [[LAST_STACK_ELEMENT_FI:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.[[LAST_STACK_ID]] ; CHECK: [[LAST_STACK_ELEMENT_FI:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.[[LAST_STACK_ID]]
; CHECK: [[LAST_STACK_ELEMENT:%[0-9]+]]:_(s32) = G_LOAD [[LAST_STACK_ELEMENT_FI]]{{.*}}load 4 from %fixed-stack.[[LAST_STACK_ID]] ; CHECK: [[LAST_STACK_ELEMENT:%[0-9]+]]:_(s32) = G_LOAD [[LAST_STACK_ELEMENT_FI]]{{.*}}load 4 from %fixed-stack.[[LAST_STACK_ID]]
; CHECK: [[IMPDEF:%[0-9]+]]:_(s640) = G_IMPLICIT_DEF
; CHECK: [[INS1:%[0-9]+]]:_(s640) = G_INSERT [[IMPDEF]], [[R0]](s32), 0
; CHECK: [[INS:%[0-9]+]]:_(s640) = G_INSERT {{.*}}, [[LAST_STACK_ELEMENT]](s32), 608
; CHECK: ADJCALLSTACKDOWN 64, 0, 14, $noreg, implicit-def $sp, implicit $sp ; CHECK: ADJCALLSTACKDOWN 64, 0, 14, $noreg, implicit-def $sp, implicit $sp
; CHECK: [[R0:%[0-9]+]]:_(s32), [[R1:%[0-9]+]]:_(s32), [[R2:%[0-9]+]]:_(s32), [[R3:%[0-9]+]]:_(s32), [[FIRST_STACK_ELEMENT:%[0-9]+]]:_(s32), {{.*}}, [[LAST_STACK_ELEMENT:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[INS]](s640)
; CHECK: $r0 = COPY [[R0]] ; CHECK: $r0 = COPY [[R0]]
; CHECK: $r1 = COPY [[R1]] ; CHECK: $r1 = COPY [[R1]]
; CHECK: $r2 = COPY [[R2]] ; CHECK: $r2 = COPY [[R2]]
@ -324,12 +308,7 @@ define arm_aapcscc [2 x float] @test_fp_arrays_aapcs([3 x double] %arr) {
; BIG: [[ARR1:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[ARR1_1]](s32), [[ARR1_0]](s32) ; BIG: [[ARR1:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[ARR1_1]](s32), [[ARR1_0]](s32)
; CHECK: [[ARR2_FI:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.[[ARR2_ID]] ; CHECK: [[ARR2_FI:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.[[ARR2_ID]]
; CHECK: [[ARR2:%[0-9]+]]:_(s64) = G_LOAD [[ARR2_FI]]{{.*}}load 8 from %fixed-stack.[[ARR2_ID]] ; CHECK: [[ARR2:%[0-9]+]]:_(s64) = G_LOAD [[ARR2_FI]]{{.*}}load 8 from %fixed-stack.[[ARR2_ID]]
; CHECK: [[IMPDEF:%[0-9]+]]:_(s192) = G_IMPLICIT_DEF
; CHECK: [[INS1:%[0-9]+]]:_(s192) = G_INSERT [[IMPDEF]], [[ARR0]](s64), 0
; CHECK: [[INS2:%[0-9]+]]:_(s192) = G_INSERT [[INS1]], [[ARR1]](s64), 64
; CHECK: [[INS3:%[0-9]+]]:_(s192) = G_INSERT [[INS2]], [[ARR2]](s64), 128
; CHECK: ADJCALLSTACKDOWN 8, 0, 14, $noreg, implicit-def $sp, implicit $sp ; CHECK: ADJCALLSTACKDOWN 8, 0, 14, $noreg, implicit-def $sp, implicit $sp
; CHECK: [[ARR0:%[0-9]+]]:_(s64), [[ARR1:%[0-9]+]]:_(s64), [[ARR2:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[INS3]](s192)
; CHECK: [[ARR0_0:%[0-9]+]]:_(s32), [[ARR0_1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[ARR0]](s64) ; CHECK: [[ARR0_0:%[0-9]+]]:_(s32), [[ARR0_1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[ARR0]](s64)
; LITTLE: $r0 = COPY [[ARR0_0]](s32) ; LITTLE: $r0 = COPY [[ARR0_0]](s32)
; LITTLE: $r1 = COPY [[ARR0_1]](s32) ; LITTLE: $r1 = COPY [[ARR0_1]](s32)
@ -382,23 +361,7 @@ define arm_aapcs_vfpcc [4 x float] @test_fp_arrays_aapcs_vfp([3 x double] %x, [3
; CHECK: [[Z2:%[0-9]+]]:_(s64) = G_LOAD [[Z2_FI]]{{.*}}load 8 ; CHECK: [[Z2:%[0-9]+]]:_(s64) = G_LOAD [[Z2_FI]]{{.*}}load 8
; CHECK: [[Z3_FI:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.[[Z3_ID]] ; CHECK: [[Z3_FI:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.[[Z3_ID]]
; CHECK: [[Z3:%[0-9]+]]:_(s64) = G_LOAD [[Z3_FI]]{{.*}}load 8 ; CHECK: [[Z3:%[0-9]+]]:_(s64) = G_LOAD [[Z3_FI]]{{.*}}load 8
; CHECK: [[IMPDEF:%[0-9]+]]:_(s192) = G_IMPLICIT_DEF
; CHECK: [[INS1:%[0-9]+]]:_(s192) = G_INSERT [[IMPDEF]], [[X0]](s64), 0
; CHECK: [[INS2:%[0-9]+]]:_(s192) = G_INSERT [[INS1]], [[X1]](s64), 64
; CHECK: [[INS3:%[0-9]+]]:_(s192) = G_INSERT [[INS2]], [[X2]](s64), 128
; CHECK: [[IMPDEF2:%[0-9]+]]:_(s96) = G_IMPLICIT_DEF
; CHECK: [[INS4:%[0-9]+]]:_(s96) = G_INSERT [[IMPDEF2]], [[Y0]](s32), 0
; CHECK: [[INS5:%[0-9]+]]:_(s96) = G_INSERT [[INS4]], [[Y1]](s32), 32
; CHECK: [[INS6:%[0-9]+]]:_(s96) = G_INSERT [[INS5]], [[Y2]](s32), 64
; CHECK: [[IMPDEF3:%[0-9]+]]:_(s256) = G_IMPLICIT_DEF
; CHECK: [[INS7:%[0-9]+]]:_(s256) = G_INSERT [[IMPDEF3]], [[Z0]](s64), 0
; CHECK: [[INS8:%[0-9]+]]:_(s256) = G_INSERT [[INS7]], [[Z1]](s64), 64
; CHECK: [[INS9:%[0-9]+]]:_(s256) = G_INSERT [[INS8]], [[Z2]](s64), 128
; CHECK: [[INS10:%[0-9]+]]:_(s256) = G_INSERT [[INS9]], [[Z3]](s64), 192
; CHECK: ADJCALLSTACKDOWN 32, 0, 14, $noreg, implicit-def $sp, implicit $sp ; CHECK: ADJCALLSTACKDOWN 32, 0, 14, $noreg, implicit-def $sp, implicit $sp
; CHECK: [[X0:%[0-9]+]]:_(s64), [[X1:%[0-9]+]]:_(s64), [[X2:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[INS3]](s192)
; CHECK: [[Y0:%[0-9]+]]:_(s32), [[Y1:%[0-9]+]]:_(s32), [[Y2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[INS6]](s96)
; CHECK: [[Z0:%[0-9]+]]:_(s64), [[Z1:%[0-9]+]]:_(s64), [[Z2:%[0-9]+]]:_(s64), [[Z3:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[INS10]](s256)
; CHECK: $d0 = COPY [[X0]](s64) ; CHECK: $d0 = COPY [[X0]](s64)
; CHECK: $d1 = COPY [[X1]](s64) ; CHECK: $d1 = COPY [[X1]](s64)
; CHECK: $d2 = COPY [[X2]](s64) ; CHECK: $d2 = COPY [[X2]](s64)
@ -457,9 +420,7 @@ define arm_aapcscc [2 x i32*] @test_tough_arrays([6 x [4 x i32]] %arr) {
; CHECK: [[FIRST_STACK_ELEMENT:%[0-9]+]]:_(s32) = G_LOAD [[FIRST_STACK_ELEMENT_FI]]{{.*}}load 4 from %fixed-stack.[[FIRST_STACK_ID]] ; CHECK: [[FIRST_STACK_ELEMENT:%[0-9]+]]:_(s32) = G_LOAD [[FIRST_STACK_ELEMENT_FI]]{{.*}}load 4 from %fixed-stack.[[FIRST_STACK_ID]]
; CHECK: [[LAST_STACK_ELEMENT_FI:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.[[LAST_STACK_ID]] ; CHECK: [[LAST_STACK_ELEMENT_FI:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.[[LAST_STACK_ID]]
; CHECK: [[LAST_STACK_ELEMENT:%[0-9]+]]:_(s32) = G_LOAD [[LAST_STACK_ELEMENT_FI]]{{.*}}load 4 from %fixed-stack.[[LAST_STACK_ID]] ; CHECK: [[LAST_STACK_ELEMENT:%[0-9]+]]:_(s32) = G_LOAD [[LAST_STACK_ELEMENT_FI]]{{.*}}load 4 from %fixed-stack.[[LAST_STACK_ID]]
; CHECK: [[INS:%[0-9]+]]:_(s768) = G_INSERT {{.*}}, [[LAST_STACK_ELEMENT]](s32), 736
; CHECK: ADJCALLSTACKDOWN 80, 0, 14, $noreg, implicit-def $sp, implicit $sp ; CHECK: ADJCALLSTACKDOWN 80, 0, 14, $noreg, implicit-def $sp, implicit $sp
; CHECK: [[R0:%[0-9]+]]:_(s32), [[R1:%[0-9]+]]:_(s32), [[R2:%[0-9]+]]:_(s32), [[R3:%[0-9]+]]:_(s32), [[FIRST_STACK_ELEMENT:%[0-9]+]]:_(s32), {{.*}}, [[LAST_STACK_ELEMENT:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[INS]](s768)
; CHECK: $r0 = COPY [[R0]] ; CHECK: $r0 = COPY [[R0]]
; CHECK: $r1 = COPY [[R1]] ; CHECK: $r1 = COPY [[R1]]
; CHECK: $r2 = COPY [[R2]] ; CHECK: $r2 = COPY [[R2]]
@ -495,11 +456,7 @@ define arm_aapcscc {i32, i32} @test_structs({i32, i32} %x) {
; CHECK: liveins: $r0, $r1 ; CHECK: liveins: $r0, $r1
; CHECK-DAG: [[X0:%[0-9]+]]:_(s32) = COPY $r0 ; CHECK-DAG: [[X0:%[0-9]+]]:_(s32) = COPY $r0
; CHECK-DAG: [[X1:%[0-9]+]]:_(s32) = COPY $r1 ; CHECK-DAG: [[X1:%[0-9]+]]:_(s32) = COPY $r1
; CHECK: [[IMPDEF:%[0-9]+]]:_(s64) = G_IMPLICIT_DEF
; CHECK: [[INS1:%[0-9]+]]:_(s64) = G_INSERT [[IMPDEF]], [[X0]](s32), 0
; CHECK: [[INS2:%[0-9]+]]:_(s64) = G_INSERT [[INS1]], [[X1]](s32), 32
; CHECK: ADJCALLSTACKDOWN 0, 0, 14, $noreg, implicit-def $sp, implicit $sp ; CHECK: ADJCALLSTACKDOWN 0, 0, 14, $noreg, implicit-def $sp, implicit $sp
; CHECK: [[X0:%[0-9]+]]:_(s32), [[X1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[INS2]](s64)
; CHECK-DAG: $r0 = COPY [[X0]](s32) ; CHECK-DAG: $r0 = COPY [[X0]](s32)
; CHECK-DAG: $r1 = COPY [[X1]](s32) ; CHECK-DAG: $r1 = COPY [[X1]](s32)
; ARM: BL @structs_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $r0, implicit $r1, implicit-def $r0, implicit-def $r1 ; ARM: BL @structs_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $r0, implicit $r1, implicit-def $r0, implicit-def $r1