[llvm] bee6c23 - [AIX][PowerPC] Implement caller byval arguments in stack memory

Chris Bowler via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 15 14:58:16 PDT 2020


Author: Chris Bowler
Date: 2020-04-15T17:57:31-04:00
New Revision: bee6c234ed28ae7349cb83afa322dfd8394590ee

URL: https://github.com/llvm/llvm-project/commit/bee6c234ed28ae7349cb83afa322dfd8394590ee
DIFF: https://github.com/llvm/llvm-project/commit/bee6c234ed28ae7349cb83afa322dfd8394590ee.diff

LOG: [AIX][PowerPC] Implement caller byval arguments in stack memory

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

Added: 
    llvm/test/CodeGen/PowerPC/aix-cc-byval-mem.ll

Modified: 
    llvm/lib/Target/PowerPC/PPCISelLowering.cpp
    llvm/test/CodeGen/PowerPC/aix-cc-byval-limitation1.ll
    llvm/test/CodeGen/PowerPC/aix-cc-byval-limitation2.ll
    llvm/test/CodeGen/PowerPC/aix-cc-byval-split.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index fd1e23d30340..85e34d7cfe03 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -6936,14 +6936,18 @@ static bool CC_AIX(unsigned ValNo, MVT ValVT, MVT LocVT,
       return false;
     }
 
-    State.AllocateStack(alignTo(ByValSize, PtrByteSize), PtrByteSize);
-
-    for (unsigned I = 0, E = ByValSize; I < E; I += PtrByteSize) {
+    const unsigned StackSize = alignTo(ByValSize, PtrByteSize);
+    unsigned Offset = State.AllocateStack(StackSize, PtrByteSize);
+    for (const unsigned E = Offset + StackSize; Offset < E;
+         Offset += PtrByteSize) {
       if (unsigned Reg = State.AllocateReg(IsPPC64 ? GPR_64 : GPR_32))
         State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, RegVT, LocInfo));
-      else
-        report_fatal_error(
-            "Pass-by-value arguments are only supported in registers.");
+      else {
+        State.addLoc(CCValAssign::getMem(ValNo, MVT::INVALID_SIMPLE_VALUE_TYPE,
+                                         Offset, MVT::INVALID_SIMPLE_VALUE_TYPE,
+                                         LocInfo));
+        break;
+      }
     }
     return false;
   }
@@ -7370,12 +7374,12 @@ SDValue PPCTargetLowering::LowerCall_AIX(
       unsigned LoadOffset = 0;
 
       // Initialize registers, which are fully occupied by the by-val argument.
-      while (I != E && LoadOffset + PtrByteSize <= ByValSize) {
+      while (LoadOffset + PtrByteSize <= ByValSize && ArgLocs[I].isRegLoc()) {
         SDValue Load = GetLoad(PtrVT, LoadOffset);
         MemOpChains.push_back(Load.getValue(1));
         LoadOffset += PtrByteSize;
         const CCValAssign &ByValVA = ArgLocs[I++];
-        assert(ByValVA.isRegLoc() && ByValVA.getValNo() == ValNo &&
+        assert(ByValVA.getValNo() == ValNo &&
                "Unexpected location for pass-by-value argument.");
         RegsToPass.push_back(std::make_pair(ByValVA.getLocReg(), Load));
       }
@@ -7383,15 +7387,32 @@ SDValue PPCTargetLowering::LowerCall_AIX(
       if (LoadOffset == ByValSize)
         continue;
 
-      const unsigned ResidueBytes = ByValSize % PtrByteSize;
-      assert(ResidueBytes != 0 && LoadOffset + PtrByteSize > ByValSize &&
-             "Unexpected register residue for by-value argument.");
+      // There must be one more loc to handle the remainder.
+      assert(ArgLocs[I].getValNo() == ValNo &&
+             "Expected additional location for by-value argument.");
+
+      if (ArgLocs[I].isMemLoc()) {
+        assert(LoadOffset < ByValSize && "Unexpected memloc for by-val arg.");
+        const CCValAssign &ByValVA = ArgLocs[I++];
+        ISD::ArgFlagsTy MemcpyFlags = Flags;
+        // Only memcpy the bytes that don't pass in register.
+        MemcpyFlags.setByValSize(ByValSize - LoadOffset);
+        Chain = CallSeqStart = createMemcpyOutsideCallSeq(
+            (LoadOffset != 0) ? DAG.getObjectPtrOffset(dl, Arg, LoadOffset)
+                              : Arg,
+            DAG.getObjectPtrOffset(dl, StackPtr, ByValVA.getLocMemOffset()),
+            CallSeqStart, MemcpyFlags, DAG, dl);
+        continue;
+      }
 
       // Initialize the final register residue.
       // Any residue that occupies the final by-val arg register must be
       // left-justified on AIX. Loads must be a power-of-2 size and cannot be
       // larger than the ByValSize. For example: a 7 byte by-val arg requires 4,
       // 2 and 1 byte loads.
+      const unsigned ResidueBytes = ByValSize % PtrByteSize;
+      assert(ResidueBytes != 0 && LoadOffset + PtrByteSize > ByValSize &&
+             "Unexpected register residue for by-value argument.");
       SDValue ResidueVal;
       for (unsigned Bytes = 0; Bytes != ResidueBytes;) {
         const unsigned N = PowerOf2Floor(ResidueBytes - Bytes);
@@ -7421,8 +7442,6 @@ SDValue PPCTargetLowering::LowerCall_AIX(
       }
 
       const CCValAssign &ByValVA = ArgLocs[I++];
-      assert(ByValVA.isRegLoc() && ByValVA.getValNo() == ValNo &&
-             "Additional register location expected for by-value argument.");
       RegsToPass.push_back(std::make_pair(ByValVA.getLocReg(), ResidueVal));
       continue;
     }

diff  --git a/llvm/test/CodeGen/PowerPC/aix-cc-byval-limitation1.ll b/llvm/test/CodeGen/PowerPC/aix-cc-byval-limitation1.ll
index d7815e7bf4e1..eca919bee34b 100644
--- a/llvm/test/CodeGen/PowerPC/aix-cc-byval-limitation1.ll
+++ b/llvm/test/CodeGen/PowerPC/aix-cc-byval-limitation1.ll
@@ -3,14 +3,9 @@
 
 %struct.S = type { [65 x i8] }
 
-define void @bar() {
+define void @foo(%struct.S* byval(%struct.S) align 1 %s) {
 entry:
-  %s1 = alloca %struct.S, align 1
-  %agg.tmp = alloca %struct.S, align 1
-  call void @foo(%struct.S* byval(%struct.S) align 1 %agg.tmp)
   ret void
 }
 
-declare void @foo(%struct.S* byval(%struct.S) align 1)
-
-; CHECK: LLVM ERROR: Pass-by-value arguments are only supported in registers.
+; CHECK: LLVM ERROR: Passing ByVals split between registers and stack not yet implemented.

diff  --git a/llvm/test/CodeGen/PowerPC/aix-cc-byval-limitation2.ll b/llvm/test/CodeGen/PowerPC/aix-cc-byval-limitation2.ll
index 37700f251429..e78d5957fce0 100644
--- a/llvm/test/CodeGen/PowerPC/aix-cc-byval-limitation2.ll
+++ b/llvm/test/CodeGen/PowerPC/aix-cc-byval-limitation2.ll
@@ -1,16 +1,11 @@
 ; 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 { [1 x i8] }
+%struct.S = type { i8 }
 
-define void @bar() {
+define void @foo(i32 %i1, i32 %i2, i32 %i3, i32 %i4, i32 %i5, i32 %i6, i32 %i7, i32 %i8, %struct.S* byval(%struct.S) align 1 %s) {
 entry:
-  %s1 = alloca %struct.S, align 1
-  %agg.tmp = alloca %struct.S, align 1
-  call void @foo(i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, %struct.S* byval(%struct.S) align 1 %agg.tmp)
   ret void
 }
 
-declare void @foo(i32, i32, i32, i32, i32, i32, i32, i32, %struct.S* byval(%struct.S) align 1)
-
-; CHECK: LLVM ERROR: Pass-by-value arguments are only supported in registers.
+; CHECK: LLVM ERROR: ByVal arguments passed on stack not implemented yet

diff  --git a/llvm/test/CodeGen/PowerPC/aix-cc-byval-mem.ll b/llvm/test/CodeGen/PowerPC/aix-cc-byval-mem.ll
new file mode 100644
index 000000000000..dd5574438a9d
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/aix-cc-byval-mem.ll
@@ -0,0 +1,297 @@
+; RUN: llc -verify-machineinstrs -stop-before=ppc-vsx-copy \
+; RUN:  -mcpu=pwr4 -mattr=-altivec \
+; RUN:  -mtriple powerpc-ibm-aix-xcoff < %s | \
+; RUN: FileCheck --check-prefixes=CHECK,32BIT %s
+
+; RUN: llc -verify-machineinstrs -mcpu=pwr4 -mattr=-altivec \
+; RUN:  -mtriple powerpc-ibm-aix-xcoff < %s | \
+; RUN: FileCheck --check-prefixes=CHECKASM,ASM32BIT %s
+
+; RUN: llc -verify-machineinstrs -stop-before=ppc-vsx-copy \
+; RUN:  -mcpu=pwr4 -mattr=-altivec \
+; RUN:  -mtriple powerpc64-ibm-aix-xcoff < %s | \
+; RUN: FileCheck --check-prefixes=CHECK,64BIT %s
+
+; RUN: llc -verify-machineinstrs -mcpu=pwr4 -mattr=-altivec \
+; RUN:  -mtriple powerpc64-ibm-aix-xcoff < %s | \
+; RUN: FileCheck --check-prefixes=CHECKASM,ASM64BIT %s
+
+%struct_S1 = type { i8 }
+
+ at gS1 = external global %struct_S1, align 1
+
+define void @call_test_byval_mem1() {
+entry:
+  call void @test_byval_mem1(i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, %struct_S1* byval(%struct_S1) align 1 @gS1)
+  ret void
+}
+
+declare void @test_byval_mem1(i32, i32, i32, i32, i32, i32, i32, i32, %struct_S1* byval(%struct_S1) align 1)
+
+; CHECKASM-LABEL: .call_test_byval_mem1:
+
+; ASM32BIT:       stwu 1, -64(1)
+; ASM32BIT:       lwz [[REG1:[0-9]+]], LC{{[0-9]+}}(2)
+; ASM32BIT:       lbz [[REG2:[0-9]+]], 0([[REG1]])
+; ASM32BIT:       stb [[REG2]], 56(1)
+; ASM32BIT:       bl .test_byval_mem1
+; ASM32BIT:       addi 1, 1, 64
+
+; ASM64BIT:       stdu 1, -128(1)
+; ASM64BIT:       ld [[REG1:[0-9]+]], LC{{[0-9]+}}(2)
+; ASM64BIT:       lbz [[REG2:[0-9]+]], 0([[REG1]])
+; ASM64BIT:       stb [[REG2]], 112(1)
+; ASM64BIT:       bl .test_byval_mem1
+; ASM64BIT:       addi 1, 1, 128
+
+
+%struct_S256 = type { [256 x i8] }
+
+ at gS256 = external global %struct_S256, align 1
+
+define void @call_test_byval_mem2() {
+entry:
+  call void @test_byval_mem2(i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, %struct_S256* byval(%struct_S256) align 1 @gS256)
+  ret void
+}
+
+declare void @test_byval_mem2(i32, i32, i32, i32, i32, i32, i32, i32, %struct_S256* byval(%struct_S256) align 1)
+
+; CHECK-LABEL:    name: call_test_byval_mem2
+
+; Confirm the expected memcpy call is independent of the call to test_byval_mem2.
+; 32BIT:          ADJCALLSTACKDOWN 56, 0, implicit-def dead $r1, implicit $r1
+; 32BIT-NEXT:     %0:gprc = nuw ADDI $r1, 56
+; 32BIT-NEXT:     %1:gprc = LWZtoc @gS256, $r2 :: (load 4 from got)
+; 32BIT-NEXT:     %2:gprc = LI 256
+; 32BIT-DAG:      $r3 = COPY %0
+; 32BIT-DAG:      $r4 = COPY %1
+; 32BIT-DAG:      $r5 = COPY %2
+; 32BIT-NEXT:     BL_NOP <mcsymbol .memcpy>, csr_aix32, implicit-def dead $lr, implicit $rm, implicit $r3, implicit $r4, implicit $r5, implicit $r2, implicit-def $r1, implicit-def $r3
+; 32BIT-NEXT:     ADJCALLSTACKUP 56, 0, implicit-def dead $r1, implicit $r1
+; 32BIT:          ADJCALLSTACKDOWN 312, 0, implicit-def dead $r1, implicit $r1
+; 32BIT-DAG:      $r3 = COPY %{{[0-9]+}}
+; 32BIT-DAG:      $r4 = COPY %{{[0-9]+}}
+; 32BIT-DAG:      $r5 = COPY %{{[0-9]+}}
+; 32BIT-DAG:      $r6 = COPY %{{[0-9]+}}
+; 32BIT-DAG:      $r7 = COPY %{{[0-9]+}}
+; 32BIT-DAG:      $r8 = COPY %{{[0-9]+}}
+; 32BIT-DAG:      $r9 = COPY %{{[0-9]+}}
+; 32BIT-DAG:      $r10 = COPY %{{[0-9]+}}
+; 32BIT-NEXT:     BL_NOP <mcsymbol .test_byval_mem2>, csr_aix32, implicit-def dead $lr, implicit $rm, implicit $r3, implicit $r4, implicit $r5, implicit $r6, implicit $r7, implicit $r8, implicit $r9, implicit $r10, implicit $r2, implicit-def $r1
+; 32BIT-NEXT:     ADJCALLSTACKUP 312, 0, implicit-def dead $r1, implicit $r1
+
+; CHECKASM-LABEL: .call_test_byval_mem2:
+
+; ASM32BIT:       stwu 1, -320(1)
+; ASM32BIT-DAG:   addi 3, 1, 56
+; ASM32BIT-DAG:   lwz 4, LC{{[0-9]+}}(2)
+; ASM32BIT-DAG:   li 5, 256
+; ASM32BIT-NEXT:  bl .memcpy
+; ASM32BIT:       bl .test_byval_mem2
+; ASM32BIT:       addi 1, 1, 320
+
+; Confirm the expected memcpy call is independent of the call to test_byval_mem2.
+; 64BIT:          ADJCALLSTACKDOWN 112, 0, implicit-def dead $r1, implicit $r1
+; 64BIT-NEXT:     %0:g8rc = nuw ADDI8 $x1, 112
+; 64BIT-NEXT:     %1:g8rc = LDtoc @gS256, $x2 :: (load 8 from got)
+; 64BIT-NEXT:     %2:g8rc = LI8 256
+; 64BIT-DAG:      $x3 = COPY %0
+; 64BIT-DAG:      $x4 = COPY %1
+; 64BIT-DAG:      $x5 = COPY %2
+; 64BIT-NEXT:     BL8_NOP <mcsymbol .memcpy>, csr_ppc64, implicit-def dead $lr8, implicit $rm, implicit $x3, implicit $x4, implicit $x5, implicit $x2, implicit-def $r1, implicit-def $x3
+; 64BIT-NEXT:     ADJCALLSTACKUP 112, 0, implicit-def dead $r1, implicit $r1
+; 64BIT:          ADJCALLSTACKDOWN 368, 0, implicit-def dead $r1, implicit $r1
+; 64BIT-DAG:      $x3 = COPY %{{[0-9]+}}
+; 64BIT-DAG:      $x4 = COPY %{{[0-9]+}}
+; 64BIT-DAG:      $x5 = COPY %{{[0-9]+}}
+; 64BIT-DAG:      $x6 = COPY %{{[0-9]+}}
+; 64BIT-DAG:      $x7 = COPY %{{[0-9]+}}
+; 64BIT-DAG:      $x8 = COPY %{{[0-9]+}}
+; 64BIT-DAG:      $x9 = COPY %{{[0-9]+}}
+; 64BIT-DAG:      $x10 = COPY %{{[0-9]+}}
+; 64BIT-NEXT:     BL8_NOP <mcsymbol .test_byval_mem2>, csr_ppc64, implicit-def dead $lr8, implicit $rm, implicit $x3, implicit $x4, implicit $x5, implicit $x6, implicit $x7, implicit $x8, implicit $x9, implicit $x10, implicit $x2, implicit-def $r1
+; 64BIT-NEXT:     ADJCALLSTACKUP 368, 0, implicit-def dead $r1, implicit $r1
+
+; ASM64BIT:       stdu 1, -368(1)
+; ASM64BIT-DAG:   addi 3, 1, 112
+; ASM64BIT-DAG:   ld 4, LC{{[0-9]+}}(2)
+; ASM64BIT-DAG:   li 5, 256
+; ASM64BIT-NEXT:  bl .memcpy
+; ASM64BIT:       bl .test_byval_mem2
+; ASM64BIT:       addi 1, 1, 368
+
+
+%struct_S57 = type { [57 x i8] }
+
+ at gS57 = external global %struct_S57, align 1
+
+define void @call_test_byval_mem3() {
+entry:
+  call void @test_byval_mem3(i32 42, float 0x40091EB860000000, %struct_S57* byval(%struct_S57) align 1 @gS57)
+  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.
+; 32BIT:          ADJCALLSTACKDOWN 56, 0, implicit-def dead $r1, implicit $r1
+; 32BIT-NEXT:     %0:gprc_and_gprc_nor0 = LWZtoc @gS57, $r2 :: (load 4 from got)
+; 32BIT-NEXT:     %1:gprc = nuw ADDI %0, 24
+; 32BIT-NEXT:     %2:gprc = nuw ADDI $r1, 56
+; 32BIT-NEXT:     %3:gprc = LI 33
+; 32BIT-DAG:      $r3 = COPY %2
+; 32BIT-DAG:      $r4 = COPY %1
+; 32BIT-DAG:      $r5 = COPY %3
+; 32BIT-NEXT:     BL_NOP <mcsymbol .memcpy>, csr_aix32, implicit-def dead $lr, implicit $rm, implicit $r3, implicit $r4, implicit $r5, implicit $r2, implicit-def $r1, implicit-def $r3
+; 32BIT-NEXT:     ADJCALLSTACKUP 56, 0, implicit-def dead $r1, implicit $r1
+; 32BIT:          ADJCALLSTACKDOWN 92, 0, implicit-def dead $r1, implicit $r1
+; 32BIT-DAG:      $r3 = COPY %{{[0-9]+}}
+; 32BIT-DAG:      $f1 = COPY %{{[0-9]+}}
+; 32BIT-DAG:      $r5 = COPY %{{[0-9]+}}
+; 32BIT-DAG:      $r6 = COPY %{{[0-9]+}}
+; 32BIT-DAG:      $r7 = COPY %{{[0-9]+}}
+; 32BIT-DAG:      $r8 = COPY %{{[0-9]+}}
+; 32BIT-DAG:      $r9 = COPY %{{[0-9]+}}
+; 32BIT-DAG:      $r10 = COPY %{{[0-9]+}}
+; 32BIT-NEXT:     BL_NOP <mcsymbol .test_byval_mem3>, csr_aix32, implicit-def dead $lr, implicit $rm, implicit $r3, implicit $f1, implicit $r5, implicit $r6, implicit $r7, implicit $r8, implicit $r9, implicit $r10, implicit $r2, implicit-def $r1
+; 32BIT-NEXT:     ADJCALLSTACKUP 92, 0, implicit-def dead $r1, implicit $r1
+
+; CHECKASM-LABEL: .call_test_byval_mem3:
+
+; ASM32BIT:       stwu 1, -96(1)
+; ASM32BIT-DAG:   lwz [[REG:[0-9]+]], LC{{[0-9]+}}(2)
+; ASM32BIT-DAG:   addi 3, 1, 56
+; ASM32BIT-DAG:   addi 4, [[REG]], 24
+; ASM32BIT-DAG:   li 5, 33
+; ASM32BIT-NEXT:  bl .memcpy
+; ASM32BIT-DAG:   lwz 5, 0([[REG]])
+; ASM32BIT-DAG:   lwz 6, 4([[REG]])
+; ASM32BIT-DAG:   lwz 7, 8([[REG]])
+; ASM32BIT-DAG:   lwz 8, 12([[REG]])
+; ASM32BIT-DAG:   lwz 9, 16([[REG]])
+; ASM32BIT-DAG:   lwz 10, 20([[REG]])
+; ASM32BIT:       bl .test_byval_mem3
+; ASM32BIT:       addi 1, 1, 96
+
+; The memcpy call was inlined in 64-bit so MIR test is redundant and omitted.
+; ASM64BIT:       stdu 1, -128(1)
+; ASM64BIT-DAG:   ld [[REG1:[0-9]+]], LC{{[0-9]+}}(2)
+; ASM64BIT-DAG:   ld [[REG2:[0-9]+]], 48([[REG1]])
+; ASM64BIT-DAG:   std [[REG2]], 112(1)
+; ASM64BIT-DAG:   lbz [[REG3:[0-9]+]], 56([[REG1]])
+; ASM64BIT-DAG:   stb [[REG3]], 120(1)
+; ASM64BIT-DAG:   ld 5, 0([[REG1]])
+; ASM64BIT-DAG:   ld 6, 8([[REG1]])
+; ASM64BIT-DAG:   ld 7, 16([[REG1]])
+; ASM64BIT-DAG:   ld 8, 24([[REG1]])
+; ASM64BIT-DAG:   ld 9, 32([[REG1]])
+; ASM64BIT-DAG:   ld 10, 40([[REG1]])
+; ASM64BIT:       bl .test_byval_mem3
+; ASM64BIT:       addi 1, 1, 128
+
+
+%struct_S31 = type { [31 x i8] }
+
+ at gS31 = external global %struct_S31, align 1
+
+define void @call_test_byval_mem4() {
+entry:
+  call void @test_byval_mem4(i32 42, %struct_S31* byval(%struct_S31) align 1 @gS31, %struct_S256* byval(%struct_S256) align 1 @gS256)
+  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
+
+; CHECKASM-LABEL: .call_test_byval_mem4:
+
+; Confirm the expected memcpy call is independent of the call to test_byval_mem4.
+; 32BIT:          ADJCALLSTACKDOWN 56, 0, implicit-def dead $r1, implicit $r1
+; 32BIT-NEXT:     %3:gprc = nuw ADDI $r1, 60
+; 32BIT-NEXT:     %4:gprc = LWZtoc @gS256, $r2 :: (load 4 from got)
+; 32BIT-NEXT:     %5:gprc = LI 256
+; 32BIT-DAG:      $r3 = COPY %3
+; 32BIT-DAG:      $r4 = COPY %4
+; 32BIT-DAG:      $r5 = COPY %5
+; 32BIT-NEXT:     BL_NOP <mcsymbol .memcpy>, csr_aix32, implicit-def dead $lr, implicit $rm, implicit $r3, implicit $r4, implicit $r5, implicit $r2, implicit-def $r1, implicit-def $r3
+; 32BIT-NEXT:     ADJCALLSTACKUP 56, 0, implicit-def dead $r1, implicit $r1
+; 32BIT:          ADJCALLSTACKDOWN 316, 0, implicit-def dead $r1, implicit $r1
+; 32BIT-DAG:      $r3 = COPY %{{[0-9]+}}
+; 32BIT-DAG:      $r4 = COPY %{{[0-9]+}}
+; 32BIT-DAG:      $r5 = COPY %{{[0-9]+}}
+; 32BIT-DAG:      $r6 = COPY %{{[0-9]+}}
+; 32BIT-DAG:      $r7 = COPY %{{[0-9]+}}
+; 32BIT-DAG:      $r8 = COPY %{{[0-9]+}}
+; 32BIT-DAG:      $r9 = COPY %{{[0-9]+}}
+; 32BIT-DAG:      $r10 = COPY %{{[0-9]+}}
+; 32BIT-NEXT:     BL_NOP <mcsymbol .test_byval_mem4>, csr_aix32, implicit-def dead $lr, implicit $rm, implicit $r3, implicit $r4, implicit $r5, implicit $r6, implicit $r7, implicit $r8, implicit $r9, implicit $r10, implicit $r2, implicit-def $r1
+; 32BIT-NEXT:     ADJCALLSTACKUP 316, 0, implicit-def dead $r1, implicit $r1
+
+; ASM32BIT:       stwu 1, -320(1)
+; ASM32BIT-DAG:   lwz [[REG1:[0-9]+]], LC{{[0-9]+}}(2)
+; ASM32BIT-DAG:   lhz [[REG2:[0-9]+]], 28([[REG1]])
+; ASM32BIT-DAG:   sth [[REG2]], 56(1)
+; ASM32BIT-DAG:   lbz [[REG3:[0-9]+]], 30([[REG1]])
+; ASM32BIT-DAG:   stb [[REG3]], 58(1)
+; ASM32BIT-DAG:   addi 3, 1, 60
+; ASM32BIT-DAG:   4, LC{{[0-9]+}}(2)
+; ASM32BIT-DAG:   li 5, 256
+; ASM32BIT-NEXT:  bl .memcpy
+; ASM32BIT-DAG:   lwz 4, 0(13)
+; ASM32BIT-DAG:   lwz 5, 4(13)
+; ASM32BIT-DAG:   lwz 6, 8(13)
+; ASM32BIT-DAG:   lwz 7, 12(13)
+; ASM32BIT-DAG:   lwz 8, 16(13)
+; ASM32BIT-DAG:   lwz 9, 20(13)
+; ASM32BIT-DAG:   lwz 10, 24(13)
+; ASM32BIT:       bl .test_byval_mem4
+; ASM32BIT:       addi 1, 1, 320
+
+; Confirm the expected memcpy call is independent of the call to test_byval_mem4.
+; 64BIT:          ADJCALLSTACKDOWN 112, 0, implicit-def dead $r1, implicit $r1
+; 64BIT-NEXT:     %0:g8rc_and_g8rc_nox0 = LDtoc @gS256, $x2 :: (load 8 from got)
+; 64BIT-NEXT:     %1:g8rc = nuw ADDI8 %0, 24
+; 64BIT-NEXT:     %2:g8rc = nuw ADDI8 $x1, 112
+; 64BIT-NEXT:     %3:g8rc = LI8 232
+; 64BIT-DAG:      $x3 = COPY %2
+; 64BIT-DAG:      $x4 = COPY %1
+; 64BIT-DAG:      $x5 = COPY %3
+; 64BIT-NEXT:     BL8_NOP <mcsymbol .memcpy>, csr_ppc64, implicit-def dead $lr8, implicit $rm, implicit $x3, implicit $x4, implicit $x5, implicit $x2, implicit-def $r1, implicit-def $x3
+; 64BIT-NEXT:     ADJCALLSTACKUP 112, 0, implicit-def dead $r1, implicit $r1
+; 64BIT:          ADJCALLSTACKDOWN 344, 0, implicit-def dead $r1, implicit $r1
+; 64BIT-DAG:      $x3 = COPY %{{[0-9]+}}
+; 64BIT-DAG:      $x4 = COPY %{{[0-9]+}}
+; 64BIT-DAG:      $x5 = COPY %{{[0-9]+}}
+; 64BIT-DAG:      $x6 = COPY %{{[0-9]+}}
+; 64BIT-DAG:      $x7 = COPY %{{[0-9]+}}
+; 64BIT-DAG:      $x8 = COPY %{{[0-9]+}}
+; 64BIT-DAG:      $x9 = COPY %{{[0-9]+}}
+; 64BIT-DAG:      $x10 = COPY %{{[0-9]+}}
+; 64BIT-NEXT:     BL8_NOP <mcsymbol .test_byval_mem4>, csr_ppc64, implicit-def dead $lr8, implicit $rm, implicit $x3, implicit $x4, implicit $x5, implicit $x6, implicit $x7, implicit $x8, implicit $x9, implicit $x10, implicit $x2, implicit-def $r1
+; 64BIT-NEXT:     ADJCALLSTACKUP 344, 0, implicit-def dead $r1, implicit $r1
+
+; ASM64BIT:       stdu 1, -352(1)
+; ASM64BIT-DAG:   ld [[REG1:[0-9]+]], LC{{[0-9]+}}(2)
+; ASM64BIT-DAG:   addi 3, 1, 112
+; ASM64BIT-DAG:   addi 4, [[REG1]], 24
+; ASM64BIT-DAG:   li 5, 232
+; ASM64BIT-NEXT:  bl .memcpy
+; ASM64BIT-DAG:   ld [[REG2:[0-9]+]], LC{{[0-9]+}}(2)
+; ASM64BIT-DAG:   ld 4, 0([[REG2]])
+; ASM64BIT-DAG:   ld 5, 8([[REG2]])
+; ASM64BIT-DAG:   ld 6, 16([[REG2]])
+; ASM64BIT-DAG:   lwz [[REG3:[0-9]+]], 24([[REG2]])
+; ASM64BIT-DAG:   lhz [[REG4:[0-9]+]], 28([[REG2]])
+; ASM64BIT-DAG:   lbz 7, 30([[REG2]])
+; ASM64BIT-DAG:   rlwinm 7, 7, 8, 16, 23
+; ASM64BIT-DAG:   rlwimi 7, [[REG4]], 16, 0, 15
+; ASM64BIT-DAG:   rldimi 7, [[REG3]], 32, 0
+; ASM64BIT-DAG:   ld 8, 0([[REG1]])
+; ASM64BIT-DAG:   ld 9, 8([[REG1]])
+; ASM64BIT-DAG:   ld 10, 16([[REG1]])
+; ASM64BIT:       bl .test_byval_mem4
+; ASM64BIT:       addi 1, 1, 352

diff  --git a/llvm/test/CodeGen/PowerPC/aix-cc-byval-split.ll b/llvm/test/CodeGen/PowerPC/aix-cc-byval-split.ll
index 9117e3f288f1..535998af9190 100644
--- a/llvm/test/CodeGen/PowerPC/aix-cc-byval-split.ll
+++ b/llvm/test/CodeGen/PowerPC/aix-cc-byval-split.ll
@@ -4,7 +4,7 @@
 ; 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: Pass-by-value arguments are only supported in registers.
+; CHECK: LLVM ERROR: Passing ByVals split between registers and stack not yet implemented.
 
 %struct.Spill = type { [12 x i64 ] }
 @GS = external global %struct.Spill, align 4


        


More information about the llvm-commits mailing list