Index: llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h =================================================================== --- llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h +++ llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h @@ -258,8 +258,9 @@ /// /// \p CI is the call/invoke instruction. /// - /// \p ResReg is a register where the call's return value should be stored (or - /// 0 if there is no return value). + /// \p ResRegs are the registers where the call's return value should be + /// stored (or 0 if there is no return value). There will be one register for + /// each non-aggregate type, as returned by \c computeValueLLTs. /// /// \p ArgRegs is a list of virtual registers containing each argument that /// needs to be passed. @@ -275,10 +276,9 @@ /// /// \return true if the lowering succeeded, false otherwise. bool lowerCall(MachineIRBuilder &MIRBuilder, ImmutableCallSite CS, - unsigned ResReg, ArrayRef ArgRegs, + ArrayRef ResRegs, ArrayRef ArgRegs, unsigned SwiftErrorVReg, std::function GetCalleeReg) const; - }; } // end namespace llvm Index: llvm/lib/CodeGen/GlobalISel/CallLowering.cpp =================================================================== --- llvm/lib/CodeGen/GlobalISel/CallLowering.cpp +++ llvm/lib/CodeGen/GlobalISel/CallLowering.cpp @@ -28,7 +28,8 @@ void CallLowering::anchor() {} bool CallLowering::lowerCall(MachineIRBuilder &MIRBuilder, ImmutableCallSite CS, - unsigned ResReg, ArrayRef ArgRegs, + ArrayRef ResRegs, + ArrayRef ArgRegs, unsigned SwiftErrorVReg, std::function GetCalleeReg) const { auto &DL = CS.getParent()->getParent()->getParent()->getDataLayout(); @@ -56,7 +57,7 @@ else Callee = MachineOperand::CreateReg(GetCalleeReg(), false); - ArgInfo OrigRet{ResReg, CS.getType(), ISD::ArgFlagsTy{}}; + ArgInfo OrigRet{ResRegs, CS.getType(), ISD::ArgFlagsTy{}}; if (!OrigRet.Ty->isVoidTy()) setArgFlags(OrigRet, AttributeList::ReturnIndex, DL, CS); Index: llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp =================================================================== --- llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp +++ llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp @@ -1208,10 +1208,7 @@ } if (!F || !F->isIntrinsic() || ID == Intrinsic::not_intrinsic) { - bool IsSplitType = valueIsSplit(CI); - unsigned Res = IsSplitType ? MRI->createGenericVirtualRegister( - getLLTForType(*CI.getType(), *DL)) - : getOrCreateVReg(CI); + ArrayRef Res = getOrCreateVRegs(CI); SmallVector Args; unsigned SwiftErrorVReg = 0; @@ -1234,9 +1231,6 @@ CLI->lowerCall(MIRBuilder, &CI, Res, Args, SwiftErrorVReg, [&]() { return getOrCreateVReg(*CI.getCalledValue()); }); - if (IsSplitType) - unpackRegs(CI, Res, MIRBuilder); - return Success; } @@ -1310,9 +1304,9 @@ MCSymbol *BeginSymbol = Context.createTempSymbol(); MIRBuilder.buildInstr(TargetOpcode::EH_LABEL).addSym(BeginSymbol); - unsigned Res = 0; + ArrayRef Res; if (!I.getType()->isVoidTy()) - Res = MRI->createGenericVirtualRegister(getLLTForType(*I.getType(), *DL)); + Res = getOrCreateVRegs(I); SmallVector Args; unsigned SwiftErrorVReg = 0; for (auto &Arg : I.arg_operands()) { @@ -1334,8 +1328,6 @@ [&]() { return getOrCreateVReg(*I.getCalledValue()); })) return false; - unpackRegs(I, Res, MIRBuilder); - MCSymbol *EndSymbol = Context.createTempSymbol(); MIRBuilder.buildInstr(TargetOpcode::EH_LABEL).addSym(EndSymbol); Index: llvm/lib/Target/AArch64/AArch64CallLowering.cpp =================================================================== --- llvm/lib/Target/AArch64/AArch64CallLowering.cpp +++ llvm/lib/Target/AArch64/AArch64CallLowering.cpp @@ -498,24 +498,18 @@ // symmetry with the arugments, the physical register must be an // implicit-define of the call instruction. CCAssignFn *RetAssignFn = TLI.CCAssignFnForReturn(F.getCallingConv()); - assert(OrigRet.Regs.size() == 1 && "Can't handle multple regs yet"); - if (OrigRet.Regs[0]) { + if (!OrigRet.Ty->isVoidTy()) { SplitArgs.clear(); - SmallVector RegOffsets; - SmallVector SplitRegs; splitToValueTypes(OrigRet, SplitArgs, DL, MRI, F.getCallingConv(), [&](unsigned Reg, uint64_t Offset) { - RegOffsets.push_back(Offset); - SplitRegs.push_back(Reg); + llvm_unreachable( + "Call results should already be split"); }); CallReturnHandler Handler(MIRBuilder, MRI, MIB, RetAssignFn); if (!handleAssignments(MIRBuilder, SplitArgs, Handler)) return false; - - if (!RegOffsets.empty()) - MIRBuilder.buildSequence(OrigRet.Regs[0], SplitRegs, RegOffsets); } if (SwiftErrorVReg) { Index: llvm/lib/Target/ARM/ARMCallLowering.cpp =================================================================== --- llvm/lib/Target/ARM/ARMCallLowering.cpp +++ llvm/lib/Target/ARM/ARMCallLowering.cpp @@ -619,21 +619,14 @@ return false; ArgInfos.clear(); - SmallVector SplitRegs; - splitToValueTypes(OrigRet, ArgInfos, MF, - [&](unsigned Reg) { SplitRegs.push_back(Reg); }); + splitToValueTypes(OrigRet, ArgInfos, MF, [&](unsigned Reg) { + llvm_unreachable("Call results should already be split"); + }); auto RetAssignFn = TLI.CCAssignFnForReturn(CallConv, IsVarArg); CallReturnHandler RetHandler(MIRBuilder, MRI, MIB, RetAssignFn); if (!handleAssignments(MIRBuilder, ArgInfos, RetHandler)) return false; - - if (!SplitRegs.empty()) { - // We have split the value and allocated each individual piece, now build - // it up again. - assert(OrigRet.Regs.size() == 1 && "Can't handle multple regs yet"); - MIRBuilder.buildMerge(OrigRet.Regs[0], SplitRegs); - } } // We now know the size of the stack - update the ADJCALLSTACKDOWN Index: llvm/lib/Target/ARM/ARMLegalizerInfo.cpp =================================================================== --- llvm/lib/Target/ARM/ARMLegalizerInfo.cpp +++ llvm/lib/Target/ARM/ARMLegalizerInfo.cpp @@ -369,24 +369,17 @@ MI.getOpcode() == G_SREM ? RTLIB::SDIVREM_I32 : RTLIB::UDIVREM_I32; // Our divmod libcalls return a struct containing the quotient and the - // remainder. We need to create a virtual register for it. + // remainder. Create a new, unused register for the quotient and use the + // destination of the original instruction for the remainder. Type *ArgTy = Type::getInt32Ty(Ctx); StructType *RetTy = StructType::get(Ctx, {ArgTy, ArgTy}, /* Packed */ true); - auto RetVal = MRI.createGenericVirtualRegister( - getLLTForType(*RetTy, MIRBuilder.getMF().getDataLayout())); - - auto Status = createLibcall(MIRBuilder, Libcall, {RetVal, RetTy}, + unsigned RetRegs[] = {MRI.createGenericVirtualRegister(LLT::scalar(32)), + OriginalResult}; + auto Status = createLibcall(MIRBuilder, Libcall, {RetRegs, RetTy}, {{MI.getOperand(1).getReg(), ArgTy}, {MI.getOperand(2).getReg(), ArgTy}}); if (Status != LegalizerHelper::Legalized) return false; - - // The remainder is the second result of divmod. Split the return value into - // a new, unused register for the quotient and the destination of the - // original instruction for the remainder. - MIRBuilder.buildUnmerge( - {MRI.createGenericVirtualRegister(LLT::scalar(32)), OriginalResult}, - RetVal); break; } case G_FCMP: { Index: llvm/lib/Target/Mips/MipsCallLowering.cpp =================================================================== --- llvm/lib/Target/Mips/MipsCallLowering.cpp +++ llvm/lib/Target/Mips/MipsCallLowering.cpp @@ -514,7 +514,6 @@ return false; } - assert(OrigRet.Regs.size() == 1 && "Can't handle multple regs yet"); if (OrigRet.Regs[0] && !isSupportedType(OrigRet.Ty)) return false; Index: llvm/lib/Target/X86/X86CallLowering.cpp =================================================================== --- llvm/lib/Target/X86/X86CallLowering.cpp +++ llvm/lib/Target/X86/X86CallLowering.cpp @@ -453,7 +453,8 @@ // implicit-define of the call instruction. if (!OrigRet.Ty->isVoidTy()) { - assert(OrigRet.Regs.size() == 1 && "Can't handle multple regs yet"); + if (OrigRet.Regs.size() > 1) + return false; SplitArgs.clear(); SmallVector NewRegs; Index: llvm/test/CodeGen/AArch64/GlobalISel/call-translator.ll =================================================================== --- llvm/test/CodeGen/AArch64/GlobalISel/call-translator.ll +++ llvm/test/CodeGen/AArch64/GlobalISel/call-translator.ll @@ -131,8 +131,7 @@ ; CHECK: [[E1:%[0-9]+]]:_(s64) = COPY $x1 ; CHECK: [[E2:%[0-9]+]]:_(s64) = COPY $x2 ; CHECK: [[E3:%[0-9]+]]:_(s64) = COPY $x3 -; CHECK: [[RES:%[0-9]+]]:_(s256) = G_MERGE_VALUES [[E0]](s64), [[E1]](s64), [[E2]](s64), [[E3]](s64) -; CHECK: G_EXTRACT [[RES]](s256), 64 +; CHECK: $x0 = COPY [[E1]] declare [4 x i64] @arr_callee([4 x i64]) define i64 @test_arr_call([4 x i64]* %addr) { %arg = load [4 x i64], [4 x i64]* %addr Index: llvm/test/CodeGen/ARM/GlobalISel/arm-param-lowering.ll =================================================================== --- llvm/test/CodeGen/ARM/GlobalISel/arm-param-lowering.ll +++ llvm/test/CodeGen/ARM/GlobalISel/arm-param-lowering.ll @@ -214,17 +214,13 @@ ; CHECK: [[R0:%[0-9]+]]:_(s32) = COPY $r0 ; CHECK: [[R1:%[0-9]+]]:_(s32) = COPY $r1 ; CHECK: [[R2:%[0-9]+]]:_(s32) = COPY $r2 -; CHECK: [[RES_ARR:%[0-9]+]]:_(s96) = G_MERGE_VALUES [[R0]](s32), [[R1]](s32), [[R2]](s32) ; CHECK: ADJCALLSTACKUP 0, 0, 14, $noreg, implicit-def $sp, implicit $sp -; CHECK: [[EXT3:%[0-9]+]]:_(s32) = G_EXTRACT [[RES_ARR]](s96), 0 -; CHECK: [[EXT4:%[0-9]+]]:_(s32) = G_EXTRACT [[RES_ARR]](s96), 32 -; CHECK: [[EXT5:%[0-9]+]]:_(s32) = G_EXTRACT [[RES_ARR]](s96), 64 ; FIXME: This doesn't seem correct with regard to the AAPCS docs (which say ; that composite types larger than 4 bytes should be passed through memory), ; but it's what DAGISel does. We should fix it in the common code for both. -; CHECK: $r0 = COPY [[EXT3]] -; CHECK: $r1 = COPY [[EXT4]] -; CHECK: $r2 = COPY [[EXT5]] +; CHECK: $r0 = COPY [[R0]] +; CHECK: $r1 = COPY [[R1]] +; CHECK: $r2 = COPY [[R2]] ; ARM: BX_RET 14, $noreg, implicit $r0, implicit $r1, implicit $r2 ; THUMB: tBX_RET 14, $noreg, implicit $r0, implicit $r1, implicit $r2 entry: @@ -352,12 +348,9 @@ ; THUMB: tBL 14, $noreg, @fp_arrays_aapcs_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $r0, implicit $r1, implicit $r2, implicit $r3, implicit-def $r0, implicit-def $r1 ; CHECK: [[R0:%[0-9]+]]:_(s32) = COPY $r0 ; CHECK: [[R1:%[0-9]+]]:_(s32) = COPY $r1 -; CHECK: [[R_MERGED:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[R0]](s32), [[R1]](s32) ; CHECK: ADJCALLSTACKUP 8, 0, 14, $noreg, implicit-def $sp, implicit $sp -; CHECK: [[EXT4:%[0-9]+]]:_(s32) = G_EXTRACT [[R_MERGED]](s64), 0 -; CHECK: [[EXT5:%[0-9]+]]:_(s32) = G_EXTRACT [[R_MERGED]](s64), 32 -; CHECK: $r0 = COPY [[EXT4]] -; CHECK: $r1 = COPY [[EXT5]] +; CHECK: $r0 = COPY [[R0]] +; CHECK: $r1 = COPY [[R1]] ; ARM: BX_RET 14, $noreg, implicit $r0, implicit $r1 ; THUMB: tBX_RET 14, $noreg, implicit $r0, implicit $r1 entry: @@ -434,16 +427,11 @@ ; CHECK: [[R1:%[0-9]+]]:_(s32) = COPY $s1 ; CHECK: [[R2:%[0-9]+]]:_(s32) = COPY $s2 ; CHECK: [[R3:%[0-9]+]]:_(s32) = COPY $s3 -; CHECK: [[R_MERGED:%[0-9]+]]:_(s128) = G_MERGE_VALUES [[R0]](s32), [[R1]](s32), [[R2]](s32), [[R3]](s32) ; CHECK: ADJCALLSTACKUP 32, 0, 14, $noreg, implicit-def $sp, implicit $sp -; CHECK: [[EXT11:%[0-9]+]]:_(s32) = G_EXTRACT [[R_MERGED]](s128), 0 -; CHECK: [[EXT12:%[0-9]+]]:_(s32) = G_EXTRACT [[R_MERGED]](s128), 32 -; CHECK: [[EXT13:%[0-9]+]]:_(s32) = G_EXTRACT [[R_MERGED]](s128), 64 -; CHECK: [[EXT14:%[0-9]+]]:_(s32) = G_EXTRACT [[R_MERGED]](s128), 96 -; CHECK: $s0 = COPY [[EXT11]] -; CHECK: $s1 = COPY [[EXT12]] -; CHECK: $s2 = COPY [[EXT13]] -; CHECK: $s3 = COPY [[EXT14]] +; CHECK: $s0 = COPY [[R0]] +; CHECK: $s1 = COPY [[R1]] +; CHECK: $s2 = COPY [[R2]] +; CHECK: $s3 = COPY [[R3]] ; ARM: BX_RET 14, $noreg, implicit $s0, implicit $s1, implicit $s2, implicit $s3 ; THUMB: tBX_RET 14, $noreg, implicit $s0, implicit $s1, implicit $s2, implicit $s3 entry: @@ -488,14 +476,11 @@ ; CHECK: G_STORE [[LAST_STACK_ELEMENT]](s32), [[LAST_STACK_ARG_ADDR]]{{.*}}store 4 ; ARM: BL @tough_arrays_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $r0, implicit $r1, implicit $r2, implicit $r3, implicit-def $r0, implicit-def $r1 ; THUMB: tBL 14, $noreg, @tough_arrays_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $r0, implicit $r1, implicit $r2, implicit $r3, implicit-def $r0, implicit-def $r1 -; CHECK: [[R0:%[0-9]+]]:_(s32) = COPY $r0 -; CHECK: [[R1:%[0-9]+]]:_(s32) = COPY $r1 -; CHECK: [[RES_ARR:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[R0]](s32), [[R1]](s32) +; CHECK: [[R0:%[0-9]+]]:_(p0) = COPY $r0 +; CHECK: [[R1:%[0-9]+]]:_(p0) = COPY $r1 ; CHECK: ADJCALLSTACKUP 80, 0, 14, $noreg, implicit-def $sp, implicit $sp -; CHECK: [[EXT1:%[0-9]+]]:_(p0) = G_EXTRACT [[RES_ARR]](s64), 0 -; CHECK: [[EXT2:%[0-9]+]]:_(p0) = G_EXTRACT [[RES_ARR]](s64), 32 -; CHECK: $r0 = COPY [[EXT1]] -; CHECK: $r1 = COPY [[EXT2]] +; CHECK: $r0 = COPY [[R0]] +; CHECK: $r1 = COPY [[R1]] ; ARM: BX_RET 14, $noreg, implicit $r0, implicit $r1 ; THUMB: tBX_RET 14, $noreg, implicit $r0, implicit $r1 entry: @@ -521,12 +506,9 @@ ; THUMB: tBL 14, $noreg, @structs_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $r0, implicit $r1, implicit-def $r0, implicit-def $r1 ; CHECK: [[R0:%[0-9]+]]:_(s32) = COPY $r0 ; CHECK: [[R1:%[0-9]+]]:_(s32) = COPY $r1 -; CHECK: [[R:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[R0]](s32), [[R1]](s32) ; CHECK: ADJCALLSTACKUP 0, 0, 14, $noreg, implicit-def $sp, implicit $sp -; CHECK: [[EXT3:%[0-9]+]]:_(s32) = G_EXTRACT [[R]](s64), 0 -; CHECK: [[EXT4:%[0-9]+]]:_(s32) = G_EXTRACT [[R]](s64), 32 -; CHECK: $r0 = COPY [[EXT3]](s32) -; CHECK: $r1 = COPY [[EXT4]](s32) +; CHECK: $r0 = COPY [[R0]](s32) +; CHECK: $r1 = COPY [[R1]](s32) ; ARM: BX_RET 14, $noreg, implicit $r0, implicit $r1 ; THUMB: tBX_RET 14, $noreg, implicit $r0, implicit $r1 %r = notail call arm_aapcscc {i32, i32} @structs_target({i32, i32} %x)