[compiler-rt] 1e68c79 - Reapply [xray] add support for hexagon

Brian Cain via llvm-commits llvm-commits at lists.llvm.org
Fri Dec 10 05:32:34 PST 2021


Author: Brian Cain
Date: 2021-12-10T05:32:28-08:00
New Revision: 1e68c79987a628f2e9c6b3a7416a8308a58eb436

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

LOG: Reapply [xray] add support for hexagon

Adds x-ray support for hexagon to llvm codegen, clang driver,
compiler-rt libs.

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

Reapplying this after 543a9ad7c460bb8d641b1b7c67bbc032c9bfdb45,
which fixes the leak introduced there.

Added: 
    compiler-rt/lib/xray/xray_hexagon.cpp
    compiler-rt/lib/xray/xray_trampoline_hexagon.S
    llvm/test/CodeGen/Hexagon/xray-pred-ret.ll
    llvm/test/CodeGen/Hexagon/xray.ll

Modified: 
    clang/lib/Driver/ToolChains/Hexagon.cpp
    clang/lib/Driver/XRayArgs.cpp
    compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake
    compiler-rt/lib/xray/CMakeLists.txt
    compiler-rt/lib/xray/xray_interface.cpp
    compiler-rt/lib/xray/xray_tsc.h
    llvm/lib/CodeGen/XRayInstrumentation.cpp
    llvm/lib/Target/Hexagon/HexagonAsmPrinter.cpp
    llvm/lib/Target/Hexagon/HexagonAsmPrinter.h
    llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp
    llvm/lib/Target/Hexagon/HexagonInstrInfo.h
    llvm/lib/Target/Hexagon/HexagonMCInstLower.cpp
    llvm/lib/Target/Hexagon/HexagonSubtarget.h
    llvm/lib/Target/Hexagon/HexagonVLIWPacketizer.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/Driver/ToolChains/Hexagon.cpp b/clang/lib/Driver/ToolChains/Hexagon.cpp
index 18270818d1589..2ce7904ecc40d 100644
--- a/clang/lib/Driver/ToolChains/Hexagon.cpp
+++ b/clang/lib/Driver/ToolChains/Hexagon.cpp
@@ -226,6 +226,7 @@ constructHexagonLinkArgs(Compilation &C, const JobAction &JA,
   StringRef CpuVer = toolchains::HexagonToolChain::GetTargetCPUVersion(Args);
 
   bool NeedsSanitizerDeps = addSanitizerRuntimes(HTC, Args, CmdArgs);
+  bool NeedsXRayDeps = addXRayRuntime(HTC, Args, CmdArgs);
 
   //----------------------------------------------------------------------------
   // Silence warnings for various options
@@ -297,6 +298,8 @@ constructHexagonLinkArgs(Compilation &C, const JobAction &JA,
 
         CmdArgs.push_back("-lunwind");
       }
+      if (NeedsXRayDeps)
+        linkXRayRuntimeDeps(HTC, CmdArgs);
 
       CmdArgs.push_back("-lclang_rt.builtins-hexagon");
       CmdArgs.push_back("-lc");

diff  --git a/clang/lib/Driver/XRayArgs.cpp b/clang/lib/Driver/XRayArgs.cpp
index b44509ad3b881..63b575178bd12 100644
--- a/clang/lib/Driver/XRayArgs.cpp
+++ b/clang/lib/Driver/XRayArgs.cpp
@@ -40,6 +40,7 @@ XRayArgs::XRayArgs(const ToolChain &TC, const ArgList &Args) {
     case llvm::Triple::x86_64:
     case llvm::Triple::arm:
     case llvm::Triple::aarch64:
+    case llvm::Triple::hexagon:
     case llvm::Triple::ppc64le:
     case llvm::Triple::mips:
     case llvm::Triple::mipsel:

diff  --git a/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake b/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake
index 45226b4158d74..3e86cf63c789b 100644
--- a/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake
+++ b/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake
@@ -73,7 +73,8 @@ set(ALL_SCUDO_STANDALONE_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64}
 if(APPLE)
 set(ALL_XRAY_SUPPORTED_ARCH ${X86_64})
 else()
-set(ALL_XRAY_SUPPORTED_ARCH ${X86_64} ${ARM32} ${ARM64} ${MIPS32} ${MIPS64} powerpc64le)
+set(ALL_XRAY_SUPPORTED_ARCH ${X86_64} ${ARM32} ${ARM64} ${MIPS32} ${MIPS64}
+		powerpc64le ${HEXAGON})
 endif()
 set(ALL_SHADOWCALLSTACK_SUPPORTED_ARCH ${ARM64})
 

diff  --git a/compiler-rt/lib/xray/CMakeLists.txt b/compiler-rt/lib/xray/CMakeLists.txt
index 204e5b17c7970..ca9389747a5ee 100644
--- a/compiler-rt/lib/xray/CMakeLists.txt
+++ b/compiler-rt/lib/xray/CMakeLists.txt
@@ -73,6 +73,11 @@ set(powerpc64le_SOURCES
   xray_trampoline_powerpc64_asm.S
   )
 
+set(hexagon_SOURCES
+  xray_hexagon.cpp
+  xray_trampoline_hexagon.S
+  )
+
 set(XRAY_IMPL_HEADERS
   xray_allocator.h
   xray_basic_flags.h
@@ -111,6 +116,7 @@ set(XRAY_ALL_SOURCE_FILES
   ${x86_64_SOURCES}
   ${arm_SOURCES}
   ${armhf_SOURCES}
+  ${hexagon_SOURCES}
   ${mips_SOURCES}
   ${mipsel_SOURCES}
   ${mips64_SOURCES}

diff  --git a/compiler-rt/lib/xray/xray_hexagon.cpp b/compiler-rt/lib/xray/xray_hexagon.cpp
new file mode 100644
index 0000000000000..7f127b2b499cd
--- /dev/null
+++ b/compiler-rt/lib/xray/xray_hexagon.cpp
@@ -0,0 +1,168 @@
+//===-- xray_hexagon.cpp --------------------------------------*- C++ ---*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of XRay, a dynamic runtime instrumentation system.
+//
+// Implementation of hexagon-specific routines (32-bit).
+//
+//===----------------------------------------------------------------------===//
+#include "sanitizer_common/sanitizer_common.h"
+#include "xray_defs.h"
+#include "xray_interface_internal.h"
+#include <assert.h>
+#include <atomic>
+
+namespace __xray {
+
+// The machine codes for some instructions used in runtime patching.
+enum PatchOpcodes : uint32_t {
+  PO_JUMPI_14 = 0x5800c00a, // jump #0x014 (PC + 0x014)
+  PO_CALLR_R6 = 0x50a6c000, // indirect call: callr r6
+  PO_TFR_IMM = 0x78000000,  // transfer immed
+                            // ICLASS 0x7 - S2-type A-type
+  PO_IMMEXT = 0x00000000, // constant extender
+};
+
+enum PacketWordParseBits : uint32_t {
+  PP_DUPLEX = 0x00 << 14,
+  PP_NOT_END = 0x01 << 14,
+  PP_PACKET_END = 0x03 << 14,
+};
+
+enum RegNum : uint32_t {
+  RN_R6 = 0x6,
+  RN_R7 = 0x7,
+};
+
+inline static uint32_t
+encodeExtendedTransferImmediate(uint32_t Imm, RegNum DestReg,
+                                bool PacketEnd = false) XRAY_NEVER_INSTRUMENT {
+  static const uint32_t REG_MASK = 0x1f;
+  assert((DestReg & (~REG_MASK)) == 0);
+  // The constant-extended register transfer encodes the 6 least
+  // significant bits of the effective constant:
+  Imm = Imm & 0x03f;
+  const PacketWordParseBits ParseBits = PacketEnd ? PP_PACKET_END : PP_NOT_END;
+
+  return PO_TFR_IMM | ParseBits | (Imm << 5) | (DestReg & REG_MASK);
+}
+
+inline static uint32_t
+encodeConstantExtender(uint32_t Imm) XRAY_NEVER_INSTRUMENT {
+  // Bits   Name      Description
+  // -----  -------   ------------------------------------------
+  // 31:28  ICLASS    Instruction class = 0000
+  // 27:16  high      High 12 bits of 26-bit constant extension
+  // 15:14  Parse     Parse bits
+  // 13:0   low       Low 14 bits of 26-bit constant extension
+  static const uint32_t IMM_MASK_LOW = 0x03fff;
+  static const uint32_t IMM_MASK_HIGH = 0x00fff << 14;
+
+  // The extender encodes the 26 most significant bits of the effective
+  // constant:
+  Imm = Imm >> 6;
+
+  const uint32_t high = (Imm & IMM_MASK_HIGH) << 16;
+  const uint32_t low = Imm & IMM_MASK_LOW;
+
+  return PO_IMMEXT | high | PP_NOT_END | low;
+}
+
+static void WriteInstFlushCache(void *Addr, uint32_t NewInstruction) {
+  asm volatile("icinva(%[inst_addr])\n\t"
+               "isync\n\t"
+               "memw(%[inst_addr]) = %[new_inst]\n\t"
+               "dccleaninva(%[inst_addr])\n\t"
+               "syncht\n\t"
+               :
+               : [ inst_addr ] "r"(Addr), [ new_inst ] "r"(NewInstruction)
+               : "memory");
+}
+
+inline static bool patchSled(const bool Enable, const uint32_t FuncId,
+                             const XRaySledEntry &Sled,
+                             void (*TracingHook)()) XRAY_NEVER_INSTRUMENT {
+  // When |Enable| == true,
+  // We replace the following compile-time stub (sled):
+  //
+  // .L_xray_sled_N:
+  // <xray_sled_base>:
+  // {  jump .Ltmp0 }
+  // {  nop
+  //    nop
+  //    nop
+  //    nop }
+  // .Ltmp0:
+
+  // With the following runtime patch:
+  //
+  // xray_sled_n (32-bit):
+  //
+  // <xray_sled_n>:
+  // {  immext(#...) // upper 26-bits of func id
+  //    r7 = ##...   // lower  6-bits of func id
+  //    immext(#...) // upper 26-bits of trampoline
+  //    r6 = ##... }  // lower 6 bits of trampoline
+  // {  callr r6 }
+  //
+  // When |Enable|==false, we set back the first instruction in the sled to be
+  // {  jump .Ltmp0 }
+
+  uint32_t *FirstAddress = reinterpret_cast<uint32_t *>(Sled.address());
+  if (Enable) {
+    uint32_t *CurAddress = FirstAddress + 1;
+    *CurAddress = encodeExtendedTransferImmediate(FuncId, RN_R7);
+    CurAddress++;
+    *CurAddress = encodeConstantExtender(reinterpret_cast<uint32_t>(TracingHook));
+    CurAddress++;
+    *CurAddress =
+        encodeExtendedTransferImmediate(reinterpret_cast<uint32_t>(TracingHook), RN_R6, true);
+    CurAddress++;
+
+    *CurAddress = uint32_t(PO_CALLR_R6);
+
+    WriteInstFlushCache(FirstAddress, uint32_t(encodeConstantExtender(FuncId)));
+  } else {
+    WriteInstFlushCache(FirstAddress, uint32_t(PatchOpcodes::PO_JUMPI_14));
+  }
+  return true;
+}
+
+bool patchFunctionEntry(const bool Enable, const uint32_t FuncId,
+                        const XRaySledEntry &Sled,
+                        void (*Trampoline)()) XRAY_NEVER_INSTRUMENT {
+  return patchSled(Enable, FuncId, Sled, Trampoline);
+}
+
+bool patchFunctionExit(const bool Enable, const uint32_t FuncId,
+                       const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT {
+  return patchSled(Enable, FuncId, Sled, __xray_FunctionExit);
+}
+
+bool patchFunctionTailExit(const bool Enable, const uint32_t FuncId,
+                           const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT {
+  return patchSled(Enable, FuncId, Sled, __xray_FunctionExit);
+}
+
+bool patchCustomEvent(const bool Enable, const uint32_t FuncId,
+                      const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT {
+  // FIXME: Implement in hexagon?
+  return false;
+}
+
+bool patchTypedEvent(const bool Enable, const uint32_t FuncId,
+                     const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT {
+  // FIXME: Implement in hexagon?
+  return false;
+}
+
+} // namespace __xray
+
+extern "C" void __xray_ArgLoggerEntry() XRAY_NEVER_INSTRUMENT {
+  // FIXME: this will have to be implemented in the trampoline assembly file
+}

diff  --git a/compiler-rt/lib/xray/xray_interface.cpp b/compiler-rt/lib/xray/xray_interface.cpp
index 391f08e8c6d64..73e67618c9d5f 100644
--- a/compiler-rt/lib/xray/xray_interface.cpp
+++ b/compiler-rt/lib/xray/xray_interface.cpp
@@ -52,6 +52,8 @@ static const int16_t cSledLength = 48;
 static const int16_t cSledLength = 64;
 #elif defined(__powerpc64__)
 static const int16_t cSledLength = 8;
+#elif defined(__hexagon__)
+static const int16_t cSledLength = 20;
 #else
 #error "Unsupported CPU Architecture"
 #endif /* CPU architecture */

diff  --git a/compiler-rt/lib/xray/xray_trampoline_hexagon.S b/compiler-rt/lib/xray/xray_trampoline_hexagon.S
new file mode 100644
index 0000000000000..c87ec4bed1f9c
--- /dev/null
+++ b/compiler-rt/lib/xray/xray_trampoline_hexagon.S
@@ -0,0 +1,99 @@
+//===-- xray_trampoline_hexagon.s -------------------------------*- ASM -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of XRay, a dynamic runtime instrumentation system.
+//
+// This implements the hexagon-specific assembler for the trampolines.
+//
+//===----------------------------------------------------------------------===//
+
+#include "../builtins/assembly.h"
+#include "../sanitizer_common/sanitizer_asm.h"
+
+.macro SAVE_REGISTERS
+memw(sp+#0)=r0
+memw(sp+#4)=r1
+memw(sp+#8)=r2
+memw(sp+#12)=r3
+memw(sp+#16)=r4
+.endm
+.macro RESTORE_REGISTERS
+r0=memw(sp+#0)
+r1=memw(sp+#4)
+r2=memw(sp+#8)
+r3=memw(sp+#12)
+r4=memw(sp+#16)
+.endm
+
+.macro CALL_PATCHED_FUNC entry_type
+	// if (xray::XRayPatchedFunctionE != NULL)
+	//     xray::XRayPatchedFunctionE(FuncType);
+
+	r8 = #ASM_SYMBOL(_ZN6__xray19XRayPatchedFunctionE)
+
+	// The patched sled puts the function type
+	// into r6.  Move it into r0 to pass it to
+	// the patched function.
+	{ r0 = r6
+          r1 = \entry_type
+          p0 = !cmp.eq(r8, #0)
+	  if (p0) callr r8 }
+.endm
+
+	.text
+	.globl ASM_SYMBOL(__xray_FunctionEntry)
+	ASM_HIDDEN(__xray_FunctionEntry)
+	ASM_TYPE_FUNCTION(__xray_FunctionEntry)
+# LLVM-MCA-BEGIN __xray_FunctionEntry
+ASM_SYMBOL(__xray_FunctionEntry):
+	CFI_STARTPROC
+	SAVE_REGISTERS
+
+	CALL_PATCHED_FUNC #0  // XRayEntryType::ENTRY
+.Ltmp0:
+	RESTORE_REGISTERS
+	// return
+# LLVM-MCA-END
+	ASM_SIZE(__xray_FunctionEntry)
+	CFI_ENDPROC
+
+
+	.globl ASM_SYMBOL(__xray_FunctionExit)
+	ASM_HIDDEN(__xray_FunctionExit)
+	ASM_TYPE_FUNCTION(__xray_FunctionExit)
+# LLVM-MCA-BEGIN __xray_FunctionExit
+ASM_SYMBOL(__xray_FunctionExit):
+	CFI_STARTPROC
+	SAVE_REGISTERS
+
+	CALL_PATCHED_FUNC #1  // XRayEntryType::EXIT
+.Ltmp1:
+	RESTORE_REGISTERS
+	// return
+	jumpr r31
+# LLVM-MCA-END
+	ASM_SIZE(__xray_FunctionExit)
+	CFI_ENDPROC
+
+
+	.globl ASM_SYMBOL(__xray_FunctionTailExit)
+	ASM_HIDDEN(__xray_FunctionTailExit)
+	ASM_TYPE_FUNCTION(__xray_FunctionTailExit)
+# LLVM-MCA-BEGIN __xray_FunctionTailExit
+ASM_SYMBOL(__xray_FunctionTailExit):
+	CFI_STARTPROC
+	SAVE_REGISTERS
+
+	CALL_PATCHED_FUNC #2  // XRayEntryType::TAIL
+.Ltmp2:
+	RESTORE_REGISTERS
+	// return
+	jumpr r31
+# LLVM-MCA-END
+	ASM_SIZE(__xray_FunctionTailExit)
+	CFI_ENDPROC

diff  --git a/compiler-rt/lib/xray/xray_tsc.h b/compiler-rt/lib/xray/xray_tsc.h
index bd7e1911abb35..58347dca5f7a1 100644
--- a/compiler-rt/lib/xray/xray_tsc.h
+++ b/compiler-rt/lib/xray/xray_tsc.h
@@ -42,7 +42,8 @@ inline uint64_t getTSCFrequency() XRAY_NEVER_INSTRUMENT {
 #include "xray_x86_64.inc"
 #elif defined(__powerpc64__)
 #include "xray_powerpc64.inc"
-#elif defined(__arm__) || defined(__aarch64__) || defined(__mips__)
+#elif defined(__arm__) || defined(__aarch64__) || defined(__mips__) ||         \
+    defined(__hexagon__)
 // Emulated TSC.
 // There is no instruction like RDTSCP in user mode on ARM. ARM's CP15 does
 //   not have a constant frequency like TSC on x86(_64), it may go faster

diff  --git a/llvm/lib/CodeGen/XRayInstrumentation.cpp b/llvm/lib/CodeGen/XRayInstrumentation.cpp
index 11d1b309aa645..b66429d8a5bf5 100644
--- a/llvm/lib/CodeGen/XRayInstrumentation.cpp
+++ b/llvm/lib/CodeGen/XRayInstrumentation.cpp
@@ -226,6 +226,7 @@ bool XRayInstrumentation::runOnMachineFunction(MachineFunction &MF) {
     case Triple::ArchType::arm:
     case Triple::ArchType::thumb:
     case Triple::ArchType::aarch64:
+    case Triple::ArchType::hexagon:
     case Triple::ArchType::mips:
     case Triple::ArchType::mipsel:
     case Triple::ArchType::mips64:

diff  --git a/llvm/lib/Target/Hexagon/HexagonAsmPrinter.cpp b/llvm/lib/Target/Hexagon/HexagonAsmPrinter.cpp
index 8e6a01e3a1865..411078052e0fb 100644
--- a/llvm/lib/Target/Hexagon/HexagonAsmPrinter.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonAsmPrinter.cpp
@@ -773,6 +773,67 @@ void HexagonAsmPrinter::emitInstruction(const MachineInstr *MI) {
   OutStreamer->emitInstruction(MCB, getSubtargetInfo());
 }
 
+void HexagonAsmPrinter::EmitSled(const MachineInstr &MI, SledKind Kind) {
+  static const int8_t NoopsInSledCount = 4;
+  // We want to emit the following pattern:
+  //
+  // .L_xray_sled_N:
+  // <xray_sled_base>:
+  // { 	jump .Ltmp0 }
+  // {  nop
+  //    nop
+  //    nop
+  //    nop }
+  // .Ltmp0:
+  //
+  // We need the 4 nop words because at runtime, we'd be patching over the
+  // full 5 words with the following pattern:
+  //
+  // <xray_sled_n>:
+  // { 	immext(#...) // upper 26-bits of trampoline
+  //    r6 = ##...   // lower  6-bits of trampoline
+  //    immext(#...) // upper 26-bits of func id
+  //    r7 = ##... }  // lower 6 bits of func id
+  // { 	callr r6 }
+  //
+  //
+  auto CurSled = OutContext.createTempSymbol("xray_sled_", true);
+  OutStreamer->emitLabel(CurSled);
+
+  MCInst *SledJump = new (OutContext) MCInst();
+  SledJump->setOpcode(Hexagon::J2_jump);
+  auto PostSled = OutContext.createTempSymbol();
+  SledJump->addOperand(MCOperand::createExpr(HexagonMCExpr::create(
+      MCSymbolRefExpr::create(PostSled, OutContext), OutContext)));
+
+  // Emit "jump PostSled" instruction, which jumps over the nop series.
+  MCInst SledJumpPacket;
+  SledJumpPacket.setOpcode(Hexagon::BUNDLE);
+  SledJumpPacket.addOperand(MCOperand::createImm(0));
+  SledJumpPacket.addOperand(MCOperand::createInst(SledJump));
+
+  EmitToStreamer(*OutStreamer, SledJumpPacket);
+
+  // FIXME: this will emit individual packets, we should
+  // special-case this and combine them into a single packet.
+  emitNops(NoopsInSledCount);
+
+  OutStreamer->emitLabel(PostSled);
+  recordSled(CurSled, MI, Kind, 0);
+}
+
+void HexagonAsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI) {
+  EmitSled(MI, SledKind::FUNCTION_ENTER);
+}
+
+void HexagonAsmPrinter::LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr &MI) {
+  EmitSled(MI, SledKind::FUNCTION_EXIT);
+}
+
+void HexagonAsmPrinter::LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI) {
+  EmitSled(MI, SledKind::TAIL_CALL);
+}
+
 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeHexagonAsmPrinter() {
   RegisterAsmPrinter<HexagonAsmPrinter> X(getTheHexagonTarget());
 }

diff  --git a/llvm/lib/Target/Hexagon/HexagonAsmPrinter.h b/llvm/lib/Target/Hexagon/HexagonAsmPrinter.h
index 3932def878544..93d5f1dce7afe 100644
--- a/llvm/lib/Target/Hexagon/HexagonAsmPrinter.h
+++ b/llvm/lib/Target/Hexagon/HexagonAsmPrinter.h
@@ -36,7 +36,11 @@ class TargetMachine;
 
     bool runOnMachineFunction(MachineFunction &Fn) override {
       Subtarget = &Fn.getSubtarget<HexagonSubtarget>();
-      return AsmPrinter::runOnMachineFunction(Fn);
+      const bool Modified = AsmPrinter::runOnMachineFunction(Fn);
+      // Emit the XRay table for this function.
+      emitXRayTable();
+
+      return Modified;
     }
 
     StringRef getPassName() const override {
@@ -47,6 +51,16 @@ class TargetMachine;
           const override;
 
     void emitInstruction(const MachineInstr *MI) override;
+
+    //===------------------------------------------------------------------===//
+    // XRay implementation
+    //===------------------------------------------------------------------===//
+    // XRay-specific lowering for Hexagon.
+    void LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI);
+    void LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr &MI);
+    void LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI);
+    void EmitSled(const MachineInstr &MI, SledKind Kind);
+
     void HexagonProcessInstruction(MCInst &Inst, const MachineInstr &MBB);
 
     void printOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O);

diff  --git a/llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp b/llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp
index b6984d40f78e2..931b0c0e00903 100644
--- a/llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp
@@ -40,6 +40,7 @@
 #include "llvm/CodeGen/TargetSubtargetInfo.h"
 #include "llvm/IR/DebugLoc.h"
 #include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCInstBuilder.h"
 #include "llvm/MC/MCInstrDesc.h"
 #include "llvm/MC/MCInstrItineraries.h"
 #include "llvm/MC/MCRegisterInfo.h"
@@ -4655,3 +4656,11 @@ short HexagonInstrInfo::changeAddrMode_rr_ur(short Opc) const {
 short HexagonInstrInfo::changeAddrMode_ur_rr(short Opc) const {
   return Opc >= 0 ? Hexagon::changeAddrMode_ur_rr(Opc) : Opc;
 }
+
+MCInst HexagonInstrInfo::getNop() const {
+  static const MCInst Nop = MCInstBuilder(Hexagon::A2_nop);
+
+  return MCInstBuilder(Hexagon::BUNDLE)
+    .addImm(0)
+    .addInst(&Nop);
+}

diff  --git a/llvm/lib/Target/Hexagon/HexagonInstrInfo.h b/llvm/lib/Target/Hexagon/HexagonInstrInfo.h
index eaaf9f7046c74..830f04d9eac3d 100644
--- a/llvm/lib/Target/Hexagon/HexagonInstrInfo.h
+++ b/llvm/lib/Target/Hexagon/HexagonInstrInfo.h
@@ -524,6 +524,8 @@ class HexagonInstrInfo : public HexagonGenInstrInfo {
   short changeAddrMode_ur_rr(const MachineInstr &MI) const {
     return changeAddrMode_ur_rr(MI.getOpcode());
   }
+
+  MCInst getNop() const override;
 };
 
 } // end namespace llvm

diff  --git a/llvm/lib/Target/Hexagon/HexagonMCInstLower.cpp b/llvm/lib/Target/Hexagon/HexagonMCInstLower.cpp
index 987c4a5fa6c41..d5c34ac467c34 100644
--- a/llvm/lib/Target/Hexagon/HexagonMCInstLower.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonMCInstLower.cpp
@@ -104,6 +104,19 @@ void llvm::HexagonLowerToMC(const MCInstrInfo &MCII, const MachineInstr *MI,
     HexagonMCInstrInfo::setOuterLoop(MCB);
     return;
   }
+  if (MI->getOpcode() == Hexagon::PATCHABLE_FUNCTION_ENTER) {
+    AP.EmitSled(*MI, HexagonAsmPrinter::SledKind::FUNCTION_ENTER);
+    return;
+  }
+  if (MI->getOpcode() == Hexagon::PATCHABLE_FUNCTION_EXIT) {
+    AP.EmitSled(*MI, HexagonAsmPrinter::SledKind::FUNCTION_EXIT);
+    return;
+  }
+  if (MI->getOpcode() == Hexagon::PATCHABLE_TAIL_CALL) {
+    AP.EmitSled(*MI, HexagonAsmPrinter::SledKind::TAIL_CALL);
+    return;
+  }
+
   MCInst *MCI = AP.OutContext.createMCInst();
   MCI->setOpcode(MI->getOpcode());
   assert(MCI->getOpcode() == static_cast<unsigned>(MI->getOpcode()) &&

diff  --git a/llvm/lib/Target/Hexagon/HexagonSubtarget.h b/llvm/lib/Target/Hexagon/HexagonSubtarget.h
index a4f2e159bf4bb..8ca6018bd81cc 100644
--- a/llvm/lib/Target/Hexagon/HexagonSubtarget.h
+++ b/llvm/lib/Target/Hexagon/HexagonSubtarget.h
@@ -138,6 +138,8 @@ class HexagonSubtarget : public HexagonGenSubtargetInfo {
   /// subtarget options.  Definition of function is auto generated by tblgen.
   void ParseSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS);
 
+  bool isXRaySupported() const override { return true; }
+
   bool hasV5Ops() const {
     return getHexagonArchVersion() >= Hexagon::ArchEnum::V5;
   }

diff  --git a/llvm/lib/Target/Hexagon/HexagonVLIWPacketizer.cpp b/llvm/lib/Target/Hexagon/HexagonVLIWPacketizer.cpp
index 7640054306d78..85ec0cdcd8f07 100644
--- a/llvm/lib/Target/Hexagon/HexagonVLIWPacketizer.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonVLIWPacketizer.cpp
@@ -1082,6 +1082,11 @@ bool HexagonPacketizerList::isSoloInstruction(const MachineInstr &MI) {
   if (HII->isSolo(MI))
     return true;
 
+  if (MI.getOpcode() == Hexagon::PATCHABLE_FUNCTION_ENTER ||
+      MI.getOpcode() == Hexagon::PATCHABLE_FUNCTION_EXIT ||
+      MI.getOpcode() == Hexagon::PATCHABLE_TAIL_CALL)
+    return true;
+
   if (MI.getOpcode() == Hexagon::A2_nop)
     return true;
 

diff  --git a/llvm/test/CodeGen/Hexagon/xray-pred-ret.ll b/llvm/test/CodeGen/Hexagon/xray-pred-ret.ll
new file mode 100644
index 0000000000000..c7d5333059253
--- /dev/null
+++ b/llvm/test/CodeGen/Hexagon/xray-pred-ret.ll
@@ -0,0 +1,27 @@
+; RUN: llc -filetype=asm -o - -mtriple=hexagon-unknown-linux-musl < %s | FileCheck %s
+
+define void @Foo(i32 signext %a, i32 signext %b) #0 {
+; CHECK-LABEL: @Foo
+; CHECK-LABEL: .Lxray_sled_0:
+; CHECK:        jump .Ltmp0
+; CHECK-COUNT-4: nop
+entry:
+  %cmp = icmp sgt i32 %a, %b
+  br i1 %cmp, label %return, label %if.end
+
+; CHECK-LABEL: .Lxray_sled_1:
+; CHECK:        jump .Ltmp1
+; CHECK-COUNT-4: nop
+; CHECK-LABEL: .Ltmp1:
+; CHECK:       if (p0) jumpr:nt r31
+if.end:
+  tail call void @Bar()
+  br label %return
+
+return:
+  ret void
+}
+
+declare void @Bar()
+
+attributes #0 = { "function-instrument"="xray-always" }

diff  --git a/llvm/test/CodeGen/Hexagon/xray.ll b/llvm/test/CodeGen/Hexagon/xray.ll
new file mode 100644
index 0000000000000..ba5913a12de39
--- /dev/null
+++ b/llvm/test/CodeGen/Hexagon/xray.ll
@@ -0,0 +1,29 @@
+; RUN: llc -filetype=asm -o - -mtriple=hexagon-unknown-elf < %s | FileCheck %s
+; RUN: llc -filetype=asm -o - -mtriple=hexagon-unknown-linux-musl  < %s | FileCheck %s
+
+define i32 @foo() nounwind noinline uwtable "function-instrument"="xray-always" {
+; CHECK-LABEL: .Lxray_sled_0:
+; CHECK:       jump .Ltmp0
+; CHECK:         nop
+; CHECK:         nop
+; CHECK:         nop
+; CHECK:         nop
+; CHECK-LABEL: .Ltmp0:
+  ret i32 0
+; CHECK-LABEL: .Lxray_sled_1:
+; CHECK:       jump .Ltmp1
+; CHECK:         nop
+; CHECK:         nop
+; CHECK:         nop
+; CHECK:         nop
+; CHECK-LABEL: .Ltmp1:
+; CHECK:       jumpr r31
+}
+; CHECK-LABEL: xray_instr_map
+; CHECK-LABEL: .Lxray_sleds_start0:
+; CHECK:       .word {{.*}}Lxray_sled_0
+; CHECK:       .word {{.*}}Lxray_sled_1
+; CHECK-LABEL: .Lxray_sleds_end0:
+; CHECK-LABEL: xray_fn_idx
+; CHECK:       .word {{.*}}Lxray_sleds_start0
+; CHECK-NEXT:  .word {{.*}}Lxray_sleds_end0


        


More information about the llvm-commits mailing list