diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -7232,20 +7232,24 @@ unsigned Offset = 0; HandleRegLoc(VA.getLocReg(), Offset); Offset += PtrByteSize; - for (; Offset != StackSize; Offset += PtrByteSize) { - assert(I != End && - "Expecting enough RegLocs to copy entire ByVal arg."); - - if (!ArgLocs[I].isRegLoc()) - report_fatal_error("Passing ByVals split between registers and stack " - "not yet implemented."); - + for (; Offset != StackSize && ArgLocs[I].isRegLoc(); + Offset += PtrByteSize) { assert(ArgLocs[I].getValNo() == VA.getValNo() && - "Expecting more RegLocs for ByVal argument."); + "RegLocs should be for ByVal argument."); const CCValAssign RL = ArgLocs[I++]; HandleRegLoc(RL.getLocReg(), Offset); } + + if (Offset != StackSize) { + assert(ArgLocs[I].getValNo() == VA.getValNo() && + "Expected MemLoc for remaining bytes."); + assert(ArgLocs[I].isMemLoc() && "Expected MemLoc for remaining bytes."); + // Consume the MemLoc.The InVal has already been emitted, so nothing + // more needs to be done. + ++I; + } + continue; } diff --git a/llvm/test/CodeGen/PowerPC/aix-cc-byval-limitation1.ll b/llvm/test/CodeGen/PowerPC/aix-cc-byval-limitation1.ll deleted file mode 100644 --- a/llvm/test/CodeGen/PowerPC/aix-cc-byval-limitation1.ll +++ /dev/null @@ -1,11 +0,0 @@ -; RUN: not --crash llc -mtriple powerpc-ibm-aix-xcoff < %s 2>&1 | FileCheck %s -; RUN: not --crash llc -mtriple powerpc64-ibm-aix-xcoff < %s 2>&1 | FileCheck %s - -%struct.S = type { [65 x i8] } - -define void @foo(%struct.S* byval(%struct.S) align 1 %s) { -entry: - ret void -} - -; CHECK: LLVM ERROR: Passing ByVals split between registers and stack not yet implemented. diff --git a/llvm/test/CodeGen/PowerPC/aix-cc-byval-mem.ll b/llvm/test/CodeGen/PowerPC/aix-cc-byval-mem.ll --- a/llvm/test/CodeGen/PowerPC/aix-cc-byval-mem.ll +++ b/llvm/test/CodeGen/PowerPC/aix-cc-byval-mem.ll @@ -176,8 +176,6 @@ ret void } -declare void @test_byval_mem3(i32, float, %struct_S57* byval(%struct_S57) align 1) - ; CHECK-LABEL: name: call_test_byval_mem3 ; Confirm the expected memcpy call is independent of the call to test_byval_mem3. @@ -236,6 +234,53 @@ ; ASM64BIT: bl .test_byval_mem3 ; ASM64BIT: addi 1, 1, 128 +define void @test_byval_mem3(i32, float, %struct_S57* byval(%struct_S57) align 1 %s) { +entry: + ret void +} + + +;CHECK-LABEL: name: test_byval_mem3 + +; 32BIT: fixedStack: +; 32BIT-NEXT: - { id: 0, type: default, offset: 32, size: 60, alignment: 16, stack-id: default, + +; 32BIT: bb.0.entry: +; 32BIT-NEXT: liveins: $r5, $r6, $r7, $r8, $r9, $r10 + +; 32BIT-DAG: %2:gprc = COPY $r5 +; 32BIT-DAG: %3:gprc = COPY $r6 +; 32BIT-DAG: %4:gprc = COPY $r7 +; 32BIT-DAG: %5:gprc = COPY $r8 +; 32BIT-DAG: %6:gprc = COPY $r9 +; 32BIT-DAG: %7:gprc = COPY $r10 +; 32BIT-NEXT: STW %2, 0, %fixed-stack.0 :: (store 4 into %fixed-stack.0 +; 32BIT-DAG: STW %3, 4, %fixed-stack.0 :: (store 4 into %fixed-stack.0 + 4 +; 32BIT-DAG: STW %4, 8, %fixed-stack.0 :: (store 4 into %fixed-stack.0 + 8 +; 32BIT-DAG: STW %5, 12, %fixed-stack.0 :: (store 4 into %fixed-stack.0 + 12 +; 32BIT-DAG: STW %6, 16, %fixed-stack.0 :: (store 4 into %fixed-stack.0 + 16 +; 32BIT-DAG: STW %7, 20, %fixed-stack.0 :: (store 4 into %fixed-stack.0 + 20 +; 32BIT-NEXT: BLR implicit $lr, implicit $rm + +; 64BIT: fixedStack: +; 64BIT-NEXT: - { id: 0, type: default, offset: 64, size: 64, alignment: 16, stack-id: default, + +; 64BIT: bb.0.entry +; 64BIT-NEXT: liveins: $x5, $x6, $x7, $x8, $x9, $x10 + +; 64BIT-DAG: %2:g8rc = COPY $x5 +; 64BIT-DAG: %3:g8rc = COPY $x6 +; 64BIT-DAG: %4:g8rc = COPY $x7 +; 64BIT-DAG: %5:g8rc = COPY $x8 +; 64BIT-DAG: %6:g8rc = COPY $x9 +; 64BIT-DAG: %7:g8rc = COPY $x10 +; 64BIT-NEXT: STD %2, 0, %fixed-stack.0 :: (store 8 into %fixed-stack.0, align 16) +; 64BIT-DAG: STD %3, 8, %fixed-stack.0 :: (store 8 into %fixed-stack.0 + 8) +; 64BIT-DAG: STD %4, 16, %fixed-stack.0 :: (store 8 into %fixed-stack.0 + 16, align 16) +; 64BIT-DAG: STD %5, 24, %fixed-stack.0 :: (store 8 into %fixed-stack.0 + 24) +; 64BIT-DAG: STD %6, 32, %fixed-stack.0 :: (store 8 into %fixed-stack.0 + 32, align 16) +; 64BIT-DAG: STD %7, 40, %fixed-stack.0 :: (store 8 into %fixed-stack.0 + 40) +; 64BIT-NEXT: BLR8 implicit $lr8, implicit $rm %struct_S31 = type { [31 x i8] } @@ -247,7 +292,6 @@ ret void } -declare void @test_byval_mem4(i32, %struct_S31* byval(%struct_S31) align 1, %struct_S256* byval(%struct_S256) align 1) ; CHECK-LABEL: name: call_test_byval_mem4 @@ -340,3 +384,58 @@ ; ASM64BIT-DAG: ld 10, 16([[REG1]]) ; ASM64BIT: bl .test_byval_mem4 ; ASM64BIT: addi 1, 1, 352 + +define void @test_byval_mem4(i32, %struct_S31* byval(%struct_S31) align 1, %struct_S256* byval(%struct_S256) align 1 %s) { +entry: + ret void +} + +; CHECK-LABEL: name: test_byval_mem4 + +; 32BIT: fixedStack: +; 32BIT: - { id: 0, type: default, offset: 60, size: 256, alignment: 4, stack-id: default, +; 32BIT: - { id: 1, type: default, offset: 28, size: 32, alignment: 4, stack-id: default, +; 32BIT: stack: [] + +; 32BIT: bb.0.entry: +; 32BIT-NEXT: liveins: $r4, $r5, $r6, $r7, $r8, $r9, $r10 + +; 32BIT-DAG: %1:gprc = COPY $r4 +; 32BIT-DAG: %2:gprc = COPY $r5 +; 32BIT-DAG: %3:gprc = COPY $r6 +; 32BIT-DAG: %4:gprc = COPY $r7 +; 32BIT-DAG: %5:gprc = COPY $r8 +; 32BIT-DAG: %6:gprc = COPY $r9 +; 32BIT-DAG: %7:gprc = COPY $r10 +; 32BIT-NEXT: STW %1, 0, %fixed-stack.1 :: (store 4 into %fixed-stack.1 +; 32BIT-DAG: STW %2, 4, %fixed-stack.1 :: (store 4 into %fixed-stack.1 + 4 +; 32BIT-DAG: STW %3, 8, %fixed-stack.1 :: (store 4 into %fixed-stack.1 + 8 +; 32BIT-DAG: STW %4, 12, %fixed-stack.1 :: (store 4 into %fixed-stack.1 + 12 +; 32BIT-DAG: STW %5, 16, %fixed-stack.1 :: (store 4 into %fixed-stack.1 + 16 +; 32BIT-DAG: STW %6, 20, %fixed-stack.1 :: (store 4 into %fixed-stack.1 + 20 +; 32BIT-DAG: STW %7, 24, %fixed-stack.1 :: (store 4 into %fixed-stack.1 + 24 +; 32BIT-NEXT: BLR implicit $lr, implicit $rm + +; 64BIT: fixedStack: +; 64BIT: - { id: 0, type: default, offset: 88, size: 256, alignment: 8, stack-id: default, +; 64BIT: - { id: 1, type: default, offset: 56, size: 32, alignment: 8, stack-id: default, +; 64BIT: stack: [] + +; 64BIT: bb.0.entry: +; 64BIT-NEXT: liveins: $x4, $x5, $x6, $x7, $x8, $x9, $x10 + +; 64BIT-DAG: %1:g8rc = COPY $x4 +; 64BIT-DAG: %2:g8rc = COPY $x5 +; 64BIT-DAG: %3:g8rc = COPY $x6 +; 64BIT-DAG: %4:g8rc = COPY $x7 +; 64BIT-DAG: %5:g8rc = COPY $x8 +; 64BIT-DAG: %6:g8rc = COPY $x9 +; 64BIT-DAG: %7:g8rc = COPY $x10 +; 64BIT-NEXT: STD %1, 0, %fixed-stack.1 :: (store 8 into %fixed-stack.1 +; 64BIT-DAG: STD %2, 8, %fixed-stack.1 :: (store 8 into %fixed-stack.1 + 8 +; 64BIT-DAG: STD %3, 16, %fixed-stack.1 :: (store 8 into %fixed-stack.1 + 16 +; 64BIT-DAG: STD %4, 24, %fixed-stack.1 :: (store 8 into %fixed-stack.1 + 24 +; 64BIT-DAG: STD %5, 0, %fixed-stack.0 :: (store 8 into %fixed-stack.0 +; 64BIT-DAG: STD %6, 8, %fixed-stack.0 :: (store 8 into %fixed-stack.0 + 8 +; 64BIT-DAG: STD %7, 16, %fixed-stack.0 :: (store 8 into %fixed-stack.0 + 16 +; 64BIT-NEXT: BLR8 implicit $lr8, implicit $rm diff --git a/llvm/test/CodeGen/PowerPC/aix-cc-byval-split.ll b/llvm/test/CodeGen/PowerPC/aix-cc-byval-split.ll --- a/llvm/test/CodeGen/PowerPC/aix-cc-byval-split.ll +++ b/llvm/test/CodeGen/PowerPC/aix-cc-byval-split.ll @@ -1,10 +1,10 @@ -; RUN: not --crash llc -mtriple powerpc-ibm-aix-xcoff -stop-after=machine-cp \ -; RUN: -mcpu=pwr4 -mattr=-altivec -verify-machineinstrs 2>&1 < %s | FileCheck %s +; RUN: llc -mtriple powerpc-ibm-aix-xcoff -stop-after=machine-cp \ +; RUN: -mcpu=pwr4 -mattr=-altivec -verify-machineinstrs 2>&1 < %s | \ +; RUN: FileCheck --check-prefix=CHECK32 %s -; RUN: not --crash llc -mtriple powerpc64-ibm-aix-xcoff -stop-after=machine-cp \ -; RUN: -mcpu=pwr4 -mattr=-altivec -verify-machineinstrs 2>&1 < %s | FileCheck %s - -; CHECK: LLVM ERROR: Passing ByVals split between registers and stack not yet implemented. +; RUN: llc -mtriple powerpc64-ibm-aix-xcoff -stop-after=machine-cp \ +; RUN: -mcpu=pwr4 -mattr=-altivec -verify-machineinstrs 2>&1 < %s | \ +; RUN: FileCheck --check-prefix=CHECK64 %s %struct.Spill = type { [12 x i64 ] } @GS = external global %struct.Spill, align 4 @@ -18,3 +18,64 @@ %add = add i64 %a, %b ret i64 %add } + +; CHECK32: name: test +; CHECK32: liveins: +; CHECK32: - { reg: '$r3', virtual-reg: '' } +; CHECK32: - { reg: '$r4', virtual-reg: '' } +; CHECK32: - { reg: '$r5', virtual-reg: '' } +; CHECK32: - { reg: '$r6', virtual-reg: '' } +; CHECK32: - { reg: '$r7', virtual-reg: '' } +; CHECK32: - { reg: '$r8', virtual-reg: '' } +; CHECK32: - { reg: '$r9', virtual-reg: '' } +; CHECK32: - { reg: '$r10', virtual-reg: '' } +; CHECK32: fixedStack: +; CHECK32: - { id: 0, type: default, offset: 24, size: 96, alignment: 8, stack-id: default, +; CHECK32: stack: [] + +; CHECK32: bb.0.entry: +; CHECK32-NEXT: liveins: $r3, $r4, $r5, $r6, $r7, $r8, $r9, $r10 + +; CHECK32-DAG: STW killed renamable $r3, 0, %fixed-stack.0 :: (store 4 into %fixed-stack.0 +; CHECK32-DAG: STW killed renamable $r4, 4, %fixed-stack.0 :: (store 4 into %fixed-stack.0 + 4 +; CHECK32-DAG: STW killed renamable $r5, 8, %fixed-stack.0 :: (store 4 into %fixed-stack.0 + 8 +; CHECK32-DAG: STW killed renamable $r6, 12, %fixed-stack.0 :: (store 4 into %fixed-stack.0 + 12 +; CHECK32-DAG: STW renamable $r7, 16, %fixed-stack.0 :: (store 4 into %fixed-stack.0 + 16 +; CHECK32-DAG: STW renamable $r8, 20, %fixed-stack.0 :: (store 4 into %fixed-stack.0 + 20 +; CHECK32-DAG: STW killed renamable $r9, 24, %fixed-stack.0 :: (store 4 into %fixed-stack.0 + 24 +; CHECK32-DAG: STW killed renamable $r10, 28, %fixed-stack.0 :: (store 4 into %fixed-stack.0 + 28 +; CHECK32: renamable $r[[REG1:[0-9]+]] = LWZ 84, %fixed-stack.0 +; CHECK32: renamable $r[[REG2:[0-9]+]] = LWZ 80, %fixed-stack.0 +; CHECK32: renamable $r4 = ADDC killed renamable $r8, killed renamable $r[[REG1]], implicit-def $carry +; CHECK32: renamable $r3 = ADDE killed renamable $r7, killed renamable $r[[REG2]], implicit-def dead $carry, implicit killed $carry +; CHECK32: BLR implicit $lr, implicit $rm, implicit $r3, implicit $r4 + + +; CHECK64: name: test +; CHECK64: liveins: +; CHECK64: - { reg: '$x3', virtual-reg: '' } +; CHECK64: - { reg: '$x4', virtual-reg: '' } +; CHECK64: - { reg: '$x5', virtual-reg: '' } +; CHECK64: - { reg: '$x6', virtual-reg: '' } +; CHECK64: - { reg: '$x7', virtual-reg: '' } +; CHECK64: - { reg: '$x8', virtual-reg: '' } +; CHECK64: - { reg: '$x9', virtual-reg: '' } +; CHECK64: - { reg: '$x10', virtual-reg: '' } +; CHECK64: fixedStack: +; CHECK64: - { id: 0, type: default, offset: 48, size: 96, alignment: 16, stack-id: default, +; CHECK64: stack: [] + +; CHECK64: bb.0.entry: +; CHECK64: liveins: $x3, $x4, $x5, $x6, $x7, $x8, $x9, $x10 + +; CHECK64: STD killed renamable $x3, 0, %fixed-stack.0 :: (store 8 into %fixed-stack.0 +; CHECK64: STD killed renamable $x4, 8, %fixed-stack.0 :: (store 8 into %fixed-stack.0 + 8 +; CHECK64: STD renamable $x5, 16, %fixed-stack.0 :: (store 8 into %fixed-stack.0 + 16 +; CHECK64: STD killed renamable $x6, 24, %fixed-stack.0 :: (store 8 into %fixed-stack.0 + 24 +; CHECK64: STD killed renamable $x7, 32, %fixed-stack.0 :: (store 8 into %fixed-stack.0 + 32 +; CHECK64: STD killed renamable $x8, 40, %fixed-stack.0 :: (store 8 into %fixed-stack.0 + 40 +; CHECK64: STD killed renamable $x9, 48, %fixed-stack.0 :: (store 8 into %fixed-stack.0 + 48 +; CHECK64: STD killed renamable $x10, 56, %fixed-stack.0 :: (store 8 into %fixed-stack.0 + 56 +; CHECK64: renamable $x[[REG1:[0-9]+]] = LD 80, %fixed-stack.0 +; CHECK64: renamable $x3 = ADD8 killed renamable $x5, killed renamable $x[[REG1]] +; CHECK64: BLR8 implicit $lr8, implicit $rm, implicit $x3