[compiler-rt] [llvm] [Hexagon] Add XRay custom and typed event support (PR #191749)
via llvm-commits
llvm-commits at lists.llvm.org
Sun Apr 12 19:05:45 PDT 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-selectiondag
@llvm/pr-subscribers-xray
@llvm/pr-subscribers-backend-hexagon
Author: Brian Cain (androm3da)
<details>
<summary>Changes</summary>
Add support for XRay custom events (llvm.xray.customevent) and typed events (llvm.xray.typedevent) for Hexagon.
LLVM:
* Add Hexagon to the architecture gate in SelectionDAGBuilder for xray_customevent and xray_typedevent intrinsic lowering
* Implement EmitInstrWithCustomInserter for PATCHABLE_EVENT_CALL and PATCHABLE_TYPED_EVENT_CALL pseudo instructions
* Implement LowerPATCHABLE_EVENT_CALL in HexagonAsmPrinter that emits inline sleds with jump-over, allocframe/deallocframe for LR:FP save, argument register save/restore, and call to the event handler
* Add event pseudo dispatch in HexagonMCInstLower
* Prevent event pseudos from being packetized (solo instructions)
compiler-rt:
* Implement patchCustomEvent and patchTypedEvent in xray_hexagon.cpp to patch the sled jump to nop (enable) or back (disable)
* Add __xray_CustomEvent and __xray_TypedEvent trampolines in the Hexagon XRay trampoline assembly
---
Patch is 20.31 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/191749.diff
10 Files Affected:
- (modified) compiler-rt/lib/xray/xray_hexagon.cpp (+32-3)
- (modified) compiler-rt/lib/xray/xray_trampoline_hexagon.S (+50-12)
- (modified) llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp (+4-2)
- (modified) llvm/lib/Target/Hexagon/HexagonAsmPrinter.cpp (+175)
- (modified) llvm/lib/Target/Hexagon/HexagonAsmPrinter.h (+1)
- (modified) llvm/lib/Target/Hexagon/HexagonISelLowering.cpp (+12)
- (modified) llvm/lib/Target/Hexagon/HexagonISelLowering.h (+4)
- (modified) llvm/lib/Target/Hexagon/HexagonMCInstLower.cpp (+8)
- (modified) llvm/lib/Target/Hexagon/HexagonVLIWPacketizer.cpp (+3-1)
- (added) llvm/test/CodeGen/Hexagon/xray-custom-event.ll (+83)
``````````diff
diff --git a/compiler-rt/lib/xray/xray_hexagon.cpp b/compiler-rt/lib/xray/xray_hexagon.cpp
index b299f03d6daad..3e56a4d5ce7b9 100644
--- a/compiler-rt/lib/xray/xray_hexagon.cpp
+++ b/compiler-rt/lib/xray/xray_hexagon.cpp
@@ -20,8 +20,15 @@
namespace __xray {
// The machine codes for some instructions used in runtime patching.
+//
+// J2_jump encoding: bits [27:16] and [13:1] hold the PC-relative byte offset
+// divided by 4, with bits [15:14] = 0b11 for packet-end parse bits.
+// Formula: 0x5800c000 | ((ByteOffset >> 2) << 1)
enum PatchOpcodes : uint32_t {
- PO_JUMPI_1C = 0x5800c00e, // jump #0x01c (PC + 0x01c)
+ PO_JUMPI_1C = 0x5800c00e, // jump #0x01c (entry/exit sled, 28 bytes)
+ PO_JUMPI_30 = 0x5800c018, // jump #0x030 (custom event sled, 48 bytes)
+ PO_JUMPI_3C = 0x5800c01e, // jump #0x03c (typed event sled, 60 bytes)
+ PO_NOP = 0x7f00c000, // { nop } with packet-end parse bits
PO_CALLR_R6 = 0x50a6c000, // indirect call: callr r6
PO_TFR_IMM = 0x78000000, // transfer immed
// ICLASS 0x7 - S2-type A-type
@@ -176,13 +183,35 @@ bool patchFunctionTailExit(
bool patchCustomEvent(const bool Enable, const uint32_t FuncId,
const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT {
- // FIXME: Implement in hexagon?
+ // The custom event sled (2 args) is 12 words = 48 bytes:
+ // .Lxray_sled_N:
+ // { jump .Lend } <-- first word: jump over (disabled) / nop (enabled)
+ // allocframe, sp adjust, 2 saves, 2 moves, call, 2 restores,
+ // sp adjust, deallocframe
+ // .Lend:
+ uint32_t *FirstAddress = reinterpret_cast<uint32_t *>(Sled.address());
+ if (Enable) {
+ WriteInstFlushCache(FirstAddress, uint32_t(PO_NOP));
+ } else {
+ WriteInstFlushCache(FirstAddress, uint32_t(PO_JUMPI_30));
+ }
return false;
}
bool patchTypedEvent(const bool Enable, const uint32_t FuncId,
const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT {
- // FIXME: Implement in hexagon?
+ // The typed event sled (3 args) is 15 words = 60 bytes:
+ // .Lxray_sled_N:
+ // { jump .Lend } <-- first word: jump over (disabled) / nop (enabled)
+ // allocframe, sp adjust, 3 saves, 3 moves, call, 3 restores,
+ // sp adjust, deallocframe
+ // .Lend:
+ uint32_t *FirstAddress = reinterpret_cast<uint32_t *>(Sled.address());
+ if (Enable) {
+ WriteInstFlushCache(FirstAddress, uint32_t(PO_NOP));
+ } else {
+ WriteInstFlushCache(FirstAddress, uint32_t(PO_JUMPI_3C));
+ }
return false;
}
diff --git a/compiler-rt/lib/xray/xray_trampoline_hexagon.S b/compiler-rt/lib/xray/xray_trampoline_hexagon.S
index a7ba7c6b889a9..b9d2f1f2293e4 100644
--- a/compiler-rt/lib/xray/xray_trampoline_hexagon.S
+++ b/compiler-rt/lib/xray/xray_trampoline_hexagon.S
@@ -33,9 +33,7 @@
// sp+#20: r5 (parameter)
// sp+#24: r31 (return address back to sled's deallocframe)
// sp+#28: (padding for 8-byte alignment)
- {
- sp = add(sp, #-32)
- }
+ sp = add(sp, #-32)
memw(sp+#0) = r0
memw(sp+#4) = r1
memw(sp+#8) = r2
@@ -53,18 +51,14 @@
r4 = memw(sp+#16)
r5 = memw(sp+#20)
r31 = memw(sp+#24)
- {
- sp = add(sp, #32)
- }
+ sp = add(sp, #32)
.endm
.macro CALL_PATCHED_FUNC entry_type
// Load the address of the global handler function pointer,
// then dereference it to get the actual handler.
r8 = ##ASM_SYMBOL(_ZN6__xray19XRayPatchedFunctionE)
- {
- r8 = memw(r8+#0)
- }
+ r8 = memw(r8+#0)
// Skip if handler is not registered (null).
{
p0 = cmp.eq(r8, #0)
@@ -77,9 +71,7 @@
r0 = r7
r1 = \entry_type
}
- {
- callr r8
- }
+ callr r8
0:
.endm
@@ -128,4 +120,50 @@ ASM_SYMBOL(__xray_FunctionTailExit):
ASM_SIZE(__xray_FunctionTailExit)
CFI_ENDPROC
+// __xray_*Event have default visibility so that they can be referenced by user
+// DSOs that do not link against the runtime.
+
+ .globl ASM_SYMBOL(__xray_CustomEvent)
+ ASM_TYPE_FUNCTION(__xray_CustomEvent)
+ASM_SYMBOL(__xray_CustomEvent):
+ CFI_STARTPROC
+ SAVE_REGISTERS
+
+ // Arguments (r0=ptr, r1=size) are already set by the inline sled.
+ // Load the handler address.
+ r8 = ##ASM_SYMBOL(_ZN6__xray22XRayPatchedCustomEventE)
+ r8 = memw(r8+#0)
+ {
+ p0 = cmp.eq(r8, #0)
+ if (p0.new) jump:nt 0f
+ }
+ callr r8
+0:
+ RESTORE_REGISTERS
+ jumpr r31
+ ASM_SIZE(__xray_CustomEvent)
+ CFI_ENDPROC
+
+
+ .globl ASM_SYMBOL(__xray_TypedEvent)
+ ASM_TYPE_FUNCTION(__xray_TypedEvent)
+ASM_SYMBOL(__xray_TypedEvent):
+ CFI_STARTPROC
+ SAVE_REGISTERS
+
+ // Arguments (r0=type, r1=ptr, r2=size) are already set by the inline sled.
+ // Load the handler address.
+ r8 = ##ASM_SYMBOL(_ZN6__xray21XRayPatchedTypedEventE)
+ r8 = memw(r8+#0)
+ {
+ p0 = cmp.eq(r8, #0)
+ if (p0.new) jump:nt 0f
+ }
+ callr r8
+0:
+ RESTORE_REGISTERS
+ jumpr r31
+ ASM_SIZE(__xray_TypedEvent)
+ CFI_ENDPROC
+
NO_EXEC_STACK_DIRECTIVE
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 1f3b099c9c577..6ae97acb7f21c 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -7966,7 +7966,8 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
// Here we want to make sure that the intrinsic behaves as if it has a
// specific calling convention.
const auto &Triple = DAG.getTarget().getTargetTriple();
- if (!Triple.isAArch64(64) && Triple.getArch() != Triple::x86_64)
+ if (!Triple.isAArch64(64) && Triple.getArch() != Triple::x86_64 &&
+ Triple.getArch() != Triple::hexagon)
return;
SmallVector<SDValue, 8> Ops;
@@ -7995,7 +7996,8 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
// Here we want to make sure that the intrinsic behaves as if it has a
// specific calling convention.
const auto &Triple = DAG.getTarget().getTargetTriple();
- if (!Triple.isAArch64(64) && Triple.getArch() != Triple::x86_64)
+ if (!Triple.isAArch64(64) && Triple.getArch() != Triple::x86_64 &&
+ Triple.getArch() != Triple::hexagon)
return;
SmallVector<SDValue, 8> Ops;
diff --git a/llvm/lib/Target/Hexagon/HexagonAsmPrinter.cpp b/llvm/lib/Target/Hexagon/HexagonAsmPrinter.cpp
index a83a221b1a9b1..2ed5f9b774f83 100644
--- a/llvm/lib/Target/Hexagon/HexagonAsmPrinter.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonAsmPrinter.cpp
@@ -801,6 +801,181 @@ void HexagonAsmPrinter::emitAttributes() {
HTS.emitTargetAttributes(*TM.getMCSubtargetInfo());
}
+void HexagonAsmPrinter::LowerPATCHABLE_EVENT_CALL(const MachineInstr &MI,
+ bool Typed) {
+ auto &O = *OutStreamer;
+ MCSymbol *CurSled = OutContext.createTempSymbol("xray_sled_", true);
+ O.emitLabel(CurSled);
+
+ auto *Sym = MCSymbolRefExpr::create(
+ OutContext.getOrCreateSymbol(Typed ? "__xray_TypedEvent"
+ : "__xray_CustomEvent"),
+ OutContext);
+
+ // The sled structure:
+ // .Lxray_sled_N:
+ // { jump .Lend } -- disabled (patched to nop when enabled)
+ // <save args, move operands, call handler, restore args>
+ // .Lend:
+
+ MCSymbol *EndSled = OutContext.createTempSymbol();
+
+ // Packet 1: jump over the sled (disabled state).
+ MCInst *JumpInst = OutContext.createMCInst();
+ JumpInst->setOpcode(Hexagon::J2_jump);
+ JumpInst->addOperand(MCOperand::createExpr(HexagonMCExpr::create(
+ MCSymbolRefExpr::create(EndSled, OutContext), OutContext)));
+
+ MCInst JumpPacket;
+ JumpPacket.setOpcode(Hexagon::BUNDLE);
+ JumpPacket.addOperand(MCOperand::createImm(0));
+ JumpPacket.addOperand(MCOperand::createInst(JumpInst));
+ EmitToStreamer(O, JumpPacket);
+
+ // Packet 2: allocframe to save LR:FP.
+ MCInst *AllocInst = OutContext.createMCInst();
+ AllocInst->setOpcode(Hexagon::S2_allocframe);
+ AllocInst->addOperand(MCOperand::createReg(Hexagon::R29));
+ AllocInst->addOperand(MCOperand::createReg(Hexagon::R30));
+ AllocInst->addOperand(MCOperand::createExpr(HexagonMCExpr::create(
+ MCConstantExpr::create(0, OutContext), OutContext)));
+
+ MCInst AllocPacket;
+ AllocPacket.setOpcode(Hexagon::BUNDLE);
+ AllocPacket.addOperand(MCOperand::createImm(0));
+ AllocPacket.addOperand(MCOperand::createInst(AllocInst));
+ EmitToStreamer(O, AllocPacket);
+
+ // Save argument registers and set up call arguments.
+ // Custom event: 2 operands (ptr, size) in MI operands 0,1 -> r0, r1
+ // Typed event: 3 operands (type, ptr, size) in MI operands 0,1,2 ->
+ // r0,r1,r2
+ unsigned NumArgs = Typed ? 3 : 2;
+
+ // Save the original argument registers onto the stack.
+ // Packet 3: Allocate space and save r0.
+ MCInst *SubSpInst = OutContext.createMCInst();
+ SubSpInst->setOpcode(Hexagon::A2_addi);
+ SubSpInst->addOperand(MCOperand::createReg(Hexagon::R29));
+ SubSpInst->addOperand(MCOperand::createReg(Hexagon::R29));
+ SubSpInst->addOperand(MCOperand::createExpr(HexagonMCExpr::create(
+ MCConstantExpr::create(-(int64_t)(NumArgs * 4), OutContext),
+ OutContext)));
+
+ MCInst SubSpPacket;
+ SubSpPacket.setOpcode(Hexagon::BUNDLE);
+ SubSpPacket.addOperand(MCOperand::createImm(0));
+ SubSpPacket.addOperand(MCOperand::createInst(SubSpInst));
+ EmitToStreamer(O, SubSpPacket);
+
+ // Save each argument register.
+ for (unsigned I = 0; I < NumArgs; ++I) {
+ MCInst *StoreInst = OutContext.createMCInst();
+ StoreInst->setOpcode(Hexagon::S2_storeri_io);
+ StoreInst->addOperand(MCOperand::createReg(Hexagon::R29));
+ StoreInst->addOperand(MCOperand::createExpr(HexagonMCExpr::create(
+ MCConstantExpr::create(I * 4, OutContext), OutContext)));
+ StoreInst->addOperand(MCOperand::createReg(Hexagon::R0 + I));
+
+ MCInst StorePacket;
+ StorePacket.setOpcode(Hexagon::BUNDLE);
+ StorePacket.addOperand(MCOperand::createImm(0));
+ StorePacket.addOperand(MCOperand::createInst(StoreInst));
+ EmitToStreamer(O, StorePacket);
+ }
+
+ // Move operands into argument registers (r0, r1, [r2]).
+ // The XRay intrinsic uses i64 for size (and type) parameters. On 32-bit
+ // Hexagon these are in DoubleRegs (register pairs). The runtime handler
+ // expects 32-bit arguments, so extract the low sub-register.
+ //
+ // NOTE: Moves are always emitted (even identity moves like r0 = r0) so that
+ // the sled has a fixed size. The runtime patching code relies on the sled
+ // being a known number of words to encode the correct jump offset for the
+ // disabled state.
+ //
+ // NOTE: When source registers alias destination registers in a conflicting
+ // order (e.g., src0 in r1 and src1 in r0), the sequential moves can produce
+ // incorrect results. This is the same limitation as AArch64's implementation
+ // and is unlikely in practice since the register allocator rarely produces
+ // such assignments for XRay event intrinsics.
+ const auto &HRI = *MF->getSubtarget<HexagonSubtarget>().getRegisterInfo();
+ for (unsigned I = 0; I < NumArgs; ++I) {
+ Register SrcReg = MI.getOperand(I).getReg();
+ if (Hexagon::DoubleRegsRegClass.contains(SrcReg))
+ SrcReg = HRI.getSubReg(SrcReg, Hexagon::isub_lo);
+
+ MCInst *MovInst = OutContext.createMCInst();
+ MovInst->setOpcode(Hexagon::A2_tfr);
+ MovInst->addOperand(MCOperand::createReg(Hexagon::R0 + I));
+ MovInst->addOperand(MCOperand::createReg(SrcReg));
+
+ MCInst MovPacket;
+ MovPacket.setOpcode(Hexagon::BUNDLE);
+ MovPacket.addOperand(MCOperand::createImm(0));
+ MovPacket.addOperand(MCOperand::createInst(MovInst));
+ EmitToStreamer(O, MovPacket);
+ }
+
+ // Call the handler.
+ MCInst *CallInst = OutContext.createMCInst();
+ CallInst->setOpcode(Hexagon::J2_call);
+ CallInst->addOperand(
+ MCOperand::createExpr(HexagonMCExpr::create(Sym, OutContext)));
+
+ MCInst CallPacket;
+ CallPacket.setOpcode(Hexagon::BUNDLE);
+ CallPacket.addOperand(MCOperand::createImm(0));
+ CallPacket.addOperand(MCOperand::createInst(CallInst));
+ EmitToStreamer(O, CallPacket);
+
+ // Restore argument registers.
+ for (unsigned I = 0; I < NumArgs; ++I) {
+ MCInst *LoadInst = OutContext.createMCInst();
+ LoadInst->setOpcode(Hexagon::L2_loadri_io);
+ LoadInst->addOperand(MCOperand::createReg(Hexagon::R0 + I));
+ LoadInst->addOperand(MCOperand::createReg(Hexagon::R29));
+ LoadInst->addOperand(MCOperand::createExpr(HexagonMCExpr::create(
+ MCConstantExpr::create(I * 4, OutContext), OutContext)));
+
+ MCInst LoadPacket;
+ LoadPacket.setOpcode(Hexagon::BUNDLE);
+ LoadPacket.addOperand(MCOperand::createImm(0));
+ LoadPacket.addOperand(MCOperand::createInst(LoadInst));
+ EmitToStreamer(O, LoadPacket);
+ }
+
+ // Deallocate saved argument space.
+ MCInst *AddSpInst = OutContext.createMCInst();
+ AddSpInst->setOpcode(Hexagon::A2_addi);
+ AddSpInst->addOperand(MCOperand::createReg(Hexagon::R29));
+ AddSpInst->addOperand(MCOperand::createReg(Hexagon::R29));
+ AddSpInst->addOperand(MCOperand::createExpr(HexagonMCExpr::create(
+ MCConstantExpr::create(NumArgs * 4, OutContext), OutContext)));
+
+ MCInst AddSpPacket;
+ AddSpPacket.setOpcode(Hexagon::BUNDLE);
+ AddSpPacket.addOperand(MCOperand::createImm(0));
+ AddSpPacket.addOperand(MCOperand::createInst(AddSpInst));
+ EmitToStreamer(O, AddSpPacket);
+
+ // Deallocframe to restore LR:FP.
+ MCInst *DeallocInst = OutContext.createMCInst();
+ DeallocInst->setOpcode(Hexagon::L2_deallocframe);
+ DeallocInst->addOperand(MCOperand::createReg(Hexagon::D15));
+ DeallocInst->addOperand(MCOperand::createReg(Hexagon::R30));
+
+ MCInst DeallocPacket;
+ DeallocPacket.setOpcode(Hexagon::BUNDLE);
+ DeallocPacket.addOperand(MCOperand::createImm(0));
+ DeallocPacket.addOperand(MCOperand::createInst(DeallocInst));
+ EmitToStreamer(O, DeallocPacket);
+
+ OutStreamer->emitLabel(EndSled);
+ recordSled(CurSled, MI,
+ Typed ? SledKind::TYPED_EVENT : SledKind::CUSTOM_EVENT, 2);
+}
+
void HexagonAsmPrinter::EmitSled(const MachineInstr &MI, SledKind Kind) {
static const int8_t NoopsInSledCount = 6;
// We want to emit the following pattern:
diff --git a/llvm/lib/Target/Hexagon/HexagonAsmPrinter.h b/llvm/lib/Target/Hexagon/HexagonAsmPrinter.h
index 8e34d2bf9209b..83621142ca5b5 100644
--- a/llvm/lib/Target/Hexagon/HexagonAsmPrinter.h
+++ b/llvm/lib/Target/Hexagon/HexagonAsmPrinter.h
@@ -65,6 +65,7 @@ class TargetMachine;
void LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI);
void LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr &MI);
void LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI);
+ void LowerPATCHABLE_EVENT_CALL(const MachineInstr &MI, bool Typed);
void EmitSled(const MachineInstr &MI, SledKind Kind);
void HexagonProcessInstruction(MCInst &Inst, const MachineInstr &MBB);
diff --git a/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp b/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp
index 6b2a963e2e777..1945216b13b17 100644
--- a/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp
@@ -3957,6 +3957,18 @@ HexagonTargetLowering::shouldExpandAtomicCmpXchgInIR(
return AtomicExpansionKind::LLSC;
}
+MachineBasicBlock *HexagonTargetLowering::EmitInstrWithCustomInserter(
+ MachineInstr &MI, MachineBasicBlock *BB) const {
+ switch (MI.getOpcode()) {
+ case TargetOpcode::PATCHABLE_EVENT_CALL:
+ case TargetOpcode::PATCHABLE_TYPED_EVENT_CALL:
+ // These are lowered in the AsmPrinter.
+ return BB;
+ default:
+ llvm_unreachable("Unexpected instruction with custom inserter");
+ }
+}
+
bool HexagonTargetLowering::isMaskAndCmp0FoldingBeneficial(
const Instruction &AndI) const {
// Only sink 'and' mask to cmp use block if it is masking a single bit since
diff --git a/llvm/lib/Target/Hexagon/HexagonISelLowering.h b/llvm/lib/Target/Hexagon/HexagonISelLowering.h
index 55be8fd043ad5..38f613f92aa87 100644
--- a/llvm/lib/Target/Hexagon/HexagonISelLowering.h
+++ b/llvm/lib/Target/Hexagon/HexagonISelLowering.h
@@ -287,6 +287,10 @@ class HexagonTargetLowering : public TargetLowering {
return AtomicExpansionKind::LLSC;
}
+ MachineBasicBlock *
+ EmitInstrWithCustomInserter(MachineInstr &MI,
+ MachineBasicBlock *BB) const override;
+
private:
void initializeHVXLowering();
unsigned getPreferredHvxVectorAction(MVT VecTy) const;
diff --git a/llvm/lib/Target/Hexagon/HexagonMCInstLower.cpp b/llvm/lib/Target/Hexagon/HexagonMCInstLower.cpp
index 845e60bf1a2a1..c592a55615859 100644
--- a/llvm/lib/Target/Hexagon/HexagonMCInstLower.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonMCInstLower.cpp
@@ -115,6 +115,14 @@ void llvm::HexagonLowerToMC(const MCInstrInfo &MCII, const MachineInstr *MI,
AP.EmitSled(*MI, HexagonAsmPrinter::SledKind::TAIL_CALL);
return;
}
+ if (MI->getOpcode() == Hexagon::PATCHABLE_EVENT_CALL) {
+ AP.LowerPATCHABLE_EVENT_CALL(*MI, false);
+ return;
+ }
+ if (MI->getOpcode() == Hexagon::PATCHABLE_TYPED_EVENT_CALL) {
+ AP.LowerPATCHABLE_EVENT_CALL(*MI, true);
+ return;
+ }
MCInst *MCI = AP.OutContext.createMCInst();
MCI->setOpcode(MI->getOpcode());
diff --git a/llvm/lib/Target/Hexagon/HexagonVLIWPacketizer.cpp b/llvm/lib/Target/Hexagon/HexagonVLIWPacketizer.cpp
index 8d1c17ca97421..fbf196a7a23e5 100644
--- a/llvm/lib/Target/Hexagon/HexagonVLIWPacketizer.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonVLIWPacketizer.cpp
@@ -1077,7 +1077,9 @@ bool HexagonPacketizerList::isSoloInstruction(const MachineInstr &MI) {
if (MI.getOpcode() == Hexagon::PATCHABLE_FUNCTION_ENTER ||
MI.getOpcode() == Hexagon::PATCHABLE_FUNCTION_EXIT ||
- MI.getOpcode() == Hexagon::PATCHABLE_TAIL_CALL)
+ MI.getOpcode() == Hexagon::PATCHABLE_TAIL_CALL ||
+ MI.getOpcode() == Hexagon::PATCHABLE_EVENT_CALL ||
+ MI.getOpcode() == Hexagon::PATCHABLE_TYPED_EVENT_CALL)
return true;
if (MI.getOpcode() == Hexagon::A2_nop)
diff --git a/llvm/test/CodeGen/Hexagon/xray-custom-event.ll b/llvm/test/CodeGen/Hexagon/xray-custom-event.ll
new file mode 100644
index 0000000000000..951ecace4ee38
--- /dev/null
+++ b/llvm/test/CodeGen/Hexagon/xray-custom-event.ll
@@ -0,0 +1,83 @@
+; RUN: llc -mtriple=hexagon-unknown-elf < %s | FileCheck %s
+; RUN: llc -mtriple=hexagon-unknown-linux-musl < %s | FileCheck %s
+
+define i32 @customevent(ptr %p, i32 %sz) nounwind noinline uwtable "function-instrument"="xray-always" {
+entry:
+;; Function entry sled.
+; CHECK-LABEL: .Lxray_sled_0:
+; CHECK: jump
+
+;; Custom event sled (12 words = 48 bytes):
+;; jump-over, allocframe, sp adjust, 2 saves, 2 moves, call,
+;; 2 restores, sp adjust, deallocframe.
+; CHECK-LABEL: .Lxray_sled_1:
+; CHECK: jump .Ltmp
+; CHECK: allocframe(r29,#0):raw
+; CHECK: r29 = add(r29,#-8)
+; CHECK: memw(r29+#0) = r0
+; CHECK: memw(r29+#4) = r1
+; CHECK: r0 = r{{[0-9]+}}
+; CHECK: r1 = r{{[0-9]+}}
+; CHECK: call __xray_CustomEvent
+; CHECK: r0 = memw(r29+#0)
+; CHECK: r1 = memw(r29+#4)
+; CHECK: r29 = add(r29,#8)
+; CHECK: deallocframe
+; CHECK: .Ltmp
+
+ call void @llvm.xray.customevent(ptr %p, i64 4)
+
+;; Function exit sled.
+; CHECK-LABEL: .Lxray_sled_2:
+; CHECK: jump
+
+ ret i32 0
+}
+
+;; Verify the xray_instr_map entry records CUSTOM_EVENT kind (0x04).
+; CHECK: .section xray_instr_map
+; CHECK: .byte 0x04
+;; 0x04 = SledKind::CUSTOM_EVENT
+
+define i32 @typedevent(i64 %type, ptr %p, i32 %sz) nounwind noinline uwtable "function-instrument"="xray-always" {
+entry:
+;; Function entry sled.
+; CHECK-LABEL: .Lxray_sled_3:
+; CHECK: jump
+
+;; Typed event sled (15 words = 60 bytes):
+;; jump-over, allocframe, sp adjust, 3 saves, 3 moves, call,
+;; 3 restores, sp adjust, deallocframe.
+; CHECK-LABEL: .Lxray_sled_4:
+; CHECK: jump .Ltmp
+; CHECK: allocframe(r29,#0):raw
+; CHECK: r29 = add(r29,#-12)
+; CHECK: memw(r29+#0) = r0
+; CHECK: memw(r29+#4) = r1
+; CHECK: memw(r29+#8) = r2
+; CHECK: r0 = r{{[0-9]+}}
+; CHECK: r1 = r{{[0-9]+}}
+; CHECK: r2 = r{{[0-9]+}}
+; CHECK: call __xray_TypedEvent
+; CHECK: r0 = memw(r29+#0)
+; CHECK: r1 = memw(r29+#4)
+; CHECK: r2 = memw(r29+#8)
+; CHECK: r29 = add(r29,#12)
+; CHECK: deallocframe
+; CHECK: .Ltmp
+
+ call void @llvm.xray.typedevent(i64 %type, ptr %p, i64 4)
+
+;; Funct...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/191749
More information about the llvm-commits
mailing list