[llvm] b006f55 - [SystemZ/z/OS] Add XPLINK 64-bit calling convention to tablegen.

Kai Nacke via llvm-commits llvm-commits at lists.llvm.org
Fri Feb 19 15:40:37 PST 2021


Author: Yusra Syeda
Date: 2021-02-19T18:39:49-05:00
New Revision: b006f555448a7b842f6d89cf4cdc6e2aa0b9a31e

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

LOG: [SystemZ/z/OS] Add XPLINK 64-bit calling convention to tablegen.

This commit adds the initial changes to the SystemZ target
description for the XPLINK 64-bit calling convention on z/OS.
Additions include:

 - a new predicate IsTargetXPLINK64
 - different register allocation order
 - generaton of nopr after a call

Reviewed-by: uweigand

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

Added: 
    

Modified: 
    llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
    llvm/lib/Target/SystemZ/SystemZCallingConv.td
    llvm/lib/Target/SystemZ/SystemZInstrInfo.td
    llvm/lib/Target/SystemZ/SystemZRegisterInfo.td
    llvm/lib/Target/SystemZ/SystemZScheduleZ13.td
    llvm/lib/Target/SystemZ/SystemZScheduleZ14.td
    llvm/lib/Target/SystemZ/SystemZScheduleZ15.td
    llvm/lib/Target/SystemZ/SystemZScheduleZ196.td
    llvm/lib/Target/SystemZ/SystemZScheduleZEC12.td
    llvm/lib/Target/SystemZ/SystemZSubtarget.h

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
index 584737e1d940..ea5c3cbc3211 100644
--- a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
@@ -126,10 +126,15 @@ static MCInst lowerSubvectorStore(const MachineInstr *MI, unsigned Opcode) {
 
 void SystemZAsmPrinter::emitInstruction(const MachineInstr *MI) {
   SystemZMCInstLower Lower(MF->getContext(), *this);
+  const SystemZSubtarget *Subtarget = &MF->getSubtarget<SystemZSubtarget>();
   MCInst LoweredMI;
   switch (MI->getOpcode()) {
   case SystemZ::Return:
-    LoweredMI = MCInstBuilder(SystemZ::BR).addReg(SystemZ::R14D);
+    if (Subtarget->isTargetXPLINK64())
+      LoweredMI =
+          MCInstBuilder(SystemZ::B).addReg(SystemZ::R7D).addImm(2).addReg(0);
+    else
+      LoweredMI = MCInstBuilder(SystemZ::BR).addReg(SystemZ::R14D);
     break;
 
   case SystemZ::CondReturn:
@@ -211,6 +216,26 @@ void SystemZAsmPrinter::emitInstruction(const MachineInstr *MI) {
       .addImm(0);
     break;
 
+  case SystemZ::CallBRASL_XPLINK64:
+    EmitToStreamer(*OutStreamer,
+                   MCInstBuilder(SystemZ::BRASL)
+                       .addReg(SystemZ::R7D)
+                       .addExpr(Lower.getExpr(MI->getOperand(0),
+                                              MCSymbolRefExpr::VK_PLT)));
+    EmitToStreamer(
+        *OutStreamer,
+        MCInstBuilder(SystemZ::BCRAsm).addImm(0).addReg(SystemZ::R3D));
+    return;
+
+  case SystemZ::CallBASR_XPLINK64:
+    EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR)
+                                     .addReg(SystemZ::R7D)
+                                     .addReg(MI->getOperand(0).getReg()));
+    EmitToStreamer(
+        *OutStreamer,
+        MCInstBuilder(SystemZ::BCRAsm).addImm(0).addReg(SystemZ::R0D));
+    return;
+
   case SystemZ::CallBRASL:
     LoweredMI = MCInstBuilder(SystemZ::BRASL)
       .addReg(SystemZ::R14D)

diff  --git a/llvm/lib/Target/SystemZ/SystemZCallingConv.td b/llvm/lib/Target/SystemZ/SystemZCallingConv.td
index 9af525e26637..29010ab8bd1c 100644
--- a/llvm/lib/Target/SystemZ/SystemZCallingConv.td
+++ b/llvm/lib/Target/SystemZ/SystemZCallingConv.td
@@ -155,6 +155,12 @@ def CSR_SystemZ_AllRegs_Vector : CalleeSavedRegs<(add (sequence "R%dD", 2, 15),
 
 def CSR_SystemZ_NoRegs : CalleeSavedRegs<(add)>;
 
+//===----------------------------------------------------------------------===//
+// z/OS XPLINK64 callee-saved registers
+//===----------------------------------------------------------------------===//
+def CSR_SystemZ_XPLINK64 : CalleeSavedRegs<(add (sequence "R%dD", 8, 15),
+                                                (sequence "F%dD", 8, 15))>;
+
 //===----------------------------------------------------------------------===//
 // s390x return value calling convention
 //===----------------------------------------------------------------------===//

diff  --git a/llvm/lib/Target/SystemZ/SystemZInstrInfo.td b/llvm/lib/Target/SystemZ/SystemZInstrInfo.td
index ff54541477f4..ed6dc193eca0 100644
--- a/llvm/lib/Target/SystemZ/SystemZInstrInfo.td
+++ b/llvm/lib/Target/SystemZ/SystemZInstrInfo.td
@@ -6,6 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+def IsTargetXPLINK64      : Predicate<"Subtarget->isTargetXPLINK64()">;
 def IsTargetELF           : Predicate<"Subtarget->isTargetELF()">;
 
 //===----------------------------------------------------------------------===//
@@ -275,6 +276,16 @@ let isCall = 1, Defs = [CC] in {
   def BASR  : CallRR <"basr", 0x0D>;
 }
 
+// z/OS XPLINK
+let Predicates = [IsTargetXPLINK64] in {
+  let isCall = 1, Defs = [R7D, CC], Uses = [FPC] in {
+    def CallBRASL_XPLINK64 : Alias<8, (outs), (ins pcrel32:$I2, variable_ops),
+                          [(z_call pcrel32:$I2)]>;
+    def CallBASR_XPLINK64  : Alias<4, (outs), (ins ADDR64:$R2, variable_ops),
+                          [(z_call ADDR64:$R2)]>;
+  }
+}
+
 // Regular calls.
 // z/Linux ELF
 let Predicates = [IsTargetELF] in {
@@ -295,7 +306,8 @@ let Predicates = [IsTargetELF] in {
   }
 }
 
-// Sibling calls.
+// Sibling calls. Indirect sibling calls must be via R6 for XPLink,
+// R1 used for ELF
 let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in {
   def CallJG : Alias<6, (outs), (ins pcrel32:$I2),
                      [(z_sibcall pcrel32:$I2)]>;
@@ -323,7 +335,7 @@ let isCall = 1, isTerminator = 1, isReturn = 1 in {
   def CLGIBCall : Alias<6, (outs), (ins GR64:$R1, imm64zx8:$I2, cond4:$M3, ADDR64:$R4), []>;
 }
 
-// A return instruction (br %r14).
+// A return instruction (br %r14) for ELF and (b 2 %r7) for XPLink.
 let isReturn = 1, isTerminator = 1, isBarrier = 1, hasCtrlDep = 1 in
   def Return : Alias<2, (outs), (ins), [(z_retflag)]>;
 

diff  --git a/llvm/lib/Target/SystemZ/SystemZRegisterInfo.td b/llvm/lib/Target/SystemZ/SystemZRegisterInfo.td
index a85862e62749..00005a6d6179 100644
--- a/llvm/lib/Target/SystemZ/SystemZRegisterInfo.td
+++ b/llvm/lib/Target/SystemZ/SystemZRegisterInfo.td
@@ -31,8 +31,10 @@ def subreg_hl32  : ComposedSubRegIndex<subreg_h64, subreg_l32>;
 // Define a register class that contains values of types TYPES and an
 // associated operand called NAME.  SIZE is the size and alignment
 // of the registers and REGLIST is the list of individual registers.
+// If the user provides an alternate order list of regs, it will be used for
+// XPLINK. Otherwise, by default, XPLINK will use the regList ordering as well
 multiclass SystemZRegClass<string name, list<ValueType> types, int size,
-                           dag regList, bit allocatable = 1> {
+                           dag regList, list<dag> altRegList = [regList], bit allocatable = 1> {
   def AsmOperand : AsmOperandClass {
     let Name = name;
     let ParserMethod = "parse"#name;
@@ -41,6 +43,11 @@ multiclass SystemZRegClass<string name, list<ValueType> types, int size,
   let isAllocatable = allocatable in
     def Bit : RegisterClass<"SystemZ", types, size, regList> {
       let Size = size;
+      let AltOrders = altRegList;
+      let AltOrderSelect = [{
+        const SystemZSubtarget &S = MF.getSubtarget<SystemZSubtarget>();
+        return S.isTargetXPLINK64();
+      }];
     }
   def "" : RegisterOperand<!cast<RegisterClass>(name#"Bit")> {
     let ParserMatchClass = !cast<AsmOperandClass>(name#"AsmOperand");
@@ -85,40 +92,58 @@ foreach I = [0, 2, 4, 6, 8, 10, 12, 14] in {
                      !cast<GPR64>("R"#I#"D")>;
 }
 
-/// Allocate the callee-saved R6-R13 backwards. That way they can be saved
-/// together with R14 and R15 in one prolog instruction.
+/// zLinux: Allocate the callee-saved R6-R13 backwards. That way they can be
+/// saved together with R14 and R15 in one prolog instruction.
+/// XPLINK64: Allocate all registers in natural order
 defm GR32  : SystemZRegClass<"GR32",  [i32], 32,
                              (add (sequence "R%uL",  0, 5),
-                                  (sequence "R%uL", 15, 6))>;
+                                  (sequence "R%uL", 15, 6)),
+                             [(add (sequence "R%uL", 0, 15))]>;
 defm GRH32 : SystemZRegClass<"GRH32", [i32], 32,
                              (add (sequence "R%uH",  0, 5),
-                                  (sequence "R%uH", 15, 6))>;
+                                  (sequence "R%uH", 15, 6)),
+                             [(add (sequence "R%uH", 0, 15))]>;
 defm GR64  : SystemZRegClass<"GR64",  [i64], 64,
                              (add (sequence "R%uD",  0, 5),
-                                  (sequence "R%uD", 15, 6))>;
+                                  (sequence "R%uD", 15, 6)),
+                             [(add (sequence "R%uD",  0, 15))]>;
 
 // Combine the low and high GR32s into a single class.  This can only be
 // used for virtual registers if the high-word facility is available.
+/// XPLINK64: Allocate all registers in natural order
 defm GRX32 : SystemZRegClass<"GRX32", [i32], 32,
                              (add (sequence "R%uL",  0, 5),
                                   (sequence "R%uH",  0, 5),
                                   R15L, R15H, R14L, R14H, R13L, R13H,
                                   R12L, R12H, R11L, R11H, R10L, R10H,
-                                  R9L, R9H, R8L, R8H, R7L, R7H, R6L, R6H)>;
+                                  R9L, R9H, R8L, R8H, R7L, R7H, R6L, R6H),
+                             [(add
+                               R0L, R1L, R2L, R3L, R0H, R1H, R2H, R3H,
+                               R4L, R4H, R5L, R5H, R6L, R6H, R7L, R7H,
+                               R8L, R8H, R9L, R9H, R10L,R10H,R11L,R11H,
+                               R12L,R12H,R13L,R13H,R14L,R14H,R15L,R15H)
+                             ]>;
 
 // The architecture doesn't really have any i128 support, so model the
 // register pairs as untyped instead.
+// XPLINK64: Allocate all registers in natural order
 defm GR128 : SystemZRegClass<"GR128", [untyped], 128,
-                             (add R0Q, R2Q, R4Q, R12Q, R10Q, R8Q, R6Q, R14Q)>;
+                             (add R0Q, R2Q, R4Q, R12Q, R10Q, R8Q, R6Q, R14Q),
+                             [(add R0Q, R2Q, R4Q, R6Q, R8Q, R10Q, R12Q, R14Q)]>;
 
 // Base and index registers.  Everything except R0, which in an address
 // context evaluates as 0.
-defm ADDR32 : SystemZRegClass<"ADDR32", [i32], 32, (sub GR32Bit, R0L)>;
-defm ADDR64 : SystemZRegClass<"ADDR64", [i64], 64, (sub GR64Bit, R0D)>;
+// XPLINK64: Allocate all registers in natural order
+defm ADDR32 : SystemZRegClass<"ADDR32", [i32], 32, (sub GR32Bit, R0L),
+                              [(add (sequence "R%uL",  1, 15))]>;
+defm ADDR64 : SystemZRegClass<"ADDR64", [i64], 64, (sub GR64Bit, R0D),
+                              [(add (sequence "R%uD",  1, 15))]>;
 
 // Not used directly, but needs to exist for ADDR32 and ADDR64 subregs
 // of a GR128.
-defm ADDR128 : SystemZRegClass<"ADDR128", [untyped], 128, (sub GR128Bit, R0Q)>;
+// XPLINK64: Allocate all registers in natural order
+defm ADDR128 : SystemZRegClass<"ADDR128", [untyped], 128, (sub GR128Bit, R0Q),
+                               [(add R2Q, R4Q, R6Q, R8Q, R10Q, R12Q, R14Q)]>;
 
 // Any type register. Used for .insn directives when we don't know what the
 // register types could be.
@@ -126,7 +151,8 @@ defm AnyReg : SystemZRegClass<"AnyReg",
                               [i64, f64, v8i8, v4i16, v2i32, v2f32], 64,
                               (add (sequence "R%uD", 0, 15),
                                    (sequence "F%uD", 0, 15),
-                                   (sequence "V%u", 0, 15)), 0/*allocatable*/>;
+                                   (sequence "V%u", 0, 15)),
+                              [], 0/*allocatable*/>;
 
 //===----------------------------------------------------------------------===//
 // Floating-point registers
@@ -310,7 +336,7 @@ foreach I = 0-15 in {
   def A#I : ACR32<I, "a"#I>, DwarfRegNum<[!add(I, 48)]>;
 }
 defm AR32 : SystemZRegClass<"AR32", [i32], 32,
-                            (add (sequence "A%u", 0, 15)), 0>;
+                            (add (sequence "A%u", 0, 15)), [], 0>;
 
 // Control registers.
 class CREG64<bits<16> num, string n> : SystemZReg<n> {
@@ -320,5 +346,4 @@ foreach I = 0-15 in {
   def C#I : CREG64<I, "c"#I>, DwarfRegNum<[!add(I, 32)]>;
 }
 defm CR64 : SystemZRegClass<"CR64", [i64], 64,
-                            (add (sequence "C%u", 0, 15)), 0>;
-
+                            (add (sequence "C%u", 0, 15)), [], 0>;

diff  --git a/llvm/lib/Target/SystemZ/SystemZScheduleZ13.td b/llvm/lib/Target/SystemZ/SystemZScheduleZ13.td
index de49106a5a60..f4777b0097f1 100644
--- a/llvm/lib/Target/SystemZ/SystemZScheduleZ13.td
+++ b/llvm/lib/Target/SystemZ/SystemZScheduleZ13.td
@@ -167,8 +167,8 @@ def : InstRW<[WLat1, FXb, LSU, NormalGr], (instregex "CL(G)?T(Asm.*)?$")>;
 
 // Call
 def : InstRW<[WLat1, VBU, FXa2, GroupAlone], (instregex "(Call)?BRAS$")>;
-def : InstRW<[WLat1, FXa2, FXb, GroupAlone], (instregex "(Call)?BRASL$")>;
-def : InstRW<[WLat1, FXa2, FXb, GroupAlone], (instregex "(Call)?BAS(R)?$")>;
+def : InstRW<[WLat1, FXa2, FXb, GroupAlone], (instregex "(Call)?BRASL(_XPLINK64)?$")>;
+def : InstRW<[WLat1, FXa2, FXb, GroupAlone], (instregex "(Call)?BAS(R)?(_XPLINK64)?$")>;
 def : InstRW<[WLat1, FXa2, FXb, GroupAlone], (instregex "TLS_(G|L)DCALL$")>;
 
 // Return

diff  --git a/llvm/lib/Target/SystemZ/SystemZScheduleZ14.td b/llvm/lib/Target/SystemZ/SystemZScheduleZ14.td
index 5ea269cb891d..f74c0d594482 100644
--- a/llvm/lib/Target/SystemZ/SystemZScheduleZ14.td
+++ b/llvm/lib/Target/SystemZ/SystemZScheduleZ14.td
@@ -168,8 +168,8 @@ def : InstRW<[WLat1, FXb, LSU, NormalGr], (instregex "CL(G)?T(Asm.*)?$")>;
 
 // Call
 def : InstRW<[WLat1, VBU, FXa2, GroupAlone], (instregex "(Call)?BRAS$")>;
-def : InstRW<[WLat1, FXa2, FXb, GroupAlone], (instregex "(Call)?BRASL$")>;
-def : InstRW<[WLat1, FXa2, FXb, GroupAlone], (instregex "(Call)?BAS(R)?$")>;
+def : InstRW<[WLat1, FXa2, FXb, GroupAlone], (instregex "(Call)?BRASL(_XPLINK64)?$")>;
+def : InstRW<[WLat1, FXa2, FXb, GroupAlone], (instregex "(Call)?BAS(R)?(_XPLINK64)?$")>;
 def : InstRW<[WLat1, FXa2, FXb, GroupAlone], (instregex "TLS_(G|L)DCALL$")>;
 
 // Return

diff  --git a/llvm/lib/Target/SystemZ/SystemZScheduleZ15.td b/llvm/lib/Target/SystemZ/SystemZScheduleZ15.td
index 6a28aec6f846..d17e58fc6318 100644
--- a/llvm/lib/Target/SystemZ/SystemZScheduleZ15.td
+++ b/llvm/lib/Target/SystemZ/SystemZScheduleZ15.td
@@ -168,8 +168,8 @@ def : InstRW<[WLat1, FXb, LSU, NormalGr], (instregex "CL(G)?T(Asm.*)?$")>;
 
 // Call
 def : InstRW<[WLat1, VBU, FXa2, GroupAlone], (instregex "(Call)?BRAS$")>;
-def : InstRW<[WLat1, FXa2, FXb, GroupAlone], (instregex "(Call)?BRASL$")>;
-def : InstRW<[WLat1, FXa2, FXb, GroupAlone], (instregex "(Call)?BAS(R)?$")>;
+def : InstRW<[WLat1, FXa2, FXb, GroupAlone], (instregex "(Call)?BRASL(_XPLINK64)?$")>;
+def : InstRW<[WLat1, FXa2, FXb, GroupAlone], (instregex "(Call)?BAS(R)?(_XPLINK64)?$")>;
 def : InstRW<[WLat1, FXa2, FXb, GroupAlone], (instregex "TLS_(G|L)DCALL$")>;
 
 // Return

diff  --git a/llvm/lib/Target/SystemZ/SystemZScheduleZ196.td b/llvm/lib/Target/SystemZ/SystemZScheduleZ196.td
index 9a306591a34f..0f01a4291cf7 100644
--- a/llvm/lib/Target/SystemZ/SystemZScheduleZ196.td
+++ b/llvm/lib/Target/SystemZ/SystemZScheduleZ196.td
@@ -146,8 +146,8 @@ def : InstRW<[WLat1, FXU, NormalGr], (instregex "CL(F|G)IT(Asm.*)?$")>;
 
 // Call
 def : InstRW<[WLat1, LSU, FXU2, GroupAlone], (instregex "(Call)?BRAS$")>;
-def : InstRW<[WLat1, LSU, FXU2, GroupAlone], (instregex "(Call)?BRASL$")>;
-def : InstRW<[WLat1, LSU, FXU2, GroupAlone], (instregex "(Call)?BAS(R)?$")>;
+def : InstRW<[WLat1, LSU, FXU2, GroupAlone], (instregex "(Call)?BRASL(_XPLINK64)?$")>;
+def : InstRW<[WLat1, LSU, FXU2, GroupAlone], (instregex "(Call)?BAS(R)?(_XPLINK64)?$")>;
 def : InstRW<[WLat1, LSU, FXU2, GroupAlone], (instregex "TLS_(G|L)DCALL$")>;
 
 // Return

diff  --git a/llvm/lib/Target/SystemZ/SystemZScheduleZEC12.td b/llvm/lib/Target/SystemZ/SystemZScheduleZEC12.td
index f3ff1dfaba75..096a95a82ec8 100644
--- a/llvm/lib/Target/SystemZ/SystemZScheduleZEC12.td
+++ b/llvm/lib/Target/SystemZ/SystemZScheduleZEC12.td
@@ -151,8 +151,8 @@ def : InstRW<[WLat1, FXU, LSU, NormalGr], (instregex "CL(G)?T(Asm.*)?$")>;
 
 // Call
 def : InstRW<[WLat1, FXU2, VBU, GroupAlone], (instregex "(Call)?BRAS$")>;
-def : InstRW<[WLat1, FXU2, LSU, GroupAlone], (instregex "(Call)?BRASL$")>;
-def : InstRW<[WLat1, FXU2, LSU, GroupAlone], (instregex "(Call)?BAS(R)?$")>;
+def : InstRW<[WLat1, FXU2, LSU, GroupAlone], (instregex "(Call)?BRASL(_XPLINK64)?$")>;
+def : InstRW<[WLat1, FXU2, LSU, GroupAlone], (instregex "(Call)?BAS(R)?(_XPLINK64)?$")>;
 def : InstRW<[WLat1, FXU2, LSU, GroupAlone], (instregex "TLS_(G|L)DCALL$")>;
 
 // Return

diff  --git a/llvm/lib/Target/SystemZ/SystemZSubtarget.h b/llvm/lib/Target/SystemZ/SystemZSubtarget.h
index 3841063d2f61..87cb70182432 100644
--- a/llvm/lib/Target/SystemZ/SystemZSubtarget.h
+++ b/llvm/lib/Target/SystemZ/SystemZSubtarget.h
@@ -248,6 +248,15 @@ class SystemZSubtarget : public SystemZGenSubtargetInfo {
   bool isPC32DBLSymbol(const GlobalValue *GV, CodeModel::Model CM) const;
 
   bool isTargetELF() const { return TargetTriple.isOSBinFormatELF(); }
+
+  // Returns TRUE if we are generating GOFF object code
+  bool isTargetGOFF() const { return TargetTriple.isOSBinFormatGOFF(); }
+
+  // Returns TRUE if we are using XPLINK64 linkage convention
+  bool isTargetXPLINK64() const { return (isTargetGOFF() && isTargetzOS()); }
+
+  // Returns TRUE if we are generating code for a s390x machine running zOS
+  bool isTargetzOS() const { return TargetTriple.isOSzOS(); }
 };
 } // end namespace llvm
 


        


More information about the llvm-commits mailing list