Skip to content

Commit 4a37799

Browse files
authored
[SystemZ][XRay] Implement XRay instrumentation for SystemZ (#113253)
Expands pseudo instructions PATCHABLE_FUNCTION_ENTER and PATCHABLE_RET into a small instruction sequence which calls into the XRay library.
1 parent db1882e commit 4a37799

File tree

6 files changed

+161
-1
lines changed

6 files changed

+161
-1
lines changed

llvm/lib/CodeGen/XRayInstrumentation.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,8 @@ bool XRayInstrumentation::runOnMachineFunction(MachineFunction &MF) {
241241
prependRetWithPatchableExit(MF, TII, op);
242242
break;
243243
}
244-
case Triple::ArchType::ppc64le: {
244+
case Triple::ArchType::ppc64le:
245+
case Triple::ArchType::systemz: {
245246
// PPC has conditional returns. Turn them into branch and plain returns.
246247
InstrumentationOptions op;
247248
op.HandleTailcall = false;

llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "MCTargetDesc/SystemZGNUInstPrinter.h"
1616
#include "MCTargetDesc/SystemZHLASMInstPrinter.h"
1717
#include "MCTargetDesc/SystemZMCExpr.h"
18+
#include "MCTargetDesc/SystemZMCTargetDesc.h"
1819
#include "SystemZConstantPoolValue.h"
1920
#include "SystemZMCInstLower.h"
2021
#include "TargetInfo/SystemZTargetInfo.h"
@@ -662,6 +663,23 @@ void SystemZAsmPrinter::emitInstruction(const MachineInstr *MI) {
662663
LowerPATCHPOINT(*MI, Lower);
663664
return;
664665

666+
case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
667+
LowerPATCHABLE_FUNCTION_ENTER(*MI, Lower);
668+
return;
669+
670+
case TargetOpcode::PATCHABLE_RET:
671+
LowerPATCHABLE_RET(*MI, Lower);
672+
return;
673+
674+
case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
675+
llvm_unreachable("PATCHABLE_FUNCTION_EXIT should never be emitted");
676+
677+
case TargetOpcode::PATCHABLE_TAIL_CALL:
678+
// TODO: Define a trampoline `__xray_FunctionTailExit` and differentiate a
679+
// normal function exit from a tail exit.
680+
llvm_unreachable("Tail call is handled in the normal case. See comments "
681+
"around this assert.");
682+
665683
case SystemZ::EXRL_Pseudo: {
666684
unsigned TargetInsOpc = MI->getOperand(0).getImm();
667685
Register LenMinus1Reg = MI->getOperand(1).getReg();
@@ -844,6 +862,84 @@ void SystemZAsmPrinter::LowerPATCHPOINT(const MachineInstr &MI,
844862
getSubtargetInfo());
845863
}
846864

865+
void SystemZAsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(
866+
const MachineInstr &MI, SystemZMCInstLower &Lower) {
867+
// .begin:
868+
// j .end # -> stmg %r2, %r15, 16(%r15)
869+
// nop
870+
// llilf %2, FuncID
871+
// brasl %r14, __xray_FunctionEntry@GOT
872+
// .end:
873+
//
874+
// Update compiler-rt/lib/xray/xray_s390x.cpp accordingly when number
875+
// of instructions change.
876+
bool HasVectorFeature =
877+
TM.getMCSubtargetInfo()->hasFeature(SystemZ::FeatureVector) &&
878+
!TM.getMCSubtargetInfo()->hasFeature(SystemZ::FeatureSoftFloat);
879+
MCSymbol *FuncEntry = OutContext.getOrCreateSymbol(
880+
HasVectorFeature ? "__xray_FunctionEntryVec" : "__xray_FunctionEntry");
881+
MCSymbol *BeginOfSled = OutContext.createTempSymbol("xray_sled_", true);
882+
MCSymbol *EndOfSled = OutContext.createTempSymbol();
883+
OutStreamer->emitLabel(BeginOfSled);
884+
EmitToStreamer(*OutStreamer,
885+
MCInstBuilder(SystemZ::J)
886+
.addExpr(MCSymbolRefExpr::create(EndOfSled, OutContext)));
887+
EmitNop(OutContext, *OutStreamer, 2, getSubtargetInfo());
888+
EmitToStreamer(*OutStreamer,
889+
MCInstBuilder(SystemZ::LLILF).addReg(SystemZ::R2D).addImm(0));
890+
EmitToStreamer(*OutStreamer,
891+
MCInstBuilder(SystemZ::BRASL)
892+
.addReg(SystemZ::R14D)
893+
.addExpr(MCSymbolRefExpr::create(
894+
FuncEntry, MCSymbolRefExpr::VK_PLT, OutContext)));
895+
OutStreamer->emitLabel(EndOfSled);
896+
recordSled(BeginOfSled, MI, SledKind::FUNCTION_ENTER, 2);
897+
}
898+
899+
void SystemZAsmPrinter::LowerPATCHABLE_RET(const MachineInstr &MI,
900+
SystemZMCInstLower &Lower) {
901+
unsigned OpCode = MI.getOperand(0).getImm();
902+
MCSymbol *FallthroughLabel = nullptr;
903+
if (OpCode == SystemZ::CondReturn) {
904+
FallthroughLabel = OutContext.createTempSymbol();
905+
int64_t Cond0 = MI.getOperand(1).getImm();
906+
int64_t Cond1 = MI.getOperand(2).getImm();
907+
EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BRC)
908+
.addImm(Cond0)
909+
.addImm(Cond1 ^ Cond0)
910+
.addExpr(MCSymbolRefExpr::create(
911+
FallthroughLabel, OutContext)));
912+
}
913+
// .begin:
914+
// br %r14 # -> stmg %r2, %r15, 24(%r15)
915+
// nop
916+
// nop
917+
// llilf %2,FuncID
918+
// j __xray_FunctionExit@GOT
919+
//
920+
// Update compiler-rt/lib/xray/xray_s390x.cpp accordingly when number
921+
// of instructions change.
922+
bool HasVectorFeature =
923+
TM.getMCSubtargetInfo()->hasFeature(SystemZ::FeatureVector) &&
924+
!TM.getMCSubtargetInfo()->hasFeature(SystemZ::FeatureSoftFloat);
925+
MCSymbol *FuncExit = OutContext.getOrCreateSymbol(
926+
HasVectorFeature ? "__xray_FunctionExitVec" : "__xray_FunctionExit");
927+
MCSymbol *BeginOfSled = OutContext.createTempSymbol("xray_sled_", true);
928+
OutStreamer->emitLabel(BeginOfSled);
929+
EmitToStreamer(*OutStreamer,
930+
MCInstBuilder(SystemZ::BR).addReg(SystemZ::R14D));
931+
EmitNop(OutContext, *OutStreamer, 4, getSubtargetInfo());
932+
EmitToStreamer(*OutStreamer,
933+
MCInstBuilder(SystemZ::LLILF).addReg(SystemZ::R2D).addImm(0));
934+
EmitToStreamer(*OutStreamer,
935+
MCInstBuilder(SystemZ::J)
936+
.addExpr(MCSymbolRefExpr::create(
937+
FuncExit, MCSymbolRefExpr::VK_PLT, OutContext)));
938+
if (FallthroughLabel)
939+
OutStreamer->emitLabel(FallthroughLabel);
940+
recordSled(BeginOfSled, MI, SledKind::FUNCTION_EXIT, 2);
941+
}
942+
847943
// The *alignment* of 128-bit vector types is different between the software
848944
// and hardware vector ABIs. If the there is an externally visible use of a
849945
// vector type in the module it should be annotated with an attribute.

llvm/lib/Target/SystemZ/SystemZAsmPrinter.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,15 @@ class LLVM_LIBRARY_VISIBILITY SystemZAsmPrinter : public AsmPrinter {
111111
bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
112112
const char *ExtraCode, raw_ostream &OS) override;
113113

114+
bool runOnMachineFunction(MachineFunction &MF) override {
115+
AsmPrinter::runOnMachineFunction(MF);
116+
117+
// Emit the XRay table for this function.
118+
emitXRayTable();
119+
120+
return false;
121+
}
122+
114123
bool doInitialization(Module &M) override {
115124
SM.reset();
116125
return AsmPrinter::doInitialization(M);
@@ -124,6 +133,9 @@ class LLVM_LIBRARY_VISIBILITY SystemZAsmPrinter : public AsmPrinter {
124133
void LowerFENTRY_CALL(const MachineInstr &MI, SystemZMCInstLower &MCIL);
125134
void LowerSTACKMAP(const MachineInstr &MI);
126135
void LowerPATCHPOINT(const MachineInstr &MI, SystemZMCInstLower &Lower);
136+
void LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI,
137+
SystemZMCInstLower &Lower);
138+
void LowerPATCHABLE_RET(const MachineInstr &MI, SystemZMCInstLower &Lower);
127139
void emitAttributes(Module &M);
128140
};
129141
} // end namespace llvm

llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "llvm/CodeGen/SlotIndexes.h"
3131
#include "llvm/CodeGen/StackMaps.h"
3232
#include "llvm/CodeGen/TargetInstrInfo.h"
33+
#include "llvm/CodeGen/TargetOpcodes.h"
3334
#include "llvm/CodeGen/TargetSubtargetInfo.h"
3435
#include "llvm/CodeGen/VirtRegMap.h"
3536
#include "llvm/MC/MCInstrDesc.h"
@@ -1792,6 +1793,10 @@ unsigned SystemZInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
17921793
return MI.getOperand(1).getImm();
17931794
else if (MI.getOpcode() == SystemZ::FENTRY_CALL)
17941795
return 6;
1796+
if (MI.getOpcode() == TargetOpcode::PATCHABLE_FUNCTION_ENTER)
1797+
return 18;
1798+
if (MI.getOpcode() == TargetOpcode::PATCHABLE_RET)
1799+
return 18 + (MI.getOperand(0).getImm() == SystemZ::CondReturn ? 4 : 0);
17951800

17961801
return MI.getDesc().getSize();
17971802
}

llvm/lib/Target/SystemZ/SystemZSubtarget.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ class SystemZSubtarget : public SystemZGenSubtargetInfo {
106106
bool GETTER() const { return ATTRIBUTE; }
107107
#include "SystemZGenSubtargetInfo.inc"
108108

109+
bool isXRaySupported() const override { return true; }
110+
109111
bool isAddressedViaADA(const GlobalValue *GV) const;
110112

111113
// Return true if GV can be accessed using LARL for reloc model RM

llvm/test/CodeGen/SystemZ/xray.ll

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck --check-prefixes=CHECK,NOVECTOR %s
2+
; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z15 | FileCheck --check-prefixes=CHECK,VECTOR %s
3+
; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z15 -mattr=+soft-float | FileCheck --check-prefixes=CHECK,NOVECTOR %s
4+
5+
6+
define signext i32 @foo() "function-instrument"="xray-always" {
7+
; CHECK-LABEL: .Lxray_sled_0:
8+
; CHECK: j .Ltmp[[#l:]]
9+
; CHECK: bcr 0, %r0
10+
; CHECK: llilf %r2, 0
11+
; NOVECTOR: brasl %r14, __xray_FunctionEntry@PLT
12+
; VECTOR: brasl %r14, __xray_FunctionEntryVec@PLT
13+
; CHECK: .Ltmp[[#l]]:
14+
ret i32 0
15+
; CHECK-LABEL: .Lxray_sled_1:
16+
; CHECK: br %r14
17+
; CHECK: bc 0, 0
18+
; CHECK: llilf %r2, 0
19+
; NOVECtOR: j __xray_FunctionExit@PLT
20+
; VECTOR: j __xray_FunctionExitVec@PLT
21+
}
22+
23+
; CHECK: .section xray_instr_map,"ao",@progbits,foo
24+
; CHECK: .Lxray_sleds_start0:
25+
; CHECK: [[TMP1:.Ltmp[0-9]+]]:
26+
; CHECK: .quad .Lxray_sled_0-[[TMP1]]
27+
; CHECK: .quad .Lfunc_begin0-([[TMP1]]+8)
28+
; CHECK: .byte 0x00
29+
; CHECK: .byte 0x01
30+
; CHECK: .byte 0x02
31+
; CHECK: .space 13
32+
; CHECK: [[TMP2:.Ltmp[0-9]+]]:
33+
; CHECK: .quad .Lxray_sled_1-[[TMP2]]
34+
; CHECK: .quad .Lfunc_begin0-([[TMP2]]+8)
35+
; CHECK: .byte 0x01
36+
; CHECK: .byte 0x01
37+
; CHECK: .byte 0x02
38+
; CHECK: .space 13
39+
; CHECK: .Lxray_sleds_end0:
40+
; CHECK: .section xray_fn_idx,"ao",@progbits,foo
41+
; CHECK: .p2align 4
42+
; CHECK: .Lxray_fn_idx0:
43+
; CHECK: .quad .Lxray_sleds_start0-.Lxray_fn_idx0
44+
; CHECK: .quad 2

0 commit comments

Comments
 (0)