Index: llvm/trunk/lib/Target/X86/X86CallLowering.h =================================================================== --- llvm/trunk/lib/Target/X86/X86CallLowering.h +++ llvm/trunk/lib/Target/X86/X86CallLowering.h @@ -34,14 +34,15 @@ bool lowerFormalArguments(MachineIRBuilder &MIRBuilder, const Function &F, ArrayRef VRegs) const override; + private: /// A function of this type is used to perform value split action. - typedef std::function SplitArgTy; + typedef std::function)> SplitArgTy; void splitToValueTypes(const ArgInfo &OrigArgInfo, SmallVectorImpl &SplitArgs, const DataLayout &DL, MachineRegisterInfo &MRI, SplitArgTy SplitArg) const; }; -} // End of namespace llvm; +} // namespace llvm #endif Index: llvm/trunk/lib/Target/X86/X86CallLowering.cpp =================================================================== --- llvm/trunk/lib/Target/X86/X86CallLowering.cpp +++ llvm/trunk/lib/Target/X86/X86CallLowering.cpp @@ -53,7 +53,6 @@ return; } - SmallVector BitOffsets; SmallVector SplitRegs; EVT PartVT = TLI.getRegisterType(Context, VT); @@ -64,8 +63,10 @@ ArgInfo{MRI.createGenericVirtualRegister(getLLTForType(*PartTy, DL)), PartTy, OrigArg.Flags}; SplitArgs.push_back(Info); - PerformArgSplit(Info.Reg, PartVT.getSizeInBits() * i); + SplitRegs.push_back(Info.Reg); } + + PerformArgSplit(SplitRegs); } namespace { @@ -112,10 +113,9 @@ setArgFlags(OrigArg, AttributeList::ReturnIndex, DL, F); SmallVector SplitArgs; - splitToValueTypes(OrigArg, SplitArgs, DL, MRI, - [&](unsigned Reg, uint64_t Offset) { - MIRBuilder.buildExtract(Reg, VReg, Offset); - }); + splitToValueTypes( + OrigArg, SplitArgs, DL, MRI, + [&](ArrayRef Regs) { MIRBuilder.buildUnmerge(Regs, VReg); }); FuncReturnHandler Handler(MIRBuilder, MRI, MIB, RetCC_X86); if (!handleAssignments(MIRBuilder, SplitArgs, Handler)) @@ -183,22 +183,10 @@ for (auto &Arg : F.args()) { ArgInfo OrigArg(VRegs[Idx], Arg.getType()); setArgFlags(OrigArg, Idx + 1, DL, F); - LLT Ty = MRI.getType(VRegs[Idx]); - unsigned Dst = VRegs[Idx]; - bool Split = false; splitToValueTypes(OrigArg, SplitArgs, DL, MRI, - [&](unsigned Reg, uint64_t Offset) { - if (!Split) { - Split = true; - Dst = MRI.createGenericVirtualRegister(Ty); - MIRBuilder.buildUndef(Dst); - } - unsigned Tmp = MRI.createGenericVirtualRegister(Ty); - MIRBuilder.buildInsert(Tmp, Dst, Reg, Offset); - Dst = Tmp; + [&](ArrayRef Regs) { + MIRBuilder.buildMerge(VRegs[Idx], Regs); }); - if (Dst != VRegs[Idx]) - MIRBuilder.buildCopy(VRegs[Idx], Dst); Idx++; } Index: llvm/trunk/test/CodeGen/X86/GlobalISel/callingconv.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/GlobalISel/callingconv.ll +++ llvm/trunk/test/CodeGen/X86/GlobalISel/callingconv.ll @@ -0,0 +1,133 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=i386-linux-gnu -mattr=+sse2 -global-isel < %s -o - | FileCheck %s --check-prefix=ALL --check-prefix=X32 --check-prefix=X32_GISEL +; RUN: llc -mtriple=i386-linux-gnu -mattr=+sse2 < %s -o - | FileCheck %s --check-prefix=ALL --check-prefix=X32 --check-prefix=X32_ISEL +; RUN: llc -mtriple=x86_64-linux-gnu -global-isel < %s -o - | FileCheck %s --check-prefix=ALL --check-prefix=X64 --check-prefix=X64_GISEL +; RUN: llc -mtriple=x86_64-linux-gnu < %s -o - | FileCheck %s --check-prefix=ALL --check-prefix=X64 --check-prefix=X64_ISEL + +define i32 @test_ret_i32() { +; X32-LABEL: test_ret_i32: +; X32: # BB#0: +; X32-NEXT: movl $20, %eax +; X32-NEXT: retl +; +; X64-LABEL: test_ret_i32: +; X64: # BB#0: +; X64-NEXT: movl $20, %eax +; X64-NEXT: retq + ret i32 20 +} + +define i64 @test_ret_i64() { +; X32_GISEL-LABEL: test_ret_i64: +; X32_GISEL: # BB#0: +; X32_GISEL-NEXT: movl $4294967295, %eax # imm = 0xFFFFFFFF +; X32_GISEL-NEXT: movl $15, %edx +; X32_GISEL-NEXT: retl +; +; X32_ISEL-LABEL: test_ret_i64: +; X32_ISEL: # BB#0: +; X32_ISEL-NEXT: movl $-1, %eax +; X32_ISEL-NEXT: movl $15, %edx +; X32_ISEL-NEXT: retl +; +; X64-LABEL: test_ret_i64: +; X64: # BB#0: +; X64-NEXT: movabsq $68719476735, %rax # imm = 0xFFFFFFFFF +; X64-NEXT: retq + ret i64 68719476735 +} + +define i32 @test_arg_i32(i32 %a) { +; X32_GISEL-LABEL: test_arg_i32: +; X32_GISEL: # BB#0: +; X32_GISEL-NEXT: leal 4(%esp), %eax +; X32_GISEL-NEXT: movl (%eax), %eax +; X32_GISEL-NEXT: retl +; +; X32_ISEL-LABEL: test_arg_i32: +; X32_ISEL: # BB#0: +; X32_ISEL-NEXT: movl 4(%esp), %eax +; X32_ISEL-NEXT: retl +; +; X64-LABEL: test_arg_i32: +; X64: # BB#0: +; X64-NEXT: movl %edi, %eax +; X64-NEXT: retq + ret i32 %a +} + +define i64 @test_arg_i64(i64 %a) { +; X32_GISEL-LABEL: test_arg_i64: +; X32_GISEL: # BB#0: +; X32_GISEL-NEXT: leal 4(%esp), %eax +; X32_GISEL-NEXT: movl (%eax), %eax +; X32_GISEL-NEXT: leal 8(%esp), %ecx +; X32_GISEL-NEXT: movl (%ecx), %edx +; X32_GISEL-NEXT: retl +; +; X32_ISEL-LABEL: test_arg_i64: +; X32_ISEL: # BB#0: +; X32_ISEL-NEXT: movl 4(%esp), %eax +; X32_ISEL-NEXT: movl 8(%esp), %edx +; X32_ISEL-NEXT: retl +; +; X64-LABEL: test_arg_i64: +; X64: # BB#0: +; X64-NEXT: movq %rdi, %rax +; X64-NEXT: retq + ret i64 %a +} + +define i64 @test_i64_args_8(i64 %arg1, i64 %arg2, i64 %arg3, i64 %arg4, i64 %arg5, i64 %arg6, i64 %arg7, i64 %arg8) { +; X32_GISEL-LABEL: test_i64_args_8: +; X32_GISEL: # BB#0: +; X32_GISEL-NEXT: leal 60(%esp), %eax +; X32_GISEL-NEXT: movl (%eax), %eax +; X32_GISEL-NEXT: leal 64(%esp), %ecx +; X32_GISEL-NEXT: movl (%ecx), %edx +; X32_GISEL-NEXT: retl +; +; X32_ISEL-LABEL: test_i64_args_8: +; X32_ISEL: # BB#0: +; X32_ISEL-NEXT: movl 60(%esp), %eax +; X32_ISEL-NEXT: movl 64(%esp), %edx +; X32_ISEL-NEXT: retl +; +; X64_GISEL-LABEL: test_i64_args_8: +; X64_GISEL: # BB#0: +; X64_GISEL-NEXT: leaq 16(%rsp), %rax +; X64_GISEL-NEXT: movq (%rax), %rax +; X64_GISEL-NEXT: retq +; +; X64_ISEL-LABEL: test_i64_args_8: +; X64_ISEL: # BB#0: +; X64_ISEL-NEXT: movq 16(%rsp), %rax +; X64_ISEL-NEXT: retq + + ret i64 %arg8 +} + +define <4 x i32> @test_v4i32_args(<4 x i32> %arg1, <4 x i32> %arg2) { +; X32-LABEL: test_v4i32_args: +; X32: # BB#0: +; X32-NEXT: movaps %xmm1, %xmm0 +; X32-NEXT: retl +; +; X64-LABEL: test_v4i32_args: +; X64: # BB#0: +; X64-NEXT: movaps %xmm1, %xmm0 +; X64-NEXT: retq + ret <4 x i32> %arg2 +} + +define <8 x i32> @test_v8i32_args(<8 x i32> %arg1) { +; X32-LABEL: test_v8i32_args: +; X32: # BB#0: +; X32-NEXT: retl +; +; X64-LABEL: test_v8i32_args: +; X64: # BB#0: +; X64-NEXT: retq + + ret <8 x i32> %arg1 +} Index: llvm/trunk/test/CodeGen/X86/GlobalISel/irtranslator-callingconv.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/GlobalISel/irtranslator-callingconv.ll +++ llvm/trunk/test/CodeGen/X86/GlobalISel/irtranslator-callingconv.ll @@ -207,24 +207,15 @@ ; X32-NEXT: [[ARG8H_ADDR:%[0-9]+]](p0) = G_FRAME_INDEX %fixed-stack.[[STACK60]] ; X32-NEXT: [[ARG8H:%[0-9]+]](s32) = G_LOAD [[ARG8H_ADDR]](p0) :: (invariant load 4 from %fixed-stack.[[STACK60]], align 0) -; X32-NEXT: [[UNDEF:%[0-9]+]](s64) = IMPLICIT_DEF -; X32-NEXT: [[ARG1_TMP0:%[0-9]+]](s64) = G_INSERT [[UNDEF]], [[ARG1L]](s32), 0 -; X32-NEXT: [[ARG1_TMP1:%[0-9]+]](s64) = G_INSERT [[ARG1_TMP0]], [[ARG1H]](s32), 32 -; X32-NEXT: [[ARG1:%[0-9]+]](s64) = COPY [[ARG1_TMP1]] - ; ... a bunch more that we don't track ... - ; X32: IMPLICIT_DEF - ; X32: IMPLICIT_DEF - ; X32: IMPLICIT_DEF - ; X32: IMPLICIT_DEF - ; X32: IMPLICIT_DEF -; X32: [[UNDEF:%[0-9]+]](s64) = IMPLICIT_DEF -; X32-NEXT: [[ARG7_TMP0:%[0-9]+]](s64) = G_INSERT [[UNDEF]], [[ARG7L]](s32), 0 -; X32-NEXT: [[ARG7_TMP1:%[0-9]+]](s64) = G_INSERT [[ARG7_TMP0]], [[ARG7H]](s32), 32 -; X32-NEXT: [[ARG7:%[0-9]+]](s64) = COPY [[ARG7_TMP1]] -; X32-NEXT: [[UNDEF:%[0-9]+]](s64) = IMPLICIT_DEF -; X32-NEXT: [[ARG8_TMP0:%[0-9]+]](s64) = G_INSERT [[UNDEF]], [[ARG8L]](s32), 0 -; X32-NEXT: [[ARG8_TMP1:%[0-9]+]](s64) = G_INSERT [[ARG8_TMP0]], [[ARG8H]](s32), 32 -; X32-NEXT: [[ARG8:%[0-9]+]](s64) = COPY [[ARG8_TMP1]] +; X32-NEXT: [[ARG1:%[0-9]+]](s64) = G_MERGE_VALUES [[ARG1L]](s32), [[ARG1H]](s32) +; ... a bunch more that we don't track ... +; X32-NEXT: G_MERGE_VALUES +; X32-NEXT: G_MERGE_VALUES +; X32-NEXT: G_MERGE_VALUES +; X32-NEXT: G_MERGE_VALUES +; X32-NEXT: G_MERGE_VALUES +; X32-NEXT: [[ARG7:%[0-9]+]](s64) = G_MERGE_VALUES [[ARG7L]](s32), [[ARG7H]](s32) +; X32-NEXT: [[ARG8:%[0-9]+]](s64) = G_MERGE_VALUES [[ARG8L]](s32), [[ARG8H]](s32) ; ALL-NEXT: [[GADDR_A1:%[0-9]+]](p0) = G_GLOBAL_VALUE @a1_64bit ; ALL-NEXT: [[GADDR_A7:%[0-9]+]](p0) = G_GLOBAL_VALUE @a7_64bit @@ -236,8 +227,7 @@ ; X64-NEXT: %rax = COPY [[ARG1]](s64) ; X64-NEXT: RET 0, implicit %rax -; X32-NEXT: [[RETL:%[0-9]+]](s32) = G_EXTRACT [[ARG1:%[0-9]+]](s64), 0 -; X32-NEXT: [[RETH:%[0-9]+]](s32) = G_EXTRACT [[ARG1:%[0-9]+]](s64), 32 +; X32-NEXT: [[RETL:%[0-9]+]](s32), [[RETH:%[0-9]+]](s32) = G_UNMERGE_VALUES [[ARG1:%[0-9]+]](s64) ; X32-NEXT: %eax = COPY [[RETL:%[0-9]+]](s32) ; X32-NEXT: %edx = COPY [[RETH:%[0-9]+]](s32) ; X32-NEXT: RET 0, implicit %eax, implicit %edx Index: llvm/trunk/test/CodeGen/X86/GlobalISel/irtranslator-callingconv_64bit.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/GlobalISel/irtranslator-callingconv_64bit.ll +++ llvm/trunk/test/CodeGen/X86/GlobalISel/irtranslator-callingconv_64bit.ll @@ -15,12 +15,8 @@ ; X64: liveins: %xmm0, %xmm1 ; X64: [[ARG1L:%[0-9]+]](<4 x s32>) = COPY %xmm0 ; X64-NEXT: [[ARG1H:%[0-9]+]](<4 x s32>) = COPY %xmm1 -; X64-NEXT: [[UNDEF:%[0-9]+]](<8 x s32>) = IMPLICIT_DEF -; X64-NEXT: [[ARG1_TMP0:%[0-9]+]](<8 x s32>) = G_INSERT [[UNDEF]], [[ARG1L]](<4 x s32>), 0 -; X64-NEXT: [[ARG1_TMP1:%[0-9]+]](<8 x s32>) = G_INSERT [[ARG1_TMP0]], [[ARG1H]](<4 x s32>), 128 -; X64-NEXT: [[ARG1:%[0-9]+]](<8 x s32>) = COPY [[ARG1_TMP1]] -; X64-NEXT: [[RETL:%[0-9]+]](<4 x s32>) = G_EXTRACT [[ARG1:%[0-9]+]](<8 x s32>), 0 -; X64-NEXT: [[RETH:%[0-9]+]](<4 x s32>) = G_EXTRACT [[ARG1:%[0-9]+]](<8 x s32>), 128 +; X64-NEXT: [[ARG1:%[0-9]+]](<8 x s32>) = G_MERGE_VALUES [[ARG1L]](<4 x s32>), [[ARG1H]](<4 x s32>) +; X64-NEXT: [[RETL:%[0-9]+]](<4 x s32>), [[RETH:%[0-9]+]](<4 x s32>) = G_UNMERGE_VALUES [[ARG1:%[0-9]+]](<8 x s32>) ; X64-NEXT: %xmm0 = COPY [[RETL:%[0-9]+]](<4 x s32>) ; X64-NEXT: %xmm1 = COPY [[RETH:%[0-9]+]](<4 x s32>) ; X64-NEXT: RET 0, implicit %xmm0, implicit %xmm1