[PowerPC][AIX] Pass ByVal formal args that span registers and stack.
authorSean Fertile <sd.fertile@gmail.com>
Wed, 15 Apr 2020 13:58:22 +0000 (09:58 -0400)
committerSean Fertile <sd.fertile@gmail.com>
Tue, 28 Apr 2020 18:57:14 +0000 (14:57 -0400)
Implement passing of ByVal formal arguments when the argument is passed
partly in the argument registers, with the remainder of the argument
passed on the stack.

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

llvm/lib/Target/PowerPC/PPCISelLowering.cpp
llvm/test/CodeGen/PowerPC/aix-cc-byval-limitation1.ll [deleted file]
llvm/test/CodeGen/PowerPC/aix-cc-byval-mem.ll
llvm/test/CodeGen/PowerPC/aix-cc-byval-split.ll

index 69dca9b..ac2483c 100644 (file)
@@ -7232,20 +7232,24 @@ SDValue PPCTargetLowering::LowerFormalArguments_AIX(
       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 (file)
index eca919b..0000000
+++ /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.
index a87a589..3f24a43 100644 (file)
@@ -176,8 +176,6 @@ entry:
   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 @@ declare void @test_byval_mem3(i32, float, %struct_S57* byval(%struct_S57) align
 ; 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 @@ entry:
   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 @@ declare void @test_byval_mem4(i32, %struct_S31* byval(%struct_S31) align 1, %str
 ; 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
index 535998a..e9155f2 100644 (file)
@@ -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 @@ entry:
   %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