[llvm] r362708 - [AIX] Implement call lowering with parameters could pass onto GPRs

Jason Liu via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 6 07:36:43 PDT 2019


Author: jasonliu
Date: Thu Jun  6 07:36:43 2019
New Revision: 362708

URL: http://llvm.org/viewvc/llvm-project?rev=362708&view=rev
Log:
[AIX] Implement call lowering with parameters could pass onto GPRs

Summary:
This patch implements SDAG call lowering on AIX for functions
which only have parameters that could fit into GPRs.

Reviewers: hubert.reinterpretcast, syzaara

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

Added:
    llvm/trunk/test/CodeGen/PowerPC/aix_gpr_param.ll
Modified:
    llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp
    llvm/trunk/lib/Target/PowerPC/PPCRegisterInfo.cpp
    llvm/trunk/test/CodeGen/PowerPC/test_call_aix.ll

Modified: llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp?rev=362708&r1=362707&r2=362708&view=diff
==============================================================================
--- llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp Thu Jun  6 07:36:43 2019
@@ -4871,6 +4871,7 @@ PrepareCall(SelectionDAG &DAG, SDValue &
   bool isPPC64 = Subtarget.isPPC64();
   bool isSVR4ABI = Subtarget.isSVR4ABI();
   bool isELFv2ABI = Subtarget.isELFv2ABI();
+  bool isAIXABI = Subtarget.isAIXABI();
 
   EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(DAG.getDataLayout());
   NodeTys.push_back(MVT::Other);   // Returns a chain
@@ -5049,17 +5050,18 @@ PrepareCall(SelectionDAG &DAG, SDValue &
     Ops.push_back(DAG.getRegister(RegsToPass[i].first,
                                   RegsToPass[i].second.getValueType()));
 
-  // All calls, in both the ELF V1 and V2 ABIs, need the TOC register live
-  // into the call.
-  // We do need to reserve X2 to appease the verifier for the PATCHPOINT.
-  if (isSVR4ABI && isPPC64) {
+  // All calls, in the AIX ABI and 64-bit ELF ABIs, need the TOC register
+  // live into the call.
+  // We do need to reserve R2/X2 to appease the verifier for the PATCHPOINT.
+  if ((isSVR4ABI && isPPC64) || isAIXABI) {
     setUsesTOCBasePtr(DAG);
 
-    // We cannot add X2 as an operand here for PATCHPOINT, because there is no
-    // way to mark dependencies as implicit here. We will add the X2 dependency
-    // in EmitInstrWithCustomInserter.
+    // We cannot add R2/X2 as an operand here for PATCHPOINT, because there is
+    // no way to mark dependencies as implicit here.
+    // We will add the R2/X2 dependency in EmitInstrWithCustomInserter.
     if (!isPatchPoint) 
-      Ops.push_back(DAG.getRegister(PPC::X2, PtrVT));
+      Ops.push_back(DAG.getRegister(isPPC64 ? PPC::X2
+                                            : PPC::R2, PtrVT));
   }
 
   return CallOpc;
@@ -6596,9 +6598,6 @@ SDValue PPCTargetLowering::LowerCall_AIX
   unsigned PtrByteSize = isPPC64 ? 8 : 4;
   unsigned NumOps = Outs.size();
 
-  if (NumOps != 0)
-    report_fatal_error("Call lowering with parameters is not implemented "
-                       "on AIX yet.");
 
   // Count how many bytes are to be pushed on the stack, including the linkage
   // area, parameter list area.
@@ -6620,17 +6619,81 @@ SDValue PPCTargetLowering::LowerCall_AIX
   Chain = DAG.getCALLSEQ_START(Chain, NumBytes, 0, dl);
   SDValue CallSeqStart = Chain;
 
-  if (!isFunctionGlobalAddress(Callee) &&
-      !isa<ExternalSymbolSDNode>(Callee))
-    report_fatal_error("Handling of indirect call is unimplemented!");
+  static const MCPhysReg GPR_32[] = {           // 32-bit registers.
+    PPC::R3, PPC::R4, PPC::R5, PPC::R6,
+    PPC::R7, PPC::R8, PPC::R9, PPC::R10
+  };
+  static const MCPhysReg GPR_64[] = {           // 64-bit registers.
+    PPC::X3, PPC::X4, PPC::X5, PPC::X6,
+    PPC::X7, PPC::X8, PPC::X9, PPC::X10
+  };
+
+  const unsigned NumGPRs = isPPC64 ? array_lengthof(GPR_64)
+                                   : array_lengthof(GPR_32);
+  const MCPhysReg *GPR = isPPC64 ? GPR_64 : GPR_32;
+  unsigned GPR_idx = 0;
 
   SmallVector<std::pair<unsigned, SDValue>, 8> RegsToPass;
-  SDValue InFlag;
 
   if (isTailCall)
     report_fatal_error("Handling of tail call is unimplemented!");
   int SPDiff = 0;
 
+  for (unsigned i = 0; i != NumOps; ++i) {
+    SDValue Arg = OutVals[i];
+    ISD::ArgFlagsTy Flags = Outs[i].Flags;
+
+    // Promote integers if needed.
+    if (Arg.getValueType() == MVT::i1 ||
+        (isPPC64 && Arg.getValueType() == MVT::i32)) {
+      unsigned ExtOp = Flags.isSExt() ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND;
+      Arg = DAG.getNode(ExtOp, dl, PtrVT, Arg);
+    }
+
+    // Note: "by value" is code for passing a structure by value, not
+    // basic types.
+    if (Flags.isByVal())
+      report_fatal_error("Passing structure by value is unimplemented!");
+
+    switch (Arg.getSimpleValueType().SimpleTy) {
+    default: llvm_unreachable("Unexpected ValueType for argument!");
+    case MVT::i1:
+    case MVT::i32:
+    case MVT::i64:
+      if (GPR_idx != NumGPRs)
+        RegsToPass.push_back(std::make_pair(GPR[GPR_idx++], Arg));
+      else
+        report_fatal_error("Handling of placing parameters on the stack is "
+                           "unimplemented!");
+      break;
+    case MVT::f32:
+    case MVT::f64:
+    case MVT::v4f32:
+    case MVT::v4i32:
+    case MVT::v8i16:
+    case MVT::v16i8:
+    case MVT::v2f64:
+    case MVT::v2i64:
+    case MVT::v1i128:
+    case MVT::f128:
+    case MVT::v4f64:
+    case MVT::v4i1:
+      report_fatal_error("Handling of this parameter type is unimplemented!");
+    }
+  }
+
+  if (!isFunctionGlobalAddress(Callee) &&
+      !isa<ExternalSymbolSDNode>(Callee))
+    report_fatal_error("Handling of indirect call is unimplemented!");
+
+  // Build a sequence of copy-to-reg nodes chained together with token chain
+  // and flag operands which copy the outgoing args into the appropriate regs.
+  SDValue InFlag;
+  for (auto Reg : RegsToPass) {
+    Chain = DAG.getCopyToReg(Chain, dl, Reg.first, Reg.second, InFlag);
+    InFlag = Chain.getValue(1);
+  }
+
   return FinishCall(CallConv, dl, isTailCall, isVarArg, isPatchPoint,
                     /* unused except on PPC64 ELFv1 */ false, DAG,
                     RegsToPass, InFlag, Chain, CallSeqStart, Callee, SPDiff,

Modified: llvm/trunk/lib/Target/PowerPC/PPCRegisterInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCRegisterInfo.cpp?rev=362708&r1=362707&r2=362708&view=diff
==============================================================================
--- llvm/trunk/lib/Target/PowerPC/PPCRegisterInfo.cpp (original)
+++ llvm/trunk/lib/Target/PowerPC/PPCRegisterInfo.cpp Thu Jun  6 07:36:43 2019
@@ -298,6 +298,11 @@ BitVector PPCRegisterInfo::getReservedRe
     markSuperRegs(Reserved, PPC::R13); // Small Data Area pointer register
   }
 
+  // Always reserve r2 on AIX for now.
+  // TODO: Make r2 allocatable on AIX/XCOFF for some leaf functions.
+  if (Subtarget.isAIXABI())
+    markSuperRegs(Reserved, PPC::R2);  // System-reserved register
+
   // On PPC64, r13 is the thread pointer. Never allocate this register.
   if (TM.isPPC64())
     markSuperRegs(Reserved, PPC::R13);

Added: llvm/trunk/test/CodeGen/PowerPC/aix_gpr_param.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/PowerPC/aix_gpr_param.ll?rev=362708&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/PowerPC/aix_gpr_param.ll (added)
+++ llvm/trunk/test/CodeGen/PowerPC/aix_gpr_param.ll Thu Jun  6 07:36:43 2019
@@ -0,0 +1,199 @@
+; RUN: llc -mtriple powerpc-ibm-aix-xcoff -stop-after=machine-cp < %s | \
+; RUN: FileCheck --check-prefix=32BIT %s
+
+; RUN: llc -mtriple powerpc64-ibm-aix-xcoff -stop-after=machine-cp < %s | \
+; RUN: FileCheck --check-prefix=64BIT %s
+
+define void @call_test_char() {
+entry:
+; 32BIT: ADJCALLSTACKDOWN 56, 0, implicit-def dead $r1, implicit $r1
+; 32BIT: $r3 = LI 97
+; 32BIT: BL_NOP @test_char, csr_aix32, implicit-def dead $lr, implicit $rm, implicit killed $r3, implicit $r2, implicit-def $r1
+; 32BIT: ADJCALLSTACKUP 56, 0, implicit-def dead $r1, implicit $r1
+
+; 64BIT: ADJCALLSTACKDOWN 112, 0, implicit-def dead $r1, implicit $r1
+; 64BIT: $x3 = LI8 97
+; 64BIT: BL8_NOP @test_char, csr_aix64, implicit-def dead $lr8, implicit $rm, implicit killed $x3, implicit $x2, implicit-def $r1
+; 64BIT: ADJCALLSTACKUP 112, 0, implicit-def dead $r1, implicit $r1
+
+  call void @test_char(i8 signext 97)
+  ret void
+}
+
+define void @call_test_chars() {
+entry:
+; 32BIT: ADJCALLSTACKDOWN 56, 0, implicit-def dead $r1, implicit $r1
+; 32BIT: $r3 = LI 97
+; 32BIT: $r4 = LI 97
+; 32BIT: $r5 = LI 97
+; 32BIT: $r6 = LI 97
+; 32BIT: BL_NOP @test_chars, csr_aix32, implicit-def dead $lr, implicit $rm, implicit killed $r3, implicit killed $r4, implicit killed $r5, implicit killed $r6, implicit $r2, implicit-def $r1
+; 32BIT: ADJCALLSTACKUP 56, 0, implicit-def dead $r1, implicit $r1
+
+; 64BIT: ADJCALLSTACKDOWN 112, 0, implicit-def dead $r1, implicit $r1
+; 64BIT: $x3 = LI8 97
+; 64BIT: $x4 = LI8 97
+; 64BIT: $x5 = LI8 97
+; 64BIT: $x6 = LI8 97
+; 64BIT: BL8_NOP @test_chars, csr_aix64, implicit-def dead $lr8, implicit $rm, implicit killed $x3, implicit killed $x4, implicit killed $x5, implicit killed $x6, implicit $x2, implicit-def $r1
+; 64BIT: ADJCALLSTACKUP 112, 0, implicit-def dead $r1, implicit $r1
+
+  call void @test_chars(i8 signext 97, i8 signext 97, i8 signext 97, i8 signext 97)
+  ret void
+}
+
+define void @call_test_chars_mix() {
+entry:
+; 32BIT: ADJCALLSTACKDOWN 56, 0, implicit-def dead $r1, implicit $r1
+; 32BIT: $r3 = LI 97
+; 32BIT: $r4 = LI 225
+; 32BIT: $r5 = LI 97
+; 32BIT: $r6 = LI -31
+; 32BIT: BL_NOP @test_chars_mix, csr_aix32, implicit-def dead $lr, implicit $rm, implicit killed $r3, implicit killed $r4, implicit killed $r5, implicit killed $r6, implicit $r2, implicit-def $r1
+; 32BIT: ADJCALLSTACKUP 56, 0, implicit-def dead $r1, implicit $r1
+
+; 64BIT: ADJCALLSTACKDOWN 112, 0, implicit-def dead $r1, implicit $r1
+; 64BIT: $x3 = LI8 97
+; 64BIT: $x4 = LI8 225
+; 64BIT: $x5 = LI8 97
+; 64BIT: $x6 = LI8 -31
+; 64BIT: BL8_NOP @test_chars_mix, csr_aix64, implicit-def dead $lr8, implicit $rm, implicit killed $x3, implicit killed $x4, implicit killed $x5, implicit killed $x6, implicit $x2, implicit-def $r1
+; 64BIT: ADJCALLSTACKUP 112, 0, implicit-def dead $r1, implicit $r1
+
+  call void @test_chars_mix(i8 signext 97, i8 zeroext -31, i8 zeroext 97, i8 signext -31)
+  ret void
+}
+
+define void @call_test_int() {
+entry:
+; 32BIT: ADJCALLSTACKDOWN 56, 0, implicit-def dead $r1, implicit $r1
+; 32BIT: $r3 = LI 1
+; 32BIT: BL_NOP @test_int, csr_aix32, implicit-def dead $lr, implicit $rm, implicit killed $r3, implicit $r2, implicit-def $r1
+; 32BIT: ADJCALLSTACKUP 56, 0, implicit-def dead $r1, implicit $r1
+
+; 64BIT: ADJCALLSTACKDOWN 112, 0, implicit-def dead $r1, implicit $r1
+; 64BIT: $x3 = LI8 1
+; 64BIT: BL8_NOP @test_int, csr_aix64, implicit-def dead $lr8, implicit $rm, implicit killed $x3, implicit $x2, implicit-def $r1
+; 64BIT: ADJCALLSTACKUP 112, 0, implicit-def dead $r1, implicit $r1
+
+  call void @test_int(i32 1)
+  ret void
+}
+
+define void @call_test_ints() {
+entry:
+; 32BIT: ADJCALLSTACKDOWN 56, 0, implicit-def dead $r1, implicit $r1
+; 32BIT: $r3 = LI 1
+; 32BIT: $r4 = LI 1
+; 32BIT: $r5 = LI 1
+; 32BIT: $r6 = LI 1
+; 32BIT: $r7 = LI 1
+; 32BIT: $r8 = LI 1
+; 32BIT: $r9 = LI 1
+; 32BIT: $r10 = LI 1
+; 32BIT: BL_NOP @test_ints, csr_aix32, implicit-def dead $lr, implicit $rm, implicit killed $r3, implicit killed $r4, implicit killed $r5, implicit killed $r6, implicit killed $r7, implicit killed $r8, implicit killed $r9, implicit killed $r10, implicit $r2, implicit-def $r1
+; 32BIT: ADJCALLSTACKUP 56, 0, implicit-def dead $r1, implicit $r1
+
+; 64BIT: ADJCALLSTACKDOWN 112, 0, implicit-def dead $r1, implicit $r1
+; 64BIT: $x3 = LI8 1
+; 64BIT: $x4 = LI8 1
+; 64BIT: $x5 = LI8 1
+; 64BIT: $x6 = LI8 1
+; 64BIT: $x7 = LI8 1
+; 64BIT: $x8 = LI8 1
+; 64BIT: $x9 = LI8 1
+; 64BIT: $x10 = LI8 1
+; 64BIT: BL8_NOP @test_ints, csr_aix64, implicit-def dead $lr8, implicit $rm, implicit killed $x3, implicit killed $x4, implicit killed $x5, implicit killed $x6, implicit killed $x7, implicit killed $x8, implicit killed $x9, implicit killed $x10, implicit $x2, implicit-def $r1
+; 64BIT: ADJCALLSTACKUP 112, 0, implicit-def dead $r1, implicit $r1
+
+  call void @test_ints(i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1)
+  ret void
+}
+
+define void @call_test_ints_64bit() {
+entry:
+; 64BIT: ADJCALLSTACKDOWN 112, 0, implicit-def dead $r1, implicit $r1
+; 64BIT: renamable $x3 = LI8 1
+; 64BIT: renamable $x5 = RLDICR killed renamable $x3, 31, 32
+; 64BIT: $x3 = LI8 1
+; 64BIT: $x4 = LI8 1
+; 64BIT: $x6 = LIS8 32768
+; 64BIT: $x7 = LI8 1
+; 64BIT: $x8 = LI8 1
+; 64BIT: $x9 = LI8 1
+; 64BIT: $x10 = LI8 1
+; 64BIT: BL8_NOP @test_ints_64bit, csr_aix64, implicit-def dead $lr8, implicit $rm, implicit $x3, implicit killed $x4, implicit $x5, implicit killed $x6, implicit killed $x7, implicit killed $x8, implicit killed $x9, implicit killed $x10, implicit $x2, implicit-def $r1
+; 64BIT: ADJCALLSTACKUP 112, 0, implicit-def dead $r1, implicit $r1
+
+  call void @test_ints_64bit(i32 signext 1, i32 zeroext 1, i32 zeroext 2147483648, i32 signext -2147483648, i32 signext 1, i32 signext 1, i32 signext 1, i32 signext 1)
+  ret void
+}
+
+define void @call_test_i1() {
+entry:
+; 32BIT: ADJCALLSTACKDOWN 56, 0, implicit-def dead $r1, implicit $r1
+; 32BIT: $r3 = LI 1
+; 32BIT: BL_NOP @test_i1, csr_aix32, implicit-def dead $lr, implicit $rm, implicit killed $r3, implicit $r2, implicit-def $r1
+; 32BIT: ADJCALLSTACKUP 56, 0, implicit-def dead $r1, implicit $r1
+
+; 64BIT: ADJCALLSTACKDOWN 112, 0, implicit-def dead $r1, implicit $r1
+; 64BIT: $x3 = LI8 1
+; 64BIT: BL8_NOP @test_i1, csr_aix64, implicit-def dead $lr8, implicit $rm, implicit killed $x3, implicit $x2, implicit-def $r1
+; 64BIT: ADJCALLSTACKUP 112, 0, implicit-def dead $r1, implicit $r1
+
+  call void @test_i1(i1 1)
+  ret void
+}
+
+define void @call_test_i64() {
+entry:
+; 32BIT: ADJCALLSTACKDOWN 56, 0, implicit-def dead $r1, implicit $r1
+; 32BIT: $r3 = LI 0
+; 32BIT: $r4 = LI 1
+; 32BIT: BL_NOP @test_i64, csr_aix32, implicit-def dead $lr, implicit $rm, implicit killed $r3, implicit killed $r4, implicit $r2, implicit-def $r1
+; 32BIT: ADJCALLSTACKUP 56, 0, implicit-def dead $r1, implicit $r1
+
+; 64BIT: ADJCALLSTACKDOWN 112, 0, implicit-def dead $r1, implicit $r1
+; 64BIT: $x3 = LI8 1
+; 64BIT: BL8_NOP @test_i64, csr_aix64, implicit-def dead $lr8, implicit $rm, implicit killed $x3, implicit $x2, implicit-def $r1
+; 64BIT: ADJCALLSTACKUP 112, 0, implicit-def dead $r1, implicit $r1
+
+  call void @test_i64(i64 1)
+  ret void
+}
+
+define void @call_test_int_ptr() {
+entry:
+  %b = alloca i32, align 4
+; 32BIT: ADJCALLSTACKDOWN 56, 0, implicit-def dead $r1, implicit $r1
+; 32BIT: renamable $r3 = ADDI %stack.0.b, 0
+; 32BIT: BL_NOP @test_int_ptr, csr_aix32, implicit-def dead $lr, implicit $rm, implicit $r3, implicit $r2, implicit-def $r1
+; 32BIT: ADJCALLSTACKUP 56, 0, implicit-def dead $r1, implicit $r1
+
+; 64BIT: ADJCALLSTACKDOWN 112, 0, implicit-def dead $r1, implicit $r1
+; 64BIT: renamable $x3 = ADDI8 %stack.0.b, 0
+; 64BIT: BL8_NOP @test_int_ptr, csr_aix64, implicit-def dead $lr8, implicit $rm, implicit $x3, implicit $x2, implicit-def $r1
+; 64BIT: ADJCALLSTACKUP 112, 0, implicit-def dead $r1, implicit $r1
+
+  store i32 0, i32* %b, align 4
+  call void @test_int_ptr(i32* %b)
+  ret void
+}
+
+declare void @test_char(i8 signext)
+
+declare void @test_chars(i8 signext, i8 signext, i8 signext, i8 signext)
+
+declare void @test_chars_mix(i8 signext, i8 zeroext, i8 zeroext, i8 signext)
+
+declare void @test_int(i32)
+
+declare void @test_ints(i32, i32, i32, i32, i32, i32, i32, i32)
+
+declare void @test_ints_64bit(i32 signext, i32 zeroext, i32 zeroext, i32 signext, i32 signext, i32 signext, i32 signext, i32 signext)
+
+declare void @test_i1(i1)
+
+declare void @test_i64(i64)
+
+declare void @test_int_ptr(i32*)

Modified: llvm/trunk/test/CodeGen/PowerPC/test_call_aix.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/PowerPC/test_call_aix.ll?rev=362708&r1=362707&r2=362708&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/PowerPC/test_call_aix.ll (original)
+++ llvm/trunk/test/CodeGen/PowerPC/test_call_aix.ll Thu Jun  6 07:36:43 2019
@@ -9,11 +9,11 @@ declare void @foo(...)
 define void @test_call() {
 entry:
 ; 32BIT: ADJCALLSTACKDOWN 56, 0, implicit-def dead $r1, implicit $r1
-; 32BIT: BL_NOP @foo, csr_aix32, implicit-def dead $lr, implicit $rm, implicit-def $r1
+; 32BIT: BL_NOP @foo, csr_aix32, implicit-def dead $lr, implicit $rm, implicit $r2, implicit-def $r1
 ; 32BIT: ADJCALLSTACKUP 56, 0, implicit-def dead $r1, implicit $r1
 
 ; 64BIT: ADJCALLSTACKDOWN 112, 0, implicit-def dead $r1, implicit $r1
-; 64BIT: BL8_NOP @foo, csr_aix64, implicit-def dead $lr8, implicit $rm, implicit-def $r1
+; 64BIT: BL8_NOP @foo, csr_aix64, implicit-def dead $lr8, implicit $rm, implicit $x2, implicit-def $r1
 ; 64BIT: ADJCALLSTACKUP 112, 0, implicit-def dead $r1, implicit $r1
 
   call void bitcast (void (...)* @foo to void ()*)()
@@ -28,11 +28,11 @@ entry:
 define void @test_local_call() {
 entry:
 ; 32BIT: ADJCALLSTACKDOWN 56, 0, implicit-def dead $r1, implicit $r1
-; 32BIT: BL @foo_local, csr_aix32, implicit-def dead $lr, implicit $rm, implicit-def $r1
+; 32BIT: BL @foo_local, csr_aix32, implicit-def dead $lr, implicit $rm, implicit $r2, implicit-def $r1
 ; 32BIT: ADJCALLSTACKUP 56, 0, implicit-def dead $r1, implicit $r1
 
 ; 64BIT: ADJCALLSTACKDOWN 112, 0, implicit-def dead $r1, implicit $r1
-; 64BIT: BL8 @foo_local, csr_aix64, implicit-def dead $lr8, implicit $rm, implicit-def $r1
+; 64BIT: BL8 @foo_local, csr_aix64, implicit-def dead $lr8, implicit $rm, implicit $x2, implicit-def $r1
 ; 64BIT: ADJCALLSTACKUP 112, 0, implicit-def dead $r1, implicit $r1
 
   call void @foo_local()




More information about the llvm-commits mailing list