[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