Skip to content

Commit b006f55

Browse files
Yusra Syedaredstar
authored andcommitted
[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
1 parent 3275b18 commit b006f55

10 files changed

+105
-28
lines changed

llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,10 +126,15 @@ static MCInst lowerSubvectorStore(const MachineInstr *MI, unsigned Opcode) {
126126

127127
void SystemZAsmPrinter::emitInstruction(const MachineInstr *MI) {
128128
SystemZMCInstLower Lower(MF->getContext(), *this);
129+
const SystemZSubtarget *Subtarget = &MF->getSubtarget<SystemZSubtarget>();
129130
MCInst LoweredMI;
130131
switch (MI->getOpcode()) {
131132
case SystemZ::Return:
132-
LoweredMI = MCInstBuilder(SystemZ::BR).addReg(SystemZ::R14D);
133+
if (Subtarget->isTargetXPLINK64())
134+
LoweredMI =
135+
MCInstBuilder(SystemZ::B).addReg(SystemZ::R7D).addImm(2).addReg(0);
136+
else
137+
LoweredMI = MCInstBuilder(SystemZ::BR).addReg(SystemZ::R14D);
133138
break;
134139

135140
case SystemZ::CondReturn:
@@ -211,6 +216,26 @@ void SystemZAsmPrinter::emitInstruction(const MachineInstr *MI) {
211216
.addImm(0);
212217
break;
213218

219+
case SystemZ::CallBRASL_XPLINK64:
220+
EmitToStreamer(*OutStreamer,
221+
MCInstBuilder(SystemZ::BRASL)
222+
.addReg(SystemZ::R7D)
223+
.addExpr(Lower.getExpr(MI->getOperand(0),
224+
MCSymbolRefExpr::VK_PLT)));
225+
EmitToStreamer(
226+
*OutStreamer,
227+
MCInstBuilder(SystemZ::BCRAsm).addImm(0).addReg(SystemZ::R3D));
228+
return;
229+
230+
case SystemZ::CallBASR_XPLINK64:
231+
EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR)
232+
.addReg(SystemZ::R7D)
233+
.addReg(MI->getOperand(0).getReg()));
234+
EmitToStreamer(
235+
*OutStreamer,
236+
MCInstBuilder(SystemZ::BCRAsm).addImm(0).addReg(SystemZ::R0D));
237+
return;
238+
214239
case SystemZ::CallBRASL:
215240
LoweredMI = MCInstBuilder(SystemZ::BRASL)
216241
.addReg(SystemZ::R14D)

llvm/lib/Target/SystemZ/SystemZCallingConv.td

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,12 @@ def CSR_SystemZ_AllRegs_Vector : CalleeSavedRegs<(add (sequence "R%dD", 2, 15),
155155

156156
def CSR_SystemZ_NoRegs : CalleeSavedRegs<(add)>;
157157

158+
//===----------------------------------------------------------------------===//
159+
// z/OS XPLINK64 callee-saved registers
160+
//===----------------------------------------------------------------------===//
161+
def CSR_SystemZ_XPLINK64 : CalleeSavedRegs<(add (sequence "R%dD", 8, 15),
162+
(sequence "F%dD", 8, 15))>;
163+
158164
//===----------------------------------------------------------------------===//
159165
// s390x return value calling convention
160166
//===----------------------------------------------------------------------===//

llvm/lib/Target/SystemZ/SystemZInstrInfo.td

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9+
def IsTargetXPLINK64 : Predicate<"Subtarget->isTargetXPLINK64()">;
910
def IsTargetELF : Predicate<"Subtarget->isTargetELF()">;
1011

1112
//===----------------------------------------------------------------------===//
@@ -275,6 +276,16 @@ let isCall = 1, Defs = [CC] in {
275276
def BASR : CallRR <"basr", 0x0D>;
276277
}
277278

279+
// z/OS XPLINK
280+
let Predicates = [IsTargetXPLINK64] in {
281+
let isCall = 1, Defs = [R7D, CC], Uses = [FPC] in {
282+
def CallBRASL_XPLINK64 : Alias<8, (outs), (ins pcrel32:$I2, variable_ops),
283+
[(z_call pcrel32:$I2)]>;
284+
def CallBASR_XPLINK64 : Alias<4, (outs), (ins ADDR64:$R2, variable_ops),
285+
[(z_call ADDR64:$R2)]>;
286+
}
287+
}
288+
278289
// Regular calls.
279290
// z/Linux ELF
280291
let Predicates = [IsTargetELF] in {
@@ -295,7 +306,8 @@ let Predicates = [IsTargetELF] in {
295306
}
296307
}
297308

298-
// Sibling calls.
309+
// Sibling calls. Indirect sibling calls must be via R6 for XPLink,
310+
// R1 used for ELF
299311
let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in {
300312
def CallJG : Alias<6, (outs), (ins pcrel32:$I2),
301313
[(z_sibcall pcrel32:$I2)]>;
@@ -323,7 +335,7 @@ let isCall = 1, isTerminator = 1, isReturn = 1 in {
323335
def CLGIBCall : Alias<6, (outs), (ins GR64:$R1, imm64zx8:$I2, cond4:$M3, ADDR64:$R4), []>;
324336
}
325337

326-
// A return instruction (br %r14).
338+
// A return instruction (br %r14) for ELF and (b 2 %r7) for XPLink.
327339
let isReturn = 1, isTerminator = 1, isBarrier = 1, hasCtrlDep = 1 in
328340
def Return : Alias<2, (outs), (ins), [(z_retflag)]>;
329341

llvm/lib/Target/SystemZ/SystemZRegisterInfo.td

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,10 @@ def subreg_hl32 : ComposedSubRegIndex<subreg_h64, subreg_l32>;
3131
// Define a register class that contains values of types TYPES and an
3232
// associated operand called NAME. SIZE is the size and alignment
3333
// of the registers and REGLIST is the list of individual registers.
34+
// If the user provides an alternate order list of regs, it will be used for
35+
// XPLINK. Otherwise, by default, XPLINK will use the regList ordering as well
3436
multiclass SystemZRegClass<string name, list<ValueType> types, int size,
35-
dag regList, bit allocatable = 1> {
37+
dag regList, list<dag> altRegList = [regList], bit allocatable = 1> {
3638
def AsmOperand : AsmOperandClass {
3739
let Name = name;
3840
let ParserMethod = "parse"#name;
@@ -41,6 +43,11 @@ multiclass SystemZRegClass<string name, list<ValueType> types, int size,
4143
let isAllocatable = allocatable in
4244
def Bit : RegisterClass<"SystemZ", types, size, regList> {
4345
let Size = size;
46+
let AltOrders = altRegList;
47+
let AltOrderSelect = [{
48+
const SystemZSubtarget &S = MF.getSubtarget<SystemZSubtarget>();
49+
return S.isTargetXPLINK64();
50+
}];
4451
}
4552
def "" : RegisterOperand<!cast<RegisterClass>(name#"Bit")> {
4653
let ParserMatchClass = !cast<AsmOperandClass>(name#"AsmOperand");
@@ -85,48 +92,67 @@ foreach I = [0, 2, 4, 6, 8, 10, 12, 14] in {
8592
!cast<GPR64>("R"#I#"D")>;
8693
}
8794

88-
/// Allocate the callee-saved R6-R13 backwards. That way they can be saved
89-
/// together with R14 and R15 in one prolog instruction.
95+
/// zLinux: Allocate the callee-saved R6-R13 backwards. That way they can be
96+
/// saved together with R14 and R15 in one prolog instruction.
97+
/// XPLINK64: Allocate all registers in natural order
9098
defm GR32 : SystemZRegClass<"GR32", [i32], 32,
9199
(add (sequence "R%uL", 0, 5),
92-
(sequence "R%uL", 15, 6))>;
100+
(sequence "R%uL", 15, 6)),
101+
[(add (sequence "R%uL", 0, 15))]>;
93102
defm GRH32 : SystemZRegClass<"GRH32", [i32], 32,
94103
(add (sequence "R%uH", 0, 5),
95-
(sequence "R%uH", 15, 6))>;
104+
(sequence "R%uH", 15, 6)),
105+
[(add (sequence "R%uH", 0, 15))]>;
96106
defm GR64 : SystemZRegClass<"GR64", [i64], 64,
97107
(add (sequence "R%uD", 0, 5),
98-
(sequence "R%uD", 15, 6))>;
108+
(sequence "R%uD", 15, 6)),
109+
[(add (sequence "R%uD", 0, 15))]>;
99110

100111
// Combine the low and high GR32s into a single class. This can only be
101112
// used for virtual registers if the high-word facility is available.
113+
/// XPLINK64: Allocate all registers in natural order
102114
defm GRX32 : SystemZRegClass<"GRX32", [i32], 32,
103115
(add (sequence "R%uL", 0, 5),
104116
(sequence "R%uH", 0, 5),
105117
R15L, R15H, R14L, R14H, R13L, R13H,
106118
R12L, R12H, R11L, R11H, R10L, R10H,
107-
R9L, R9H, R8L, R8H, R7L, R7H, R6L, R6H)>;
119+
R9L, R9H, R8L, R8H, R7L, R7H, R6L, R6H),
120+
[(add
121+
R0L, R1L, R2L, R3L, R0H, R1H, R2H, R3H,
122+
R4L, R4H, R5L, R5H, R6L, R6H, R7L, R7H,
123+
R8L, R8H, R9L, R9H, R10L,R10H,R11L,R11H,
124+
R12L,R12H,R13L,R13H,R14L,R14H,R15L,R15H)
125+
]>;
108126

109127
// The architecture doesn't really have any i128 support, so model the
110128
// register pairs as untyped instead.
129+
// XPLINK64: Allocate all registers in natural order
111130
defm GR128 : SystemZRegClass<"GR128", [untyped], 128,
112-
(add R0Q, R2Q, R4Q, R12Q, R10Q, R8Q, R6Q, R14Q)>;
131+
(add R0Q, R2Q, R4Q, R12Q, R10Q, R8Q, R6Q, R14Q),
132+
[(add R0Q, R2Q, R4Q, R6Q, R8Q, R10Q, R12Q, R14Q)]>;
113133

114134
// Base and index registers. Everything except R0, which in an address
115135
// context evaluates as 0.
116-
defm ADDR32 : SystemZRegClass<"ADDR32", [i32], 32, (sub GR32Bit, R0L)>;
117-
defm ADDR64 : SystemZRegClass<"ADDR64", [i64], 64, (sub GR64Bit, R0D)>;
136+
// XPLINK64: Allocate all registers in natural order
137+
defm ADDR32 : SystemZRegClass<"ADDR32", [i32], 32, (sub GR32Bit, R0L),
138+
[(add (sequence "R%uL", 1, 15))]>;
139+
defm ADDR64 : SystemZRegClass<"ADDR64", [i64], 64, (sub GR64Bit, R0D),
140+
[(add (sequence "R%uD", 1, 15))]>;
118141

119142
// Not used directly, but needs to exist for ADDR32 and ADDR64 subregs
120143
// of a GR128.
121-
defm ADDR128 : SystemZRegClass<"ADDR128", [untyped], 128, (sub GR128Bit, R0Q)>;
144+
// XPLINK64: Allocate all registers in natural order
145+
defm ADDR128 : SystemZRegClass<"ADDR128", [untyped], 128, (sub GR128Bit, R0Q),
146+
[(add R2Q, R4Q, R6Q, R8Q, R10Q, R12Q, R14Q)]>;
122147

123148
// Any type register. Used for .insn directives when we don't know what the
124149
// register types could be.
125150
defm AnyReg : SystemZRegClass<"AnyReg",
126151
[i64, f64, v8i8, v4i16, v2i32, v2f32], 64,
127152
(add (sequence "R%uD", 0, 15),
128153
(sequence "F%uD", 0, 15),
129-
(sequence "V%u", 0, 15)), 0/*allocatable*/>;
154+
(sequence "V%u", 0, 15)),
155+
[], 0/*allocatable*/>;
130156

131157
//===----------------------------------------------------------------------===//
132158
// Floating-point registers
@@ -310,7 +336,7 @@ foreach I = 0-15 in {
310336
def A#I : ACR32<I, "a"#I>, DwarfRegNum<[!add(I, 48)]>;
311337
}
312338
defm AR32 : SystemZRegClass<"AR32", [i32], 32,
313-
(add (sequence "A%u", 0, 15)), 0>;
339+
(add (sequence "A%u", 0, 15)), [], 0>;
314340

315341
// Control registers.
316342
class CREG64<bits<16> num, string n> : SystemZReg<n> {
@@ -320,5 +346,4 @@ foreach I = 0-15 in {
320346
def C#I : CREG64<I, "c"#I>, DwarfRegNum<[!add(I, 32)]>;
321347
}
322348
defm CR64 : SystemZRegClass<"CR64", [i64], 64,
323-
(add (sequence "C%u", 0, 15)), 0>;
324-
349+
(add (sequence "C%u", 0, 15)), [], 0>;

llvm/lib/Target/SystemZ/SystemZScheduleZ13.td

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,8 +167,8 @@ def : InstRW<[WLat1, FXb, LSU, NormalGr], (instregex "CL(G)?T(Asm.*)?$")>;
167167

168168
// Call
169169
def : InstRW<[WLat1, VBU, FXa2, GroupAlone], (instregex "(Call)?BRAS$")>;
170-
def : InstRW<[WLat1, FXa2, FXb, GroupAlone], (instregex "(Call)?BRASL$")>;
171-
def : InstRW<[WLat1, FXa2, FXb, GroupAlone], (instregex "(Call)?BAS(R)?$")>;
170+
def : InstRW<[WLat1, FXa2, FXb, GroupAlone], (instregex "(Call)?BRASL(_XPLINK64)?$")>;
171+
def : InstRW<[WLat1, FXa2, FXb, GroupAlone], (instregex "(Call)?BAS(R)?(_XPLINK64)?$")>;
172172
def : InstRW<[WLat1, FXa2, FXb, GroupAlone], (instregex "TLS_(G|L)DCALL$")>;
173173

174174
// Return

llvm/lib/Target/SystemZ/SystemZScheduleZ14.td

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,8 +168,8 @@ def : InstRW<[WLat1, FXb, LSU, NormalGr], (instregex "CL(G)?T(Asm.*)?$")>;
168168

169169
// Call
170170
def : InstRW<[WLat1, VBU, FXa2, GroupAlone], (instregex "(Call)?BRAS$")>;
171-
def : InstRW<[WLat1, FXa2, FXb, GroupAlone], (instregex "(Call)?BRASL$")>;
172-
def : InstRW<[WLat1, FXa2, FXb, GroupAlone], (instregex "(Call)?BAS(R)?$")>;
171+
def : InstRW<[WLat1, FXa2, FXb, GroupAlone], (instregex "(Call)?BRASL(_XPLINK64)?$")>;
172+
def : InstRW<[WLat1, FXa2, FXb, GroupAlone], (instregex "(Call)?BAS(R)?(_XPLINK64)?$")>;
173173
def : InstRW<[WLat1, FXa2, FXb, GroupAlone], (instregex "TLS_(G|L)DCALL$")>;
174174

175175
// Return

llvm/lib/Target/SystemZ/SystemZScheduleZ15.td

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,8 +168,8 @@ def : InstRW<[WLat1, FXb, LSU, NormalGr], (instregex "CL(G)?T(Asm.*)?$")>;
168168

169169
// Call
170170
def : InstRW<[WLat1, VBU, FXa2, GroupAlone], (instregex "(Call)?BRAS$")>;
171-
def : InstRW<[WLat1, FXa2, FXb, GroupAlone], (instregex "(Call)?BRASL$")>;
172-
def : InstRW<[WLat1, FXa2, FXb, GroupAlone], (instregex "(Call)?BAS(R)?$")>;
171+
def : InstRW<[WLat1, FXa2, FXb, GroupAlone], (instregex "(Call)?BRASL(_XPLINK64)?$")>;
172+
def : InstRW<[WLat1, FXa2, FXb, GroupAlone], (instregex "(Call)?BAS(R)?(_XPLINK64)?$")>;
173173
def : InstRW<[WLat1, FXa2, FXb, GroupAlone], (instregex "TLS_(G|L)DCALL$")>;
174174

175175
// Return

llvm/lib/Target/SystemZ/SystemZScheduleZ196.td

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,8 +146,8 @@ def : InstRW<[WLat1, FXU, NormalGr], (instregex "CL(F|G)IT(Asm.*)?$")>;
146146

147147
// Call
148148
def : InstRW<[WLat1, LSU, FXU2, GroupAlone], (instregex "(Call)?BRAS$")>;
149-
def : InstRW<[WLat1, LSU, FXU2, GroupAlone], (instregex "(Call)?BRASL$")>;
150-
def : InstRW<[WLat1, LSU, FXU2, GroupAlone], (instregex "(Call)?BAS(R)?$")>;
149+
def : InstRW<[WLat1, LSU, FXU2, GroupAlone], (instregex "(Call)?BRASL(_XPLINK64)?$")>;
150+
def : InstRW<[WLat1, LSU, FXU2, GroupAlone], (instregex "(Call)?BAS(R)?(_XPLINK64)?$")>;
151151
def : InstRW<[WLat1, LSU, FXU2, GroupAlone], (instregex "TLS_(G|L)DCALL$")>;
152152

153153
// Return

llvm/lib/Target/SystemZ/SystemZScheduleZEC12.td

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,8 +151,8 @@ def : InstRW<[WLat1, FXU, LSU, NormalGr], (instregex "CL(G)?T(Asm.*)?$")>;
151151

152152
// Call
153153
def : InstRW<[WLat1, FXU2, VBU, GroupAlone], (instregex "(Call)?BRAS$")>;
154-
def : InstRW<[WLat1, FXU2, LSU, GroupAlone], (instregex "(Call)?BRASL$")>;
155-
def : InstRW<[WLat1, FXU2, LSU, GroupAlone], (instregex "(Call)?BAS(R)?$")>;
154+
def : InstRW<[WLat1, FXU2, LSU, GroupAlone], (instregex "(Call)?BRASL(_XPLINK64)?$")>;
155+
def : InstRW<[WLat1, FXU2, LSU, GroupAlone], (instregex "(Call)?BAS(R)?(_XPLINK64)?$")>;
156156
def : InstRW<[WLat1, FXU2, LSU, GroupAlone], (instregex "TLS_(G|L)DCALL$")>;
157157

158158
// Return

llvm/lib/Target/SystemZ/SystemZSubtarget.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,15 @@ class SystemZSubtarget : public SystemZGenSubtargetInfo {
248248
bool isPC32DBLSymbol(const GlobalValue *GV, CodeModel::Model CM) const;
249249

250250
bool isTargetELF() const { return TargetTriple.isOSBinFormatELF(); }
251+
252+
// Returns TRUE if we are generating GOFF object code
253+
bool isTargetGOFF() const { return TargetTriple.isOSBinFormatGOFF(); }
254+
255+
// Returns TRUE if we are using XPLINK64 linkage convention
256+
bool isTargetXPLINK64() const { return (isTargetGOFF() && isTargetzOS()); }
257+
258+
// Returns TRUE if we are generating code for a s390x machine running zOS
259+
bool isTargetzOS() const { return TargetTriple.isOSzOS(); }
251260
};
252261
} // end namespace llvm
253262

0 commit comments

Comments
 (0)