[llvm-branch-commits] [llvm] [AArch64][llvm] Some instructions should be `HINT` aliases (NFC) (PR #189926)

Jonathan Thackray via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Wed Jun 17 23:57:13 PDT 2026


https://github.com/jthackray updated https://github.com/llvm/llvm-project/pull/189926

>From 484fc36422ebace3ac9f38d15464640a4c6b0195 Mon Sep 17 00:00:00 2001
From: Jonathan Thackray <jonathan.thackray at arm.com>
Date: Tue, 31 Mar 2026 01:18:43 +0100
Subject: [PATCH 1/4] [AArch64][llvm] Some instructions should be `HINT`
 aliases (NFC)

Implement the following instructions as a `HINT` alias instead of a
dedicated instruction in separate classes:
  * `stshh`
  * `stcph`
  * `shuh`
  * `tsb`

Updated all their helper methods too, and updated the `stshh` pseudo
expansion for the intrinsic to emit `HINT #0x30 | policy`.

Code in AArch64AsmPrinter::emitInstruction identified an initial BTI using a
broad bitmask on the HINT immediate, which also matched shuh/stcph (50..52)
This could move the patchable entry label after a non-BTI instruction.
Replaced it with an exact BTI check using the BTI HINT range (32..63) and
AArch64BTIHint::lookupBTIByEncoding(Imm ^ 32).

A following change will remove duplicated code and simplify.

No test changes.
---
 llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp |  6 +-
 .../lib/Target/AArch64/AArch64InstrFormats.td | 81 ++++++++---------
 llvm/lib/Target/AArch64/AArch64InstrInfo.td   | 19 ++--
 .../Target/AArch64/AArch64SystemOperands.td   | 15 ++--
 .../AArch64/AsmParser/AArch64AsmParser.cpp    | 86 +++++++++++++++++++
 .../MCTargetDesc/AArch64InstPrinter.cpp       | 25 +++++-
 .../AArch64/MCTargetDesc/AArch64InstPrinter.h |  6 ++
 .../Target/AArch64/Utils/AArch64BaseInfo.h    |  2 +-
 8 files changed, 170 insertions(+), 70 deletions(-)

diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
index b16c0460adf38..b93119393afe6 100644
--- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
+++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
@@ -3202,8 +3202,10 @@ void AArch64AsmPrinter::emitInstruction(const MachineInstr *MI) {
     if (CurrentPatchableFunctionEntrySym &&
         CurrentPatchableFunctionEntrySym == CurrentFnBegin &&
         MI == &MF->front().front()) {
-      int64_t Imm = MI->getOperand(0).getImm();
-      if ((Imm & 32) && (Imm & 6)) {
+      uint64_t Imm = MI->getOperand(0).getImm();
+      // Match only exact BTI encodings in HINT space.
+      if (Imm >= 32 && Imm < 64 &&
+          AArch64BTIHint::lookupBTIByEncoding(Imm ^ 32)) {
         MCInst Inst;
         MCInstLowering.Lower(MI, Inst);
         EmitToStreamer(*OutStreamer, Inst);
diff --git a/llvm/lib/Target/AArch64/AArch64InstrFormats.td b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
index 787a11401cb6e..09be57953386d 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrFormats.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
@@ -1869,19 +1869,51 @@ def PHintInstOperand : AsmOperandClass {
 def phint_op : Operand<i32> {
     let ParserMatchClass = PHintInstOperand;
     let PrintMethod = "printPHintOp";
+    let MCOperandPredicate = [{
+      if (!MCOp.isImm())
+        return false;
+      return AArch64PHint::lookupPHintByEncoding(MCOp.getImm()) != nullptr;
+    }];
     let OperandType = "OPERAND_IMMEDIATE";
     let MIOperandInfo = (ops i32imm: $policy);
-    let DecoderMethod = "DecodeUImm<3>";
+    let DecoderMethod = "DecodeUImm<7>";
 }
 
-class STSHHI
-    : SimpleSystemI<0, (ins phint_op:$policy), "stshh", "\t$policy", []>,
-      Sched<[WriteHint]> {
-  bits<1> policy;
-  let Inst{20-12} = 0b000110010;
-  let Inst{11-8} = 0b0110;
-  let Inst{7-6} = 0b00;
-  let Inst{5} = policy;
+def TSBHintOperand : AsmOperandClass {
+    let Name = "TSBHint";
+    let ParserMethod = "tryParseTSBHintOperand";
+}
+
+def tsbhint_op : Operand<i32> {
+    let ParserMatchClass = TSBHintOperand;
+    let PrintMethod = "printTSBHintOp";
+    let MCOperandPredicate = [{
+      if (!MCOp.isImm() || MCOp.getImm() < 16)
+        return false;
+      return AArch64TSB::lookupTSBByEncoding(MCOp.getImm() - 16) != nullptr;
+    }];
+    let OperandType = "OPERAND_IMMEDIATE";
+    let MIOperandInfo = (ops i32imm: $policy);
+    let DecoderMethod = "DecodeUImm<7>";
+}
+
+def SHUHintOperand : AsmOperandClass {
+    let Name = "SHUHint";
+    let ParserMethod = "tryParseSHUHintOperand";
+}
+
+def shuhint_op : Operand<i32> {
+    let ParserMatchClass = SHUHintOperand;
+    let PrintMethod = "printSHUHintOp";
+    let MCOperandPredicate = [{
+      if (!MCOp.isImm() || MCOp.getImm() < 50)
+        return false;
+      return AArch64CMHPriorityHint::lookupCMHPriorityHintByEncoding(
+                 MCOp.getImm() - 50) != nullptr;
+    }];
+    let OperandType = "OPERAND_IMMEDIATE";
+    let MIOperandInfo = (ops i32imm: $priority);
+    let DecoderMethod = "DecodeUImm<7>";
 }
 
 // System instructions taking a single literal operand which encodes into
@@ -13600,37 +13632,6 @@ multiclass SIMDThreeSameVectorFP8MatrixMul<string asm, SDPatternOperator OpNode>
     }
 }
 
-//----------------------------------------------------------------------------
-// Contention Management Hints - FEAT_CMH
-//----------------------------------------------------------------------------
-
-class SHUHInst<string asm> : I<
-    (outs),
-    (ins CMHPriorityHint_op:$priority),
-    asm, "\t$priority", "", []>, Sched<[]> {
-  bits<1> priority;
-  let Inst{31-12} = 0b11010101000000110010;
-  let Inst{11-8}  = 0b0110;
-  let Inst{7-6}   = 0b01;
-  let Inst{5}     = priority;
-  let Inst{4-0}   = 0b11111;
-}
-
-multiclass SHUH<string asm> {
-  def NAME : SHUHInst<asm>;
-  def      : InstAlias<asm, (!cast<Instruction>(NAME) 0), 1>;
-}
-
-class STCPHInst<string asm> : I<
-    (outs),
-    (ins),
-    asm, "", "", []>, Sched<[]> {
-    let Inst{31-12} = 0b11010101000000110010;
-    let Inst{11-8}  = 0b0110;
-    let Inst{7-5}   = 0b100;
-    let Inst{4-0}   = 0b11111;
-}
-
 //---
 // Permission Overlays Extension 2 (FEAT_S1POE2)
 //---
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index 96c77c2f75196..e0da5119acdbe 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -1566,7 +1566,10 @@ def NOP : SystemNoOperands<0b000, "hint\t#0">;
 
 def : InstAlias<"nop", (NOP)>;
 
-def STSHH: STSHHI;
+def : InstAlias<"stshh $policy", (HINT phint_op:$policy)>;
+def : InstAlias<"shuh", (HINT 50)>;
+def : InstAlias<"shuh $op", (HINT shuhint_op:$op)>;
+def : InstAlias<"stcph", (HINT 52)>;
 
 // In order to be able to write readable assembly, LLVM should accept assembly
 // inputs that use Branch Target Identification mnemonics, even with BTI disabled.
@@ -1597,12 +1600,6 @@ def DSB   : CRmSystemI<barrier_op, 0b100, "dsb",
 def ISB   : CRmSystemI<barrier_op, 0b110, "isb",
                        [(int_aarch64_isb (i32 imm32_0_15:$CRm))]>;
 
-def TSB   : CRmSystemI<barrier_op, 0b010, "tsb", []> {
-  let CRm        = 0b0010;
-  let Inst{12}   = 0;
-  let Predicates = [HasTRACEV8_4];
-}
-
 def DSBnXS  : CRmSystemI<barrier_nxs_op, 0b001, "dsb"> {
   let CRm{1-0}   = 0b11;
   let Inst{9-8}  = 0b10;
@@ -1672,6 +1669,7 @@ def GCSPOPM_NoOp : InstAlias<"gcspopm", (GCSPOPM XZR)>, Requires<[HasGCS]>; // R
 
 def GCSB_DSYNC_disable : InstAlias<"gcsb\tdsync", (HINT 19), 0>;
 def GCSB_DSYNC         : InstAlias<"gcsb\tdsync", (HINT 19), 1>, Requires<[HasGCS]>;
+def : InstAlias<"tsb\t$op", (HINT tsbhint_op:$op)>, Requires<[HasTRACEV8_4]>;
 
 def : TokenAlias<"DSYNC", "dsync">;
 
@@ -11932,13 +11930,6 @@ let Predicates = [HasF16F32MM] in
 let Uses = [FPMR, FPCR] in
   defm FMMLA : SIMDThreeSameVectorFP8MatrixMul<"fmmla", int_aarch64_neon_fmmla>;
 
-//===----------------------------------------------------------------------===//
-// Contention Management Hints (FEAT_CMH)
-//===----------------------------------------------------------------------===//
-
-defm SHUH  : SHUH<"shuh">;       // Shared Update Hint instruction
-def STCPH  : STCPHInst<"stcph">; // Store Concurrent Priority Hint instruction
-
 //===----------------------------------------------------------------------===//
 // Permission Overlays Extension 2 (FEAT_S1POE2)
 //===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/AArch64/AArch64SystemOperands.td b/llvm/lib/Target/AArch64/AArch64SystemOperands.td
index bcd1786a0e9ea..d933a8f0029bb 100644
--- a/llvm/lib/Target/AArch64/AArch64SystemOperands.td
+++ b/llvm/lib/Target/AArch64/AArch64SystemOperands.td
@@ -2450,15 +2450,10 @@ def : RWSysReg<"ACTLRALIAS_EL1",  0b11, 0b000, 0b0001, 0b0100, 0b101>;
 // v9.6a PCDPHINT instruction options.
 //===----------------------------------------------------------------------===//
 
-class PHint<bits<2> op0, bits<3> op1, bits<4> crn, bits<4> crm,
-              bits<3> op2, string name> {
+class PHint<string name, bits<7> encoding> {
   string Name = name;
-  bits<16> Encoding;
-  let Encoding{15-14} = op0;
-  let Encoding{13-11} = op1;
-  let Encoding{10-7} = crn;
-  let Encoding{6-3} = crm;
-  let Encoding{2-0} = op2;
+  bits<7> Encoding;
+  let Encoding = encoding;
   code Requires = [{ {} }];
 }
 
@@ -2481,8 +2476,8 @@ def lookupPHintByName : SearchIndex {
   let Key = ["Name"];
 }
 
-def KEEP : PHint<0b00, 0b000, 0b0000, 0b0000, 0b000, "keep">;
-def STRM : PHint<0b00, 0b000, 0b0000, 0b0000, 0b001, "strm">;
+def KEEP : PHint<"keep", 0b0110000>;
+def STRM : PHint<"strm", 0b0110001>;
 
 // v9.6a Realm management extension enhancements
 def : RWSysReg<"GPCBW_EL3", 0b11, 0b110, 0b0010, 0b0001, 0b101>;
diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
index 1f0678c3c17c9..1e707656c388a 100644
--- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -268,6 +268,8 @@ class AArch64AsmParser : public MCTargetAsmParser {
   ParseStatus tryParseRPRFMOperand(OperandVector &Operands);
   ParseStatus tryParsePSBHint(OperandVector &Operands);
   ParseStatus tryParseBTIHint(OperandVector &Operands);
+  ParseStatus tryParseSHUHintOperand(OperandVector &Operands);
+  ParseStatus tryParseTSBHintOperand(OperandVector &Operands);
   ParseStatus tryParseCMHPriorityHint(OperandVector &Operands);
   ParseStatus tryParseTIndexHint(OperandVector &Operands);
   ParseStatus tryParseAdrpLabel(OperandVector &Operands);
@@ -392,6 +394,8 @@ class AArch64Operand : public MCParsedAsmOperand {
     k_PSBHint,
     k_PHint,
     k_BTIHint,
+    k_SHUHint,
+    k_TSBHint,
     k_CMHPriorityHint,
     k_TIndexHint,
   } Kind;
@@ -516,6 +520,8 @@ class AArch64Operand : public MCParsedAsmOperand {
   using PSBHintOp = NamedHintOp;
   using PHintOp = NamedHintOp;
   using BTIHintOp = NamedHintOp;
+  using SHUHintOp = NamedHintOp;
+  using TSBHintOp = NamedHintOp;
   using CMHPriorityHintOp = NamedHintOp;
   using TIndexHintOp = NamedHintOp;
 
@@ -544,6 +550,8 @@ class AArch64Operand : public MCParsedAsmOperand {
     PSBHintOp PSBHint;
     PHintOp PHint;
     BTIHintOp BTIHint;
+    SHUHintOp SHUHint;
+    TSBHintOp TSBHint;
     CMHPriorityHintOp CMHPriorityHint;
     TIndexHintOp TIndexHint;
     ShiftExtendOp ShiftExtend;
@@ -616,6 +624,12 @@ class AArch64Operand : public MCParsedAsmOperand {
     case k_BTIHint:
       BTIHint = o.BTIHint;
       break;
+    case k_SHUHint:
+      SHUHint = o.SHUHint;
+      break;
+    case k_TSBHint:
+      TSBHint = o.TSBHint;
+      break;
     case k_CMHPriorityHint:
       CMHPriorityHint = o.CMHPriorityHint;
       break;
@@ -791,11 +805,31 @@ class AArch64Operand : public MCParsedAsmOperand {
     return BTIHint.Val;
   }
 
+  unsigned getSHUHint() const {
+    assert(Kind == k_SHUHint && "Invalid access!");
+    return SHUHint.Val;
+  }
+
+  unsigned getTSBHint() const {
+    assert(Kind == k_TSBHint && "Invalid access!");
+    return TSBHint.Val;
+  }
+
   StringRef getBTIHintName() const {
     assert(Kind == k_BTIHint && "Invalid access!");
     return StringRef(BTIHint.Data, BTIHint.Length);
   }
 
+  StringRef getSHUHintName() const {
+    assert(Kind == k_SHUHint && "Invalid access!");
+    return StringRef(SHUHint.Data, SHUHint.Length);
+  }
+
+  StringRef getTSBHintName() const {
+    assert(Kind == k_TSBHint && "Invalid access!");
+    return StringRef(TSBHint.Data, TSBHint.Length);
+  }
+
   unsigned getCMHPriorityHint() const {
     assert(Kind == k_CMHPriorityHint && "Invalid access!");
     return CMHPriorityHint.Val;
@@ -1558,6 +1592,8 @@ class AArch64Operand : public MCParsedAsmOperand {
   bool isPSBHint() const { return Kind == k_PSBHint; }
   bool isPHint() const { return Kind == k_PHint; }
   bool isBTIHint() const { return Kind == k_BTIHint; }
+  bool isSHUHint() const { return Kind == k_SHUHint; }
+  bool isTSBHint() const { return Kind == k_TSBHint; }
   bool isCMHPriorityHint() const { return Kind == k_CMHPriorityHint; }
   bool isTIndexHint() const { return Kind == k_TIndexHint; }
   bool isShiftExtend() const { return Kind == k_ShiftExtend; }
@@ -2245,6 +2281,16 @@ class AArch64Operand : public MCParsedAsmOperand {
     Inst.addOperand(MCOperand::createImm(getBTIHint()));
   }
 
+  void addSHUHintOperands(MCInst &Inst, unsigned N) const {
+    assert(N == 1 && "Invalid number of operands!");
+    Inst.addOperand(MCOperand::createImm(getSHUHint()));
+  }
+
+  void addTSBHintOperands(MCInst &Inst, unsigned N) const {
+    assert(N == 1 && "Invalid number of operands!");
+    Inst.addOperand(MCOperand::createImm(getTSBHint()));
+  }
+
   void addCMHPriorityHintOperands(MCInst &Inst, unsigned N) const {
     assert(N == 1 && "Invalid number of operands!");
     Inst.addOperand(MCOperand::createImm(getCMHPriorityHint()));
@@ -2610,6 +2656,18 @@ class AArch64Operand : public MCParsedAsmOperand {
                                   BTIHintEncoding>(Val, Str, S, Ctx);
   }
 
+  static std::unique_ptr<AArch64Operand>
+  CreateSHUHint(unsigned Val, StringRef Str, SMLoc S, MCContext &Ctx) {
+    return CreateNamedHintOperand<k_SHUHint, &AArch64Operand::SHUHint>(
+        Val, Str, S, Ctx, [](unsigned EncodedVal) { return EncodedVal + 50; });
+  }
+
+  static std::unique_ptr<AArch64Operand>
+  CreateTSBHint(unsigned Val, StringRef Str, SMLoc S, MCContext &Ctx) {
+    return CreateNamedHintOperand<k_TSBHint, &AArch64Operand::TSBHint>(
+        Val, Str, S, Ctx, [](unsigned EncodedVal) { return EncodedVal | 16; });
+  }
+
   static std::unique_ptr<AArch64Operand>
   CreateCMHPriorityHint(unsigned Val, StringRef Str, SMLoc S, MCContext &Ctx) {
     return CreateNamedHintOperand<k_CMHPriorityHint,
@@ -2733,6 +2791,12 @@ void AArch64Operand::print(raw_ostream &OS, const MCAsmInfo &MAI) const {
   case k_BTIHint:
     OS << getBTIHintName();
     break;
+  case k_SHUHint:
+    OS << getSHUHintName();
+    break;
+  case k_TSBHint:
+    OS << getTSBHintName();
+    break;
   case k_CMHPriorityHint:
     OS << getCMHPriorityHintName();
     break;
@@ -4386,6 +4450,28 @@ AArch64AsmParser::tryParsePHintInstOperand(OperandVector &Operands) {
                                   AArch64Operand::CreatePHintInst);
 }
 
+ParseStatus AArch64AsmParser::tryParseSHUHintOperand(OperandVector &Operands) {
+  return tryParseNamedHintOperand(
+      Operands, AArch64CMHPriorityHint::lookupCMHPriorityHintByName,
+      AArch64Operand::CreateSHUHint);
+}
+
+ParseStatus AArch64AsmParser::tryParseTSBHintOperand(OperandVector &Operands) {
+  SMLoc S = getLoc();
+  const AsmToken &Tok = getTok();
+  if (Tok.isNot(AsmToken::Identifier))
+    return TokError("'csync' operand expected");
+
+  auto TSB = AArch64TSB::lookupTSBByName(Tok.getString());
+  if (!TSB || TSB->Encoding != AArch64TSB::csync)
+    return TokError("'csync' operand expected");
+
+  Operands.push_back(AArch64Operand::CreateTSBHint(
+      TSB->Encoding, Tok.getString(), S, getContext()));
+  Lex(); // Eat identifier token.
+  return ParseStatus::Success;
+}
+
 /// tryParseNeonVectorRegister - Parse a vector register operand.
 bool AArch64AsmParser::tryParseNeonVectorRegister(OperandVector &Operands) {
   if (getTok().isNot(AsmToken::Identifier))
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp
index 8e5d57b66b049..b901d579533da 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp
@@ -1596,6 +1596,28 @@ void AArch64InstPrinter::printBTIHintOp(const MCInst *MI, unsigned OpNum,
                    AArch64BTIHint::lookupBTIByEncoding, decodeBTIHint);
 }
 
+void AArch64InstPrinter::printSHUHintOp(const MCInst *MI, unsigned OpNum,
+                                        const MCSubtargetInfo &STI,
+                                        raw_ostream &O) {
+  unsigned shuhintop = MI->getOperand(OpNum).getImm() - 50;
+  auto SHU = AArch64CMHPriorityHint::lookupCMHPriorityHintByEncoding(shuhintop);
+  if (SHU)
+    O << SHU->Name;
+  else
+    markup(O, Markup::Immediate) << '#' << formatImm(shuhintop);
+}
+
+void AArch64InstPrinter::printTSBHintOp(const MCInst *MI, unsigned OpNum,
+                                        const MCSubtargetInfo &STI,
+                                        raw_ostream &O) {
+  unsigned tsbhintop = MI->getOperand(OpNum).getImm() ^ 16;
+  auto TSB = AArch64TSB::lookupTSBByEncoding(tsbhintop);
+  if (TSB)
+    O << TSB->Name;
+  else
+    markup(O, Markup::Immediate) << '#' << formatImm(tsbhintop);
+}
+
 void AArch64InstPrinter::printCMHPriorityHintOp(const MCInst *MI,
                                                 unsigned OpNum,
                                                 const MCSubtargetInfo &STI,
@@ -1962,9 +1984,6 @@ void AArch64InstPrinter::printBarrierOption(const MCInst *MI, unsigned OpNo,
   if (Opcode == AArch64::ISB) {
     auto ISB = AArch64ISB::lookupISBByEncoding(Val);
     Name = ISB ? ISB->Name : "";
-  } else if (Opcode == AArch64::TSB) {
-    auto TSB = AArch64TSB::lookupTSBByEncoding(Val);
-    Name = TSB ? TSB->Name : "";
   } else {
     auto DB = AArch64DB::lookupDBByEncoding(Val);
     Name = DB ? DB->Name : "";
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.h b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.h
index 48e2e7e4eaa36..057f48d808456 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.h
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.h
@@ -153,6 +153,12 @@ class AArch64InstPrinter : public MCInstPrinter {
   void printBTIHintOp(const MCInst *MI, unsigned OpNum,
                       const MCSubtargetInfo &STI, raw_ostream &O);
 
+  void printSHUHintOp(const MCInst *MI, unsigned OpNum,
+                      const MCSubtargetInfo &STI, raw_ostream &O);
+
+  void printTSBHintOp(const MCInst *MI, unsigned OpNum,
+                      const MCSubtargetInfo &STI, raw_ostream &O);
+
   void printCMHPriorityHintOp(const MCInst *MI, unsigned OpNum,
                               const MCSubtargetInfo &STI, raw_ostream &O);
 
diff --git a/llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.h b/llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.h
index 1f18af709bd93..cda590782d512 100644
--- a/llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.h
+++ b/llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.h
@@ -726,7 +726,7 @@ struct PHint {
 #include "AArch64GenSystemOperands.inc"
 
 const PHint *lookupPHintByName(StringRef);
-const PHint *lookupPHintByEncoding(uint16_t);
+const PHint *lookupPHintByEncoding(uint8_t);
 } // namespace AArch64PHint
 
 namespace AArch64BTIHint {

>From cc60ab0de461f59bc0f9afa352da2df01d89e80d Mon Sep 17 00:00:00 2001
From: Jonathan Thackray <jonathan.thackray at arm.com>
Date: Tue, 28 Apr 2026 19:34:14 +0100
Subject: [PATCH 2/4] fixup! Add testcases for all missing HINTs

---
 .../MC/AArch64/armv8.2a-statistical-profiling.s    |  3 +++
 llvm/test/MC/AArch64/armv8.4a-trace.s              |  8 ++++++++
 llvm/test/MC/AArch64/armv9.5a-pauthlr.s            |  6 ++++++
 llvm/test/MC/AArch64/armv9.6a-pcdphint.s           | 10 +++++++++-
 llvm/test/MC/AArch64/armv9.7a-memsys.s             | 14 +++++++++++++-
 llvm/test/MC/AArch64/basic-a64-instructions.s      | 12 ++++++++++++
 llvm/test/MC/AArch64/ras-extension.s               |  3 +++
 llvm/test/MC/AArch64/speculation-barriers.s        |  2 ++
 8 files changed, 56 insertions(+), 2 deletions(-)

diff --git a/llvm/test/MC/AArch64/armv8.2a-statistical-profiling.s b/llvm/test/MC/AArch64/armv8.2a-statistical-profiling.s
index 25fff6ac56ae9..006e24d4f8255 100644
--- a/llvm/test/MC/AArch64/armv8.2a-statistical-profiling.s
+++ b/llvm/test/MC/AArch64/armv8.2a-statistical-profiling.s
@@ -9,6 +9,9 @@
 // NO_SPE_OUT-NOT: mrs
 // NO_SPE_OUT-NOT: psb
 
+  hint #17
+// CHECK: psb csync              // encoding: [0x3f,0x22,0x03,0xd5]
+
   psb csync
 // CHECK: psb csync              // encoding: [0x3f,0x22,0x03,0xd5]
 // NO_SPE:  instruction requires: spe
diff --git a/llvm/test/MC/AArch64/armv8.4a-trace.s b/llvm/test/MC/AArch64/armv8.4a-trace.s
index a7ce371a0a0b6..1fb0ef0deb167 100644
--- a/llvm/test/MC/AArch64/armv8.4a-trace.s
+++ b/llvm/test/MC/AArch64/armv8.4a-trace.s
@@ -10,6 +10,10 @@
 // RUN: not llvm-mc -triple aarch64-none-linux-gnu -show-encoding -mattr=+v8.4a,-tracev8.4 -o - %s 2>&1 | \
 // RUN: FileCheck %s --check-prefixes CHECK-ERROR
 
+// RUN: llvm-mc -triple aarch64-none-linux-gnu -filetype=obj -mattr=+tracev8.4 %s \
+// RUN:        | llvm-objdump -d --mattr=+tracev8.4 --no-print-imm-hex - \
+// RUN:        | FileCheck %s --check-prefix=CHECK-HINT-ALIAS
+
 //------------------------------------------------------------------------------
 // ARMV8.4-A Debug, Trace and PMU Extensions
 //------------------------------------------------------------------------------
@@ -22,6 +26,9 @@ mrs x0, TRFCR_EL1
 mrs x0, TRFCR_EL2
 mrs x0, TRFCR_EL12
 
+hint #18
+//CHECK-HINT-ALIAS: tsb csync
+
 tsb csync
 
 //CHECK:  msr TRFCR_EL1, x0           // encoding: [0x20,0x12,0x18,0xd5]
@@ -32,6 +39,7 @@ tsb csync
 //CHECK:  mrs x0, TRFCR_EL2           // encoding: [0x20,0x12,0x3c,0xd5]
 //CHECK:  mrs x0, TRFCR_EL12          // encoding: [0x20,0x12,0x3d,0xd5]
 
+//CHECK:  tsb csync                   // encoding: [0x5f,0x22,0x03,0xd5]
 //CHECK:  tsb csync                   // encoding: [0x5f,0x22,0x03,0xd5]
 
 //CHECK-ERROR: error: expected writable system register or pstate
diff --git a/llvm/test/MC/AArch64/armv9.5a-pauthlr.s b/llvm/test/MC/AArch64/armv9.5a-pauthlr.s
index 2655798852892..f554867705b9f 100644
--- a/llvm/test/MC/AArch64/armv9.5a-pauthlr.s
+++ b/llvm/test/MC/AArch64/armv9.5a-pauthlr.s
@@ -170,6 +170,12 @@ label1:
 // CHECK-ERROR: instruction requires: pauth-lr
 // CHECK-UNKNOWN: d65f0fe3 <unknown>
 
+  hint #39
+// CHECK-INST: hint #39
+// CHECK-DISASS: pacm
+// CHECK-ENCODING: [0xff,0x24,0x03,0xd5]
+// CHECK-UNKNOWN: d50324ff hint #39
+
   pacm
 // CHECK-INST: pacm
 // CHECK-DISASS: pacm
diff --git a/llvm/test/MC/AArch64/armv9.6a-pcdphint.s b/llvm/test/MC/AArch64/armv9.6a-pcdphint.s
index 46fe8981d1ebf..bb45eb60c1119 100644
--- a/llvm/test/MC/AArch64/armv9.6a-pcdphint.s
+++ b/llvm/test/MC/AArch64/armv9.6a-pcdphint.s
@@ -6,7 +6,15 @@
 // RUN: llvm-mc -triple=aarch64 -show-encoding < %s \
 // RUN:        | sed '/.text/d' | sed 's/.*encoding: //g' \
 // RUN:        | llvm-mc -triple=aarch64 -disassemble -show-encoding \
-// RUN:        | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
+// RUN:        | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST,CHECK-HINT-ALIAS
+
+hint #48
+// CHECK-HINT-ALIAS: stshh keep
+// CHECK-ENCODING: encoding: [0x1f,0x26,0x03,0xd5]
+
+hint #49
+// CHECK-HINT-ALIAS: stshh strm
+// CHECK-ENCODING: encoding: [0x3f,0x26,0x03,0xd5]
 
 stshh keep
 // CHECK-INST: stshh keep
diff --git a/llvm/test/MC/AArch64/armv9.7a-memsys.s b/llvm/test/MC/AArch64/armv9.7a-memsys.s
index ce3ac9bc7e8ee..f93c1ee2c4c2b 100644
--- a/llvm/test/MC/AArch64/armv9.7a-memsys.s
+++ b/llvm/test/MC/AArch64/armv9.7a-memsys.s
@@ -10,10 +10,22 @@
 // RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+lscp < %s \
 // RUN:        | sed '/.text/d' | sed 's/.*encoding: //g' \
 // RUN:        | llvm-mc -triple=aarch64 -mattr=+lscp -disassemble -show-encoding \
-// RUN:        | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
+// RUN:        | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST,CHECK-HINT-ALIAS
 
 // Armv9.7-A Contention Management Hints (FEAT_CMH).
 
+hint #50
+// CHECK-HINT-ALIAS: shuh
+// CHECK-ENCODING: encoding: [0x5f,0x26,0x03,0xd5]
+
+hint #51
+// CHECK-HINT-ALIAS: shuh  ph
+// CHECK-ENCODING: encoding: [0x7f,0x26,0x03,0xd5]
+
+hint #52
+// CHECK-HINT-ALIAS: stcph
+// CHECK-ENCODING: encoding: [0x9f,0x26,0x03,0xd5]
+
 shuh
 // CHECK-INST: shuh
 // CHECK-ENCODING: encoding: [0x5f,0x26,0x03,0xd5]
diff --git a/llvm/test/MC/AArch64/basic-a64-instructions.s b/llvm/test/MC/AArch64/basic-a64-instructions.s
index 093c09c67bacb..2855c9cf2e945 100644
--- a/llvm/test/MC/AArch64/basic-a64-instructions.s
+++ b/llvm/test/MC/AArch64/basic-a64-instructions.s
@@ -3460,8 +3460,20 @@ _func:
 //------------------------------------------------------------------------------
 
         hint #0
+        hint #1
+        hint #2
+        hint #3
+        hint #4
+        hint #5
+        hint #6
         hint #127
 // CHECK: nop                             // encoding: [0x1f,0x20,0x03,0xd5]
+// CHECK: yield                           // encoding: [0x3f,0x20,0x03,0xd5]
+// CHECK: wfe                             // encoding: [0x5f,0x20,0x03,0xd5]
+// CHECK: wfi                             // encoding: [0x7f,0x20,0x03,0xd5]
+// CHECK: sev                             // encoding: [0x9f,0x20,0x03,0xd5]
+// CHECK: sevl                            // encoding: [0xbf,0x20,0x03,0xd5]
+// CHECK: dgh                             // encoding: [0xdf,0x20,0x03,0xd5]
 // CHECK: hint    #{{127|0x7f}}           // encoding: [0xff,0x2f,0x03,0xd5]
 
         nop
diff --git a/llvm/test/MC/AArch64/ras-extension.s b/llvm/test/MC/AArch64/ras-extension.s
index 2400add87cdde..53cc26ee1ea31 100644
--- a/llvm/test/MC/AArch64/ras-extension.s
+++ b/llvm/test/MC/AArch64/ras-extension.s
@@ -5,6 +5,9 @@
 // RUN: llvm-mc -triple aarch64-none-linux-gnu -show-encoding -mcpu=cortex-r82 < %s | FileCheck %s
 // RUN: llvm-mc -triple aarch64-none-linux-gnu -show-encoding -mattr=+v8r < %s | FileCheck %s
 
+  hint #16
+// CHECK: esb                             // encoding: [0x1f,0x22,0x03,0xd5]
+
   esb
 // CHECK: esb                             // encoding: [0x1f,0x22,0x03,0xd5]
 
diff --git a/llvm/test/MC/AArch64/speculation-barriers.s b/llvm/test/MC/AArch64/speculation-barriers.s
index 0ab3fe7923efa..7c80d96227166 100644
--- a/llvm/test/MC/AArch64/speculation-barriers.s
+++ b/llvm/test/MC/AArch64/speculation-barriers.s
@@ -1,9 +1,11 @@
 // RUN: llvm-mc -triple aarch64-none-linux-gnu -show-encoding < %s | FileCheck %s
 
+hint #20
 csdb
 ssbb
 pssbb
 
+// CHECK: csdb   // encoding: [0x9f,0x22,0x03,0xd5]
 // CHECK: csdb   // encoding: [0x9f,0x22,0x03,0xd5]
 // CHECK: ssbb   // encoding: [0x9f,0x30,0x03,0xd5]
 // CHECK: pssbb  // encoding: [0x9f,0x34,0x03,0xd5]

>From 0aea0561464a308fe004c1170361c57b477f50c5 Mon Sep 17 00:00:00 2001
From: Jonathan Thackray <jonathan.thackray at arm.com>
Date: Thu, 18 Jun 2026 01:20:39 +0100
Subject: [PATCH 3/4] fixup! Address PR comments

---
 llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp |  5 +-
 .../lib/Target/AArch64/AArch64InstrFormats.td | 13 ++--
 llvm/lib/Target/AArch64/AArch64InstrInfo.td   | 17 ++---
 .../Target/AArch64/AArch64SystemOperands.td   | 72 +++++++------------
 .../AArch64/AsmParser/AArch64AsmParser.cpp    | 38 +++++-----
 .../MCTargetDesc/AArch64InstPrinter.cpp       | 18 ++---
 .../AArch64/MCTargetDesc/AArch64InstPrinter.h |  3 +
 .../Target/AArch64/Utils/AArch64BaseInfo.cpp  | 23 +++---
 .../Target/AArch64/Utils/AArch64BaseInfo.h    | 48 +++++++------
 llvm/test/MC/AArch64/armv8.4a-trace-error.s   |  6 +-
 10 files changed, 108 insertions(+), 135 deletions(-)

diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
index b93119393afe6..d77ebfdbab16b 100644
--- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
+++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
@@ -3202,10 +3202,7 @@ void AArch64AsmPrinter::emitInstruction(const MachineInstr *MI) {
     if (CurrentPatchableFunctionEntrySym &&
         CurrentPatchableFunctionEntrySym == CurrentFnBegin &&
         MI == &MF->front().front()) {
-      uint64_t Imm = MI->getOperand(0).getImm();
-      // Match only exact BTI encodings in HINT space.
-      if (Imm >= 32 && Imm < 64 &&
-          AArch64BTIHint::lookupBTIByEncoding(Imm ^ 32)) {
+      if (AArch64BTIHint::isHintSpaceBTI(MI->getOperand(0).getImm())) {
         MCInst Inst;
         MCInstLowering.Lower(MI, Inst);
         EmitToStreamer(*OutStreamer, Inst);
diff --git a/llvm/lib/Target/AArch64/AArch64InstrFormats.td b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
index 09be57953386d..cd01835c492c4 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrFormats.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
@@ -1870,9 +1870,9 @@ def phint_op : Operand<i32> {
     let ParserMatchClass = PHintInstOperand;
     let PrintMethod = "printPHintOp";
     let MCOperandPredicate = [{
-      if (!MCOp.isImm())
+      if (!MCOp.isImm() || MCOp.getImm() < 48)
         return false;
-      return AArch64PHint::lookupPHintByEncoding(MCOp.getImm()) != nullptr;
+      return AArch64PHint::lookupPHintByEncoding(MCOp.getImm() - 48) != nullptr;
     }];
     let OperandType = "OPERAND_IMMEDIATE";
     let MIOperandInfo = (ops i32imm: $policy);
@@ -1890,7 +1890,8 @@ def tsbhint_op : Operand<i32> {
     let MCOperandPredicate = [{
       if (!MCOp.isImm() || MCOp.getImm() < 16)
         return false;
-      return AArch64TSB::lookupTSBByEncoding(MCOp.getImm() - 16) != nullptr;
+      return AArch64TSBHint::lookupTSBHintByEncoding(MCOp.getImm() - 16) !=
+             nullptr;
     }];
     let OperandType = "OPERAND_IMMEDIATE";
     let MIOperandInfo = (ops i32imm: $policy);
@@ -1908,8 +1909,8 @@ def shuhint_op : Operand<i32> {
     let MCOperandPredicate = [{
       if (!MCOp.isImm() || MCOp.getImm() < 50)
         return false;
-      return AArch64CMHPriorityHint::lookupCMHPriorityHintByEncoding(
-                 MCOp.getImm() - 50) != nullptr;
+      return AArch64SHUHint::lookupSHUHintByEncoding(MCOp.getImm() - 50) !=
+             nullptr;
     }];
     let OperandType = "OPERAND_IMMEDIATE";
     let MIOperandInfo = (ops i32imm: $priority);
@@ -2012,7 +2013,7 @@ def btihint_op : Operand<i32> {
     // "bti" is an alias to "hint" only for certain values of CRm:Op2 fields.
     if (!MCOp.isImm())
       return false;
-    return AArch64BTIHint::lookupBTIByEncoding(MCOp.getImm() ^ 32) != nullptr;
+    return AArch64BTIHint::isHintSpaceBTI(MCOp.getImm());
   }];
   let OperandType = "OPERAND_IMMEDIATE";
 }
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index e0da5119acdbe..0be7748aa0dc3 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -1552,13 +1552,13 @@ let hasSideEffects = 1, isCodeGenOnly = 1, isTerminator = 1, isBarrier = 1 in {
 //===----------------------------------------------------------------------===//
 
 def HINT : HintI<"hint">;
-def : InstAlias<"yield",(HINT 0b001)>;
-def : InstAlias<"wfe",  (HINT 0b010)>;
-def : InstAlias<"wfi",  (HINT 0b011)>;
-def : InstAlias<"sev",  (HINT 0b100)>;
-def : InstAlias<"sevl", (HINT 0b101)>;
-def : InstAlias<"dgh",  (HINT 0b110)>;
-def : InstAlias<"esb",  (HINT 0b10000)>, Requires<[HasRAS]>;
+def : InstAlias<"yield",(HINT 1)>;
+def : InstAlias<"wfe",  (HINT 2)>;
+def : InstAlias<"wfi",  (HINT 3)>;
+def : InstAlias<"sev",  (HINT 4)>;
+def : InstAlias<"sevl", (HINT 5)>;
+def : InstAlias<"dgh",  (HINT 6)>;
+def : InstAlias<"esb",  (HINT 16)>, Requires<[HasRAS]>;
 def : InstAlias<"csdb", (HINT 20)>;
 
 let CRm = 0b0000, hasSideEffects = 0 in
@@ -1584,6 +1584,8 @@ def : InstAlias<"bti $op", (HINT btihint_op:$op)>, Requires<[HasBTI]>;
 // v8.2a Statistical Profiling extension
 def : InstAlias<"psb $op",  (HINT psbhint_op:$op)>, Requires<[HasSPE]>;
 
+def : InstAlias<"tsb $op", (HINT tsbhint_op:$op)>, Requires<[HasTRACEV8_4]>;
+
 // As far as LLVM is concerned this writes to the system's exclusive monitors.
 let mayLoad = 1, mayStore = 1 in
 def CLREX : CRmSystemI<imm0_15, 0b010, "clrex">;
@@ -1669,7 +1671,6 @@ def GCSPOPM_NoOp : InstAlias<"gcspopm", (GCSPOPM XZR)>, Requires<[HasGCS]>; // R
 
 def GCSB_DSYNC_disable : InstAlias<"gcsb\tdsync", (HINT 19), 0>;
 def GCSB_DSYNC         : InstAlias<"gcsb\tdsync", (HINT 19), 1>, Requires<[HasGCS]>;
-def : InstAlias<"tsb\t$op", (HINT tsbhint_op:$op)>, Requires<[HasTRACEV8_4]>;
 
 def : TokenAlias<"DSYNC", "dsync">;
 
diff --git a/llvm/lib/Target/AArch64/AArch64SystemOperands.td b/llvm/lib/Target/AArch64/AArch64SystemOperands.td
index d933a8f0029bb..b34e1232a11ad 100644
--- a/llvm/lib/Target/AArch64/AArch64SystemOperands.td
+++ b/llvm/lib/Target/AArch64/AArch64SystemOperands.td
@@ -338,37 +338,19 @@ def lookupISBByName : SearchIndex {
 def : ISB<"sy", 0xf>;
 
 //===----------------------------------------------------------------------===//
-// TSB (Trace synchronization barrier) instruction options.
+// TSB (Trace synchronization barrier) HINT instruction options.
 //===----------------------------------------------------------------------===//
 
-class TSB<string name, bits<4> encoding> {
+class TSBHint<string name, bits<4> encoding> : SearchableTable {
+  let SearchableFields = ["Name", "Encoding"];
+  let EnumValueField = "Encoding";
+
   string Name = name;
   bits<4> Encoding;
   let Encoding = encoding;
-
-  code Requires = [{ {AArch64::FeatureTRACEV8_4} }];
 }
 
-def TSBValues : GenericEnum {
-  let FilterClass = "TSB";
-  let NameField = "Name";
-  let ValueField = "Encoding";
-}
-
-def TSBsList : GenericTable {
-  let FilterClass = "TSB";
-  let Fields = ["Name", "Encoding", "Requires"];
-
-  let PrimaryKey = ["Encoding"];
-  let PrimaryKeyName = "lookupTSBByEncoding";
-}
-
-def lookupTSBByName : SearchIndex {
-  let Table = TSBsList;
-  let Key = ["Name"];
-}
-
-def : TSB<"csync", 2>;
+def : TSBHint<"csync", 2>;
 
 //===----------------------------------------------------------------------===//
 // PRFM (prefetch) instruction options.
@@ -829,6 +811,17 @@ class CMHPriorityHint<string name, bits<1> encoding> : SearchableTable {
 
 def : CMHPriorityHint<"ph", 0b1>;
 
+class SHUHint<string name, bits<1> encoding> : SearchableTable {
+  let SearchableFields = ["Name", "Encoding"];
+  let EnumValueField = "Encoding";
+
+  string Name = name;
+  bits<1> Encoding;
+  let Encoding = encoding;
+}
+
+def : SHUHint<"ph", 0b1>;
+
 
 //===----------------------------------------------------------------------===//
 // TIndex instruction options.
@@ -2450,34 +2443,17 @@ def : RWSysReg<"ACTLRALIAS_EL1",  0b11, 0b000, 0b0001, 0b0100, 0b101>;
 // v9.6a PCDPHINT instruction options.
 //===----------------------------------------------------------------------===//
 
-class PHint<string name, bits<7> encoding> {
+class PHint<string name, bits<1> encoding> : SearchableTable {
+  let SearchableFields = ["Name", "Encoding"];
+  let EnumValueField = "Encoding";
+
   string Name = name;
-  bits<7> Encoding;
+  bits<1> Encoding;
   let Encoding = encoding;
-  code Requires = [{ {} }];
-}
-
-def PHintValues : GenericEnum {
-  let FilterClass = "PHint";
-  let NameField = "Name";
-  let ValueField = "Encoding";
-}
-
-def PHintsList : GenericTable {
-  let FilterClass = "PHint";
-  let Fields = ["Name", "Encoding", "Requires"];
-
-  let PrimaryKey = ["Encoding"];
-  let PrimaryKeyName = "lookupPHintByEncoding";
-}
-
-def lookupPHintByName : SearchIndex {
-  let Table = PHintsList;
-  let Key = ["Name"];
 }
 
-def KEEP : PHint<"keep", 0b0110000>;
-def STRM : PHint<"strm", 0b0110001>;
+def : PHint<"keep", 0b0>;
+def : PHint<"strm", 0b1>;
 
 // v9.6a Realm management extension enhancements
 def : RWSysReg<"GPCBW_EL3", 0b11, 0b110, 0b0010, 0b0001, 0b101>;
diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
index 1e707656c388a..1feb25e5d5824 100644
--- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -2597,6 +2597,10 @@ class AArch64Operand : public MCParsedAsmOperand {
     unsigned operator()(unsigned Val) const { return Val | 32; }
   };
 
+  struct PHintEncoding {
+    unsigned operator()(unsigned Val) const { return Val + 48; }
+  };
+
   template <KindTy Kind, NamedHintOp AArch64Operand::*Member,
             typename Encode = IdentityHintEncoding>
   static std::unique_ptr<AArch64Operand>
@@ -2614,8 +2618,8 @@ class AArch64Operand : public MCParsedAsmOperand {
 
   static std::unique_ptr<AArch64Operand>
   CreatePHintInst(unsigned Val, StringRef Str, SMLoc S, MCContext &Ctx) {
-    return CreateNamedHintOperand<k_PHint, &AArch64Operand::PHint>(Val, Str, S,
-                                                                   Ctx);
+    return CreateNamedHintOperand<k_PHint, &AArch64Operand::PHint>(
+        Val, Str, S, Ctx, PHintEncoding{});
   }
 
   static std::unique_ptr<AArch64Operand> CreateSysCR(unsigned Val, SMLoc S,
@@ -4338,15 +4342,15 @@ ParseStatus AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
     return TokError("invalid operand for instruction");
 
   StringRef Operand = Tok.getString();
-  auto TSB = AArch64TSB::lookupTSBByName(Operand);
+  bool IsTSB = Mnemonic == "tsb" && Operand == "csync";
   auto DB = AArch64DB::lookupDBByName(Operand);
   // The only valid named option for ISB is 'sy'
   if (Mnemonic == "isb" && (!DB || DB->Encoding != AArch64DB::sy))
     return TokError("'sy' or #imm operand expected");
   // The only valid named option for TSB is 'csync'
-  if (Mnemonic == "tsb" && (!TSB || TSB->Encoding != AArch64TSB::csync))
+  if (Mnemonic == "tsb" && !IsTSB)
     return TokError("'csync' operand expected");
-  if (!DB && !TSB) {
+  if (!DB && !IsTSB) {
     if (Mnemonic == "dsb") {
       // This case is a no match here, but it might be matched by the nXS
       // variant.
@@ -4356,7 +4360,7 @@ ParseStatus AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
   }
 
   Operands.push_back(AArch64Operand::CreateBarrier(
-      DB ? DB->Encoding : TSB->Encoding, Tok.getString(), getLoc(),
+      DB ? DB->Encoding : 2, Tok.getString(), getLoc(),
       getContext(), false /*hasnXSModifier*/));
   Lex(); // Consume the option
 
@@ -4451,25 +4455,15 @@ AArch64AsmParser::tryParsePHintInstOperand(OperandVector &Operands) {
 }
 
 ParseStatus AArch64AsmParser::tryParseSHUHintOperand(OperandVector &Operands) {
-  return tryParseNamedHintOperand(
-      Operands, AArch64CMHPriorityHint::lookupCMHPriorityHintByName,
-      AArch64Operand::CreateSHUHint);
+  return tryParseNamedHintOperand(Operands,
+                                  AArch64SHUHint::lookupSHUHintByName,
+                                  AArch64Operand::CreateSHUHint);
 }
 
 ParseStatus AArch64AsmParser::tryParseTSBHintOperand(OperandVector &Operands) {
-  SMLoc S = getLoc();
-  const AsmToken &Tok = getTok();
-  if (Tok.isNot(AsmToken::Identifier))
-    return TokError("'csync' operand expected");
-
-  auto TSB = AArch64TSB::lookupTSBByName(Tok.getString());
-  if (!TSB || TSB->Encoding != AArch64TSB::csync)
-    return TokError("'csync' operand expected");
-
-  Operands.push_back(AArch64Operand::CreateTSBHint(
-      TSB->Encoding, Tok.getString(), S, getContext()));
-  Lex(); // Eat identifier token.
-  return ParseStatus::Success;
+  return tryParseNamedHintOperand(Operands,
+                                  AArch64TSBHint::lookupTSBHintByName,
+                                  AArch64Operand::CreateTSBHint);
 }
 
 /// tryParseNeonVectorRegister - Parse a vector register operand.
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp
index b901d579533da..be0e206f7469a 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp
@@ -1599,23 +1599,15 @@ void AArch64InstPrinter::printBTIHintOp(const MCInst *MI, unsigned OpNum,
 void AArch64InstPrinter::printSHUHintOp(const MCInst *MI, unsigned OpNum,
                                         const MCSubtargetInfo &STI,
                                         raw_ostream &O) {
-  unsigned shuhintop = MI->getOperand(OpNum).getImm() - 50;
-  auto SHU = AArch64CMHPriorityHint::lookupCMHPriorityHintByEncoding(shuhintop);
-  if (SHU)
-    O << SHU->Name;
-  else
-    markup(O, Markup::Immediate) << '#' << formatImm(shuhintop);
+  printNamedHintOp(MI->getOperand(OpNum).getImm(), O,
+                   AArch64SHUHint::lookupSHUHintByEncoding, decodeSHUHint);
 }
 
 void AArch64InstPrinter::printTSBHintOp(const MCInst *MI, unsigned OpNum,
                                         const MCSubtargetInfo &STI,
                                         raw_ostream &O) {
-  unsigned tsbhintop = MI->getOperand(OpNum).getImm() ^ 16;
-  auto TSB = AArch64TSB::lookupTSBByEncoding(tsbhintop);
-  if (TSB)
-    O << TSB->Name;
-  else
-    markup(O, Markup::Immediate) << '#' << formatImm(tsbhintop);
+  printNamedHintOp(MI->getOperand(OpNum).getImm(), O,
+                   AArch64TSBHint::lookupTSBHintByEncoding, decodeTSBHint);
 }
 
 void AArch64InstPrinter::printCMHPriorityHintOp(const MCInst *MI,
@@ -2280,5 +2272,5 @@ void AArch64InstPrinter::printPHintOp(const MCInst *MI, unsigned OpNum,
                                       const MCSubtargetInfo &STI,
                                       raw_ostream &O) {
   printNamedHintOp(MI->getOperand(OpNum).getImm(), O,
-                   AArch64PHint::lookupPHintByEncoding, decodeIdentityHint);
+                   AArch64PHint::lookupPHintByEncoding, decodePHint);
 }
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.h b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.h
index 057f48d808456..e2f6ae876dbb3 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.h
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.h
@@ -174,6 +174,9 @@ class AArch64InstPrinter : public MCInstPrinter {
 
   static unsigned decodeIdentityHint(unsigned Value) { return Value; }
   static unsigned decodeBTIHint(unsigned Value) { return Value ^ 32; }
+  static unsigned decodePHint(unsigned Value) { return Value - 48; }
+  static unsigned decodeSHUHint(unsigned Value) { return Value - 50; }
+  static unsigned decodeTSBHint(unsigned Value) { return Value ^ 16; }
 
   void printVectorList(const MCInst *MI, unsigned OpNum,
                        const MCSubtargetInfo &STI, raw_ostream &O,
diff --git a/llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.cpp b/llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.cpp
index c2fccc91cfec9..cee6affd42950 100644
--- a/llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.cpp
+++ b/llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.cpp
@@ -59,13 +59,6 @@ namespace llvm {
   }
 }
 
-namespace llvm {
-  namespace AArch64TSB {
-#define GET_TSBsList_IMPL
-#include "AArch64GenSystemOperands.inc"
-  }
-}
-
 namespace llvm {
   namespace AArch64PRFM {
 #define GET_PRFMsList_IMPL
@@ -126,11 +119,18 @@ namespace llvm {
 
 namespace llvm {
 namespace AArch64PHint {
-#define GET_PHintsList_IMPL
+#define GET_PHINT_IMPL
 #include "AArch64GenSystemOperands.inc"
 } // namespace AArch64PHint
 } // namespace llvm
 
+namespace llvm {
+namespace AArch64TSBHint {
+#define GET_TSBHINT_IMPL
+#include "AArch64GenSystemOperands.inc"
+} // namespace AArch64TSBHint
+} // namespace llvm
+
 namespace llvm {
   namespace AArch64BTIHint {
 #define GET_BTIsList_IMPL
@@ -145,6 +145,13 @@ namespace AArch64CMHPriorityHint {
 } // namespace AArch64CMHPriorityHint
 } // namespace llvm
 
+namespace llvm {
+namespace AArch64SHUHint {
+#define GET_SHUHINT_IMPL
+#include "AArch64GenSystemOperands.inc"
+} // namespace AArch64SHUHint
+} // namespace llvm
+
 namespace llvm {
 namespace AArch64TIndexHint {
 #define GET_TINDEX_IMPL
diff --git a/llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.h b/llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.h
index cda590782d512..ecd075a1463f7 100644
--- a/llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.h
+++ b/llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.h
@@ -541,15 +541,6 @@ namespace  AArch64ISB {
 #include "AArch64GenSystemOperands.inc"
 }
 
-namespace  AArch64TSB {
-  struct TSB : SysAlias {
-    using SysAlias::SysAlias;
-  };
-#define GET_TSBValues_DECL
-#define GET_TSBsList_DECL
-#include "AArch64GenSystemOperands.inc"
-}
-
 namespace AArch64PRFM {
   struct PRFM : SysAlias {
     using SysAlias::SysAlias;
@@ -710,25 +701,23 @@ namespace AArch64PSBHint {
 }
 
 namespace AArch64PHint {
-struct PHint {
-  const char *Name;
-  unsigned Encoding;
-  FeatureBitset FeaturesRequired;
-
-  bool haveFeatures(FeatureBitset ActiveFeatures) const {
-    return ActiveFeatures[llvm::AArch64::FeatureAll] ||
-           (FeaturesRequired & ActiveFeatures) == FeaturesRequired;
-  }
+struct PHint : SysAlias {
+  using SysAlias::SysAlias;
 };
 
-#define GET_PHintValues_DECL
-#define GET_PHintsList_DECL
+#define GET_PHINT_DECL
 #include "AArch64GenSystemOperands.inc"
-
-const PHint *lookupPHintByName(StringRef);
-const PHint *lookupPHintByEncoding(uint8_t);
 } // namespace AArch64PHint
 
+namespace AArch64TSBHint {
+struct TSBHint : SysAlias {
+  using SysAlias::SysAlias;
+};
+
+#define GET_TSBHINT_DECL
+#include "AArch64GenSystemOperands.inc"
+} // namespace AArch64TSBHint
+
 namespace AArch64BTIHint {
   struct BTI : SysAlias {
     using SysAlias::SysAlias;
@@ -736,6 +725,10 @@ namespace AArch64BTIHint {
 #define GET_BTIValues_DECL
 #define GET_BTIsList_DECL
 #include "AArch64GenSystemOperands.inc"
+
+inline static bool isHintSpaceBTI(int64_t Imm) {
+  return Imm >= 32 && Imm < 64 && lookupBTIByEncoding(Imm ^ 32);
+}
 }
 
 namespace AArch64CMHPriorityHint {
@@ -746,6 +739,15 @@ struct CMHPriorityHint : SysAlias {
 #include "AArch64GenSystemOperands.inc"
 } // namespace AArch64CMHPriorityHint
 
+namespace AArch64SHUHint {
+struct SHUHint : SysAlias {
+  using SysAlias::SysAlias;
+};
+
+#define GET_SHUHINT_DECL
+#include "AArch64GenSystemOperands.inc"
+} // namespace AArch64SHUHint
+
 namespace AArch64TIndexHint {
 struct TIndex : SysAlias {
   using SysAlias::SysAlias;
diff --git a/llvm/test/MC/AArch64/armv8.4a-trace-error.s b/llvm/test/MC/AArch64/armv8.4a-trace-error.s
index 99b61280a3180..ec166c715b0ea 100644
--- a/llvm/test/MC/AArch64/armv8.4a-trace-error.s
+++ b/llvm/test/MC/AArch64/armv8.4a-trace-error.s
@@ -12,12 +12,12 @@ tsb 0
 //CHECK-ERROR: error: too few operands for instruction
 //CHECK-ERROR: tsb
 //CHECK-ERROR: ^
-//CHECK-ERROR: error: 'csync' operand expected
+//CHECK-ERROR: error: invalid operand for instruction
 //CHECK-ERROR: tsb foo
 //CHECK-ERROR:     ^
-//CHECK-ERROR: error: 'csync' operand expected
+//CHECK-ERROR: error: invalid operand for instruction
 //CHECK-ERROR: tsb #0
 //CHECK-ERROR:     ^
-//CHECK-ERROR: error: 'csync' operand expected
+//CHECK-ERROR: error: invalid operand for instruction
 //CHECK-ERROR: tsb 0
 //CHECK-ERROR:     ^

>From 7a1ab765e13aca26636ef9f7f28634c33c6f58e7 Mon Sep 17 00:00:00 2001
From: Jonathan Thackray <jonathan.thackray at arm.com>
Date: Thu, 18 Jun 2026 07:56:56 +0100
Subject: [PATCH 4/4] fixup! Convert PSB to use PSBHint for consistency

---
 .../lib/Target/AArch64/AArch64InstrFormats.td |  5 ++--
 .../Target/AArch64/AArch64SystemOperands.td   | 30 +++++--------------
 .../AArch64/AsmParser/AArch64AsmParser.cpp    | 22 ++++++++++----
 .../MCTargetDesc/AArch64InstPrinter.cpp       |  2 +-
 .../AArch64/MCTargetDesc/AArch64InstPrinter.h |  1 +
 .../Target/AArch64/Utils/AArch64BaseInfo.cpp  |  8 ++---
 .../Target/AArch64/Utils/AArch64BaseInfo.h    | 11 ++++---
 7 files changed, 38 insertions(+), 41 deletions(-)

diff --git a/llvm/lib/Target/AArch64/AArch64InstrFormats.td b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
index cd01835c492c4..822c3ee3da276 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrFormats.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
@@ -1995,9 +1995,10 @@ def psbhint_op : Operand<i32> {
   let MCOperandPredicate = [{
     // Check, if operand is valid, to fix exhaustive aliasing in disassembly.
     // "psb" is an alias to "hint" only for certain values of CRm:Op2 fields.
-    if (!MCOp.isImm())
+    if (!MCOp.isImm() || MCOp.getImm() < 16)
       return false;
-    return AArch64PSBHint::lookupPSBByEncoding(MCOp.getImm()) != nullptr;
+    return AArch64PSBHint::lookupPSBHintByEncoding(MCOp.getImm() - 16) !=
+           nullptr;
   }];
   let OperandType = "OPERAND_IMMEDIATE";
 }
diff --git a/llvm/lib/Target/AArch64/AArch64SystemOperands.td b/llvm/lib/Target/AArch64/AArch64SystemOperands.td
index b34e1232a11ad..91801c8041777 100644
--- a/llvm/lib/Target/AArch64/AArch64SystemOperands.td
+++ b/llvm/lib/Target/AArch64/AArch64SystemOperands.td
@@ -732,35 +732,19 @@ def : SVCR<"SVCRSMZA", 0b011>;
 }
 
 //===----------------------------------------------------------------------===//
-// PSB instruction options.
+// PSB (Profiling synchronization barrier) HINT instruction options.
 //===----------------------------------------------------------------------===//
 
-class PSB<string name, bits<5> encoding> {
+class PSBHint<string name, bits<4> encoding> : SearchableTable {
+  let SearchableFields = ["Name", "Encoding"];
+  let EnumValueField = "Encoding";
+
   string Name = name;
-  bits<5> Encoding;
+  bits<4> Encoding;
   let Encoding = encoding;
 }
 
-def PSBValues : GenericEnum {
-  let FilterClass = "PSB";
-  let NameField = "Name";
-  let ValueField = "Encoding";
-}
-
-def PSBsList : GenericTable {
-  let FilterClass = "PSB";
-  let Fields = ["Name", "Encoding"];
-
-  let PrimaryKey = ["Encoding"];
-  let PrimaryKeyName = "lookupPSBByEncoding";
-}
-
-def lookupPSBByName : SearchIndex {
-  let Table = PSBsList;
-  let Key = ["Name"];
-}
-
-def : PSB<"csync", 0x11>;
+def : PSBHint<"csync", 1>;
 
 //===----------------------------------------------------------------------===//
 // BTI instruction options.
diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
index 1feb25e5d5824..27e79f53c9243 100644
--- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -2601,6 +2601,18 @@ class AArch64Operand : public MCParsedAsmOperand {
     unsigned operator()(unsigned Val) const { return Val + 48; }
   };
 
+  struct PSBHintEncoding {
+    unsigned operator()(unsigned Val) const { return Val + 16; }
+  };
+
+  struct SHUHintEncoding {
+    unsigned operator()(unsigned Val) const { return Val + 50; }
+  };
+
+  struct TSBHintEncoding {
+    unsigned operator()(unsigned Val) const { return Val | 16; }
+  };
+
   template <KindTy Kind, NamedHintOp AArch64Operand::*Member,
             typename Encode = IdentityHintEncoding>
   static std::unique_ptr<AArch64Operand>
@@ -2648,8 +2660,8 @@ class AArch64Operand : public MCParsedAsmOperand {
                                                        StringRef Str,
                                                        SMLoc S,
                                                        MCContext &Ctx) {
-    return CreateNamedHintOperand<k_PSBHint, &AArch64Operand::PSBHint>(Val, Str,
-                                                                       S, Ctx);
+    return CreateNamedHintOperand<k_PSBHint, &AArch64Operand::PSBHint>(
+        Val, Str, S, Ctx, PSBHintEncoding{});
   }
 
   static std::unique_ptr<AArch64Operand> CreateBTIHint(unsigned Val,
@@ -2663,13 +2675,13 @@ class AArch64Operand : public MCParsedAsmOperand {
   static std::unique_ptr<AArch64Operand>
   CreateSHUHint(unsigned Val, StringRef Str, SMLoc S, MCContext &Ctx) {
     return CreateNamedHintOperand<k_SHUHint, &AArch64Operand::SHUHint>(
-        Val, Str, S, Ctx, [](unsigned EncodedVal) { return EncodedVal + 50; });
+        Val, Str, S, Ctx, SHUHintEncoding{});
   }
 
   static std::unique_ptr<AArch64Operand>
   CreateTSBHint(unsigned Val, StringRef Str, SMLoc S, MCContext &Ctx) {
     return CreateNamedHintOperand<k_TSBHint, &AArch64Operand::TSBHint>(
-        Val, Str, S, Ctx, [](unsigned EncodedVal) { return EncodedVal | 16; });
+        Val, Str, S, Ctx, TSBHintEncoding{});
   }
 
   static std::unique_ptr<AArch64Operand>
@@ -3365,7 +3377,7 @@ ParseStatus AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) {
 
 /// tryParsePSBHint - Try to parse a PSB operand, mapped to Hint command
 ParseStatus AArch64AsmParser::tryParsePSBHint(OperandVector &Operands) {
-  return tryParseNamedHintOperand(Operands, AArch64PSBHint::lookupPSBByName,
+  return tryParseNamedHintOperand(Operands, AArch64PSBHint::lookupPSBHintByName,
                                   AArch64Operand::CreatePSBHint);
 }
 
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp
index be0e206f7469a..4235f1724b0a1 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp
@@ -1586,7 +1586,7 @@ void AArch64InstPrinter::printPSBHintOp(const MCInst *MI, unsigned OpNum,
                                         const MCSubtargetInfo &STI,
                                         raw_ostream &O) {
   printNamedHintOp(MI->getOperand(OpNum).getImm(), O,
-                   AArch64PSBHint::lookupPSBByEncoding, decodeIdentityHint);
+                   AArch64PSBHint::lookupPSBHintByEncoding, decodePSBHint);
 }
 
 void AArch64InstPrinter::printBTIHintOp(const MCInst *MI, unsigned OpNum,
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.h b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.h
index e2f6ae876dbb3..9877a6aba9684 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.h
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.h
@@ -174,6 +174,7 @@ class AArch64InstPrinter : public MCInstPrinter {
 
   static unsigned decodeIdentityHint(unsigned Value) { return Value; }
   static unsigned decodeBTIHint(unsigned Value) { return Value ^ 32; }
+  static unsigned decodePSBHint(unsigned Value) { return Value - 16; }
   static unsigned decodePHint(unsigned Value) { return Value - 48; }
   static unsigned decodeSHUHint(unsigned Value) { return Value - 50; }
   static unsigned decodeTSBHint(unsigned Value) { return Value ^ 16; }
diff --git a/llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.cpp b/llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.cpp
index cee6affd42950..37132b08a0782 100644
--- a/llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.cpp
+++ b/llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.cpp
@@ -111,11 +111,11 @@ namespace llvm {
 }
 
 namespace llvm {
-  namespace AArch64PSBHint {
-#define GET_PSBsList_IMPL
+namespace AArch64PSBHint {
+#define GET_PSBHINT_IMPL
 #include "AArch64GenSystemOperands.inc"
-  }
-}
+} // namespace AArch64PSBHint
+} // namespace llvm
 
 namespace llvm {
 namespace AArch64PHint {
diff --git a/llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.h b/llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.h
index ecd075a1463f7..3f68affb20814 100644
--- a/llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.h
+++ b/llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.h
@@ -692,13 +692,12 @@ namespace AArch64PState {
 }
 
 namespace AArch64PSBHint {
-  struct PSB : SysAlias {
-    using SysAlias::SysAlias;
-  };
-#define GET_PSBValues_DECL
-#define GET_PSBsList_DECL
+struct PSBHint : SysAlias {
+  using SysAlias::SysAlias;
+};
+#define GET_PSBHINT_DECL
 #include "AArch64GenSystemOperands.inc"
-}
+} // namespace AArch64PSBHint
 
 namespace AArch64PHint {
 struct PHint : SysAlias {



More information about the llvm-branch-commits mailing list