Author: Jonathan Thackray
Date: 2026-07-02T10:40:33+01:00
New Revision: ce787718c3c82255825ebe5f95740c24df55f7d0

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

LOG: [AArch64][llvm] Add support for FEAT_HINTE for Armv9.6 onwards (#206905)

Add support for `FEAT_HINTE`, as defined in the Arm ARM M.c edition[1]

This defines the Extended Hint instruction space. `FEAT_HINTE` is
optional from Armv9.0, and mandatory from Armv9.6.

Add MC coverage for assembly, disassembly, diagnostics, generic sysreg
fallback behavior, Clang driver handling, and target parser extension
mapping.

[1] https://developer.arm.com/documentation/ddi0487/latest

Added: 
    llvm/test/MC/AArch64/hinte-diagnostics.s
    llvm/test/MC/AArch64/hinte.s

Modified: 
    clang/test/Driver/aarch64-v96a.c
    clang/test/Driver/print-supported-extensions-aarch64.c
    llvm/lib/Target/AArch64/AArch64Features.td
    llvm/lib/Target/AArch64/AArch64InstrFormats.td
    llvm/lib/Target/AArch64/AArch64InstrInfo.td
    llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
    llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
    llvm/unittests/TargetParser/TargetParserTest.cpp

Removed: 
    


################################################################################
diff  --git a/clang/test/Driver/aarch64-v96a.c 
b/clang/test/Driver/aarch64-v96a.c
index 6f43cfd8d36e5..6025b87159007 100644
--- a/clang/test/Driver/aarch64-v96a.c
+++ b/clang/test/Driver/aarch64-v96a.c
@@ -66,3 +66,7 @@
 // RUN: %clang -target aarch64 -march=armv9.6-a+pops -### -c %s 2>&1 | 
FileCheck -check-prefix=V96A-POPS %s
 // V96A-POPS: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "generic" 
"-target-feature" "+v9.6a"{{.*}} "-target-feature" "+pops"
 //
+// RUN: %clang -target aarch64 -march=armv9.6a+hinte -### -c %s 2>&1 | 
FileCheck -check-prefix=V96A-hinte %s
+// RUN: %clang -target aarch64 -march=armv9.6-a+hinte -### -c %s 2>&1 | 
FileCheck -check-prefix=V96A-hinte %s
+// V96A-hinte: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "generic" 
"-target-feature" "+v9.6a"{{.*}} "-target-feature" "+hinte"
+//

diff  --git a/clang/test/Driver/print-supported-extensions-aarch64.c 
b/clang/test/Driver/print-supported-extensions-aarch64.c
index 89db42f70f201..1e2882550c81f 100644
--- a/clang/test/Driver/print-supported-extensions-aarch64.c
+++ b/clang/test/Driver/print-supported-extensions-aarch64.c
@@ -38,6 +38,7 @@
 // CHECK-NEXT:     gcie                FEAT_GCIE                               
               Enable GICv5 (Generic Interrupt Controller) CPU Interface 
Extension
 // CHECK-NEXT:     gcs                 FEAT_GCS                                
               Enable Armv9.4-A Guarded Call Stack Extension
 // CHECK-NEXT:     hbc                 FEAT_HBC                                
               Enable Armv8.8-A Hinted Conditional Branches Extension
+// CHECK-NEXT:     hinte               FEAT_HINTE                              
               Enable extended A64 hint instruction space
 // CHECK-NEXT:     i8mm                FEAT_I8MM                               
               Enable Matrix Multiply Int8 Extension
 // CHECK-NEXT:     ite                 FEAT_ITE                                
               Enable Armv9.4-A Instrumentation Extension
 // CHECK-NEXT:     jscvt               FEAT_JSCVT                              
               Enable Armv8.3-A JavaScript FP conversion instructions

diff  --git a/llvm/lib/Target/AArch64/AArch64Features.td 
b/llvm/lib/Target/AArch64/AArch64Features.td
index d8b06279977e8..fc23318c0582d 100644
--- a/llvm/lib/Target/AArch64/AArch64Features.td
+++ b/llvm/lib/Target/AArch64/AArch64Features.td
@@ -582,6 +582,9 @@ def FeatureSME_TMOP: ExtensionWithMArch<"sme-tmop", 
"SME_TMOP", "FEAT_SME_TMOP",
 def FeatureSSVE_FEXPA : ExtensionWithMArch<"ssve-fexpa", "SSVE_FEXPA", 
"FEAT_SSVE_FEXPA",
   "Enable SVE FEXPA instruction in Streaming SVE mode", [FeatureSME2]>;
 
+def FeatureHINTE: ExtensionWithMArch<"hinte", "HINTE", "FEAT_HINTE",
+  "Enable extended A64 hint instruction space">;
+
 
//===----------------------------------------------------------------------===//
 //  Armv9.7 Architecture Extensions
 
//===----------------------------------------------------------------------===//
@@ -1090,9 +1093,9 @@ def HasV9_5aOps : Architecture64<9, 5, "a", "v9.5a",
   [HasV9_4aOps, FeatureCPA],
   !listconcat(HasV9_4aOps.DefaultExts, [FeatureCPA,  FeatureLUT, 
FeatureFAMINMAX])>;
 def HasV9_6aOps : Architecture64<9, 6, "a", "v9.6a",
-  [HasV9_5aOps, FeatureCMPBR, FeatureLSUI, FeatureOCCMO],
+  [HasV9_5aOps, FeatureCMPBR, FeatureLSUI, FeatureOCCMO, FeatureHINTE],
   !listconcat(HasV9_5aOps.DefaultExts, [FeatureCMPBR,
-    FeatureLSUI, FeatureOCCMO])>;
+    FeatureLSUI, FeatureOCCMO, FeatureHINTE])>;
 def HasV9_7aOps : Architecture64<9, 7, "a", "v9.7a",
   [HasV9_6aOps, FeatureSVE2p3, FeatureFPRCVT, FeatureF16F32DOT],
   !listconcat(HasV9_6aOps.DefaultExts, [FeatureSVE2p3, FeatureFPRCVT,

diff  --git a/llvm/lib/Target/AArch64/AArch64InstrFormats.td 
b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
index daf53c99988b0..8403039b72654 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrFormats.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
@@ -447,6 +447,19 @@ def uimm16 : Operand<i16>, ImmLeaf<i16, [{return Imm >= 0 
&& Imm < 65536;}]>{
   let OperandType = "OPERAND_IMMEDIATE";
 }
 
+def HinteUImm16Operand : AsmOperandClass {
+  let Name = "HinteUImm16";
+  let DiagnosticType = "InvalidHinteUImm16";
+  let RenderMethod = "addImmOperands";
+  let PredicateMethod = "isHinteUImm16";
+}
+
+def hinte_uimm16 : Operand<i64> {
+  let ParserMatchClass = HinteUImm16Operand;
+  let OperandType = "OPERAND_IMMEDIATE";
+  let DecoderMethod = "DecodeHinteUImm16";
+}
+
 def uimm6_64b : Operand<i64>, ImmLeaf<i64, [{ return Imm >= 0 && Imm < 64; }]> 
{
     let ParserMatchClass = UImm6Operand;
   let OperandType = "OPERAND_IMMEDIATE";
@@ -1861,6 +1874,20 @@ let mayStore = 1, mayLoad = 1, hasSideEffects = 1 in
     let Inst{11-5} = imm;
   }
 
+// Hint instructions (extended).
+class HintE<string mnemonic>
+    : I<(outs), (ins hinte_uimm16:$imm16), mnemonic, "\t$imm16", "", []>,
+      Sched<[WriteHint]> {
+  bits<16> imm16;
+  let Inst{31-22} = 0b1101010100;
+  let Inst{21}    = imm16{15};
+  let Inst{20-19} = 0b00;
+  let Inst{18-16} = imm16{14-12};
+  let Inst{15-12} = 0b0010;
+  let Inst{11-5}  = imm16{11-5};
+  let Inst{4-0}   = imm16{4-0};
+}
+
 def PHintInstOperand : AsmOperandClass {
     let Name = "PHint";
     let ParserMethod = "tryParsePHintInstOperand";

diff  --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td 
b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index a898d1e228053..25a5d458830ad 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -219,6 +219,8 @@ def HasLSUI          : Predicate<"Subtarget->hasLSUI()">,
                                  AssemblerPredicateWithAll<(all_of 
FeatureLSUI), "lsui">;
 def HasOCCMO         : Predicate<"Subtarget->hasOCCMO()">,
                                  AssemblerPredicateWithAll<(all_of 
FeatureOCCMO), "occmo">;
+def HasHINTE         : Predicate<"Subtarget->hasHINTE()">,
+                                 AssemblerPredicateWithAll<(all_of 
FeatureHINTE), "hinte">;
 def HasLSCP          : Predicate<"Subtarget->hasLSCP()">,
                                  AssemblerPredicateWithAll<(all_of 
FeatureLSCP), "lscp">;
 def HasSVE2p2        : Predicate<"Subtarget->isSVEAvailable() && 
Subtarget->hasSVE2p2()">,
@@ -1552,6 +1554,9 @@ let hasSideEffects = 1, isCodeGenOnly = 1, isTerminator = 
1, isBarrier = 1 in {
 
//===----------------------------------------------------------------------===//
 
 def HINT : HintI<"hint">;
+let Predicates = [HasHINTE] in
+def HINTE : HintE<"hinte">;
+
 def : InstAlias<"yield",(HINT 0b001)>;
 def : InstAlias<"wfe",  (HINT 0b010)>;
 def : InstAlias<"wfi",  (HINT 0b011)>;

diff  --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp 
b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
index d14dfa7ccfd06..0bfec39182df7 100644
--- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -990,6 +990,17 @@ class AArch64Operand : public MCParsedAsmOperand {
     return (Val >= N && Val <= M);
   }
 
+  bool isHinteUImm16() const {
+    if (!isImm())
+      return false;
+    const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
+    if (!MCE)
+      return false;
+    int64_t Val = MCE->getValue();
+    return Val >= 0 && Val <= 65535 &&
+           !(Val >= 12319 && Val <= 16383 && ((Val - 12319) % 32) == 0);
+  }
+
   // NOTE: Also used for isLogicalImmNot as anything that can be represented as
   // a logical immediate can always be represented when inverted.
   template <typename T>
@@ -3955,6 +3966,7 @@ constexpr EnumStringDef<FeatureBitset> ExtensionDefs[] = {
     {{"poe2"}, {AArch64::FeatureS1POE2}},
     {{"tev"}, {AArch64::FeatureTEV}},
     {{"btie"}, {AArch64::FeatureBTIE}},
+    {{"hinte"}, {AArch64::FeatureHINTE}},
     {{"dit"}, {AArch64::FeatureDIT}},
     {{"brbe"}, {AArch64::FeatureBRBE}},
     {{"bti"}, {AArch64::FeatureBranchTargetId}},
@@ -6310,6 +6322,11 @@ bool AArch64AsmParser::showMatchError(SMLoc Loc, 
unsigned ErrCode,
     return Error(Loc, "immediate must be an integer in range [0, 255].");
   case Match_InvalidImm0_65535:
     return Error(Loc, "immediate must be an integer in range [0, 65535].");
+  case Match_InvalidHinteUImm16:
+    return Error(Loc,
+                 "immediate must be an integer in range [0, 65535], excluding "
+                 "values in range [12319, 16383] where (value - 12319) is a "
+                 "multiple of 32.");
   case Match_InvalidImm1_8:
     return Error(Loc, "immediate must be an integer in range [1, 8].");
   case Match_InvalidImm1_16:
@@ -7089,6 +7106,7 @@ bool AArch64AsmParser::matchAndEmitInstruction(SMLoc 
IDLoc, unsigned &Opcode,
   case Match_InvalidImm0_127:
   case Match_InvalidImm0_255:
   case Match_InvalidImm0_65535:
+  case Match_InvalidHinteUImm16:
   case Match_InvalidImm1_8:
   case Match_InvalidImm1_16:
   case Match_InvalidImm1_32:

diff  --git a/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp 
b/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
index 15f40e2fa9f1b..d98478b385e79 100644
--- a/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
+++ b/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
@@ -1468,6 +1468,16 @@ static DecodeStatus DecodeImm8OptLsl(MCInst &Inst, 
unsigned Imm, uint64_t Addr,
   return Success;
 }
 
+static DecodeStatus DecodeHinteUImm16(MCInst &Inst, unsigned Imm, uint64_t 
Addr,
+                                      const MCDisassembler *Decoder) {
+  if (Imm > 65535 ||
+      (Imm >= 12319 && Imm <= 16383 && ((Imm - 12319) % 32) == 0))
+    return Fail;
+
+  Inst.addOperand(MCOperand::createImm(Imm));
+  return Success;
+}
+
 // Decode uimm4 ranged from 1-16.
 static DecodeStatus DecodeSVEIncDecImm(MCInst &Inst, unsigned Imm,
                                        uint64_t Addr,

diff  --git a/llvm/test/MC/AArch64/hinte-diagnostics.s 
b/llvm/test/MC/AArch64/hinte-diagnostics.s
new file mode 100644
index 0000000000000..90dd9a4e9d691
--- /dev/null
+++ b/llvm/test/MC/AArch64/hinte-diagnostics.s
@@ -0,0 +1,17 @@
+// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+hinte < %s 2>&1 \
+// RUN:   | FileCheck %s --check-prefix=CHECK-ERROR
+
+hinte #-1
+// CHECK-ERROR: error: immediate must be an integer in range [0, 65535], 
excluding values in range [12319, 16383] where (value - 12319) is a multiple of 
32.
+
+hinte #65536
+// CHECK-ERROR: error: immediate must be an integer in range [0, 65535], 
excluding values in range [12319, 16383] where (value - 12319) is a multiple of 
32.
+
+hinte #12319
+// CHECK-ERROR: error: immediate must be an integer in range [0, 65535], 
excluding values in range [12319, 16383] where (value - 12319) is a multiple of 
32.
+
+hinte #12383
+// CHECK-ERROR: error: immediate must be an integer in range [0, 65535], 
excluding values in range [12319, 16383] where (value - 12319) is a multiple of 
32.
+
+hinte #16383
+// CHECK-ERROR: error: immediate must be an integer in range [0, 65535], 
excluding values in range [12319, 16383] where (value - 12319) is a multiple of 
32.

diff  --git a/llvm/test/MC/AArch64/hinte.s b/llvm/test/MC/AArch64/hinte.s
new file mode 100644
index 0000000000000..e3219ea49e846
--- /dev/null
+++ b/llvm/test/MC/AArch64/hinte.s
@@ -0,0 +1,56 @@
+// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+hinte < %s \
+// RUN:   | FileCheck %s --check-prefixes=CHECK-INST,CHECK-ASM,CHECK-ENCODING
+// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \
+// RUN:   | FileCheck %s --check-prefix=CHECK-ERROR
+// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+hinte < %s \
+// RUN:   | llvm-objdump -d --mattr=+hinte --no-print-imm-hex - \
+// RUN:   | FileCheck %s --check-prefix=CHECK-INST
+// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+hinte < %s \
+// RUN:   | llvm-objdump -d --mattr=-hinte --no-print-imm-hex - \
+// RUN:   | FileCheck %s --check-prefix=CHECK-GENERIC
+
+hinte #0
+// CHECK-INST: hinte #0
+// CHECK-ENCODING: encoding: [0x00,0x20,0x00,0xd5]
+// CHECK-ERROR: instruction requires: hinte
+// CHECK-GENERIC: msr S0_0_C2_C0_0, x0
+
+hinte #16352
+// CHECK-INST: hinte #16352
+// CHECK-ENCODING: encoding: [0xe0,0x2f,0x03,0xd5]
+// CHECK-ERROR: instruction requires: hinte
+// CHECK-GENERIC: msr S0_3_C2_C15_7, x0
+
+hinte #16353
+// CHECK-INST: hinte #16353
+// CHECK-ENCODING: encoding: [0xe1,0x2f,0x03,0xd5]
+// CHECK-ERROR: instruction requires: hinte
+// CHECK-GENERIC: msr S0_3_C2_C15_7, x1
+
+hinte #21845
+// CHECK-INST: hinte #21845
+// CHECK-ENCODING: encoding: [0x55,0x25,0x05,0xd5]
+// CHECK-ERROR: instruction requires: hinte
+// CHECK-GENERIC: msr S0_5_C2_C5_2, x21
+
+hinte #43690
+// CHECK-INST: hinte #43690
+// CHECK-ENCODING: encoding: [0xaa,0x2a,0x22,0xd5]
+// CHECK-ERROR: instruction requires: hinte
+// CHECK-GENERIC: mrs x10, S0_2_C2_C10_5
+
+hinte #65535
+// CHECK-INST: hinte #65535
+// CHECK-ENCODING: encoding: [0xff,0x2f,0x27,0xd5]
+// CHECK-ERROR: instruction requires: hinte
+// CHECK-GENERIC: mrs xzr, S0_7_C2_C15_7
+
+msr S0_0_C2_C0_0, x0
+// CHECK-ASM: msr S0_0_C2_C0_0, x0
+// CHECK-ENCODING: encoding: [0x00,0x20,0x00,0xd5]
+// CHECK-ERROR: msr S0_0_C2_C0_0, x0
+
+mrs x0, S0_0_C2_C0_0
+// CHECK-ASM: mrs x0, S0_0_C2_C0_0
+// CHECK-ENCODING: encoding: [0x00,0x20,0x20,0xd5]
+// CHECK-ERROR: mrs x0, S0_0_C2_C0_0

diff  --git a/llvm/unittests/TargetParser/TargetParserTest.cpp 
b/llvm/unittests/TargetParser/TargetParserTest.cpp
index c91b6b3ac08d8..a975c3039e7f4 100644
--- a/llvm/unittests/TargetParser/TargetParserTest.cpp
+++ b/llvm/unittests/TargetParser/TargetParserTest.cpp
@@ -1435,6 +1435,9 @@ TEST(TargetParserTest, testAArch64Extension) {
   EXPECT_FALSE(testAArch64Extension(AArch64::ARMV8_3A, "fp16fml"));
   EXPECT_FALSE(testAArch64Extension(AArch64::ARMV8_4A, "fp16"));
   EXPECT_FALSE(testAArch64Extension(AArch64::ARMV8_4A, "fp16fml"));
+  EXPECT_FALSE(testAArch64Extension(AArch64::ARMV9_5A, "hinte"));
+  EXPECT_TRUE(testAArch64Extension(AArch64::ARMV9_6A, "hinte"));
+  EXPECT_TRUE(testAArch64Extension(AArch64::ARMV9_7A, "hinte"));
 }
 
 TEST(TargetParserTest, AArch64ExtensionFeatures) {
@@ -1493,7 +1496,7 @@ TEST(TargetParserTest, AArch64ExtensionFeatures) {
       AArch64::AEK_POE2,         AArch64::AEK_TEV,
       AArch64::AEK_BTIE,         AArch64::AEK_F64MM,
       AArch64::AEK_POPS,         AArch64::AEK_SVESM4,
-      AArch64::AEK_MTETC,
+      AArch64::AEK_MTETC,        AArch64::AEK_HINTE,
   };
 
   std::vector<StringRef> Features;
@@ -1617,6 +1620,7 @@ TEST(TargetParserTest, AArch64ExtensionFeatures) {
   EXPECT_TRUE(llvm::is_contained(Features, "+poe2"));
   EXPECT_TRUE(llvm::is_contained(Features, "+tev"));
   EXPECT_TRUE(llvm::is_contained(Features, "+btie"));
+  EXPECT_TRUE(llvm::is_contained(Features, "+hinte"));
 
   // Assuming we listed every extension above, this should produce the same
   // result.
@@ -1795,6 +1799,7 @@ TEST(TargetParserTest, AArch64ArchExtFeature) {
       {"poe2", "nopoe2", "+poe2", "-poe2"},
       {"tev", "notev", "+tev", "-tev"},
       {"btie", "nobtie", "+btie", "-btie"},
+      {"hinte", "nohinte", "+hinte", "-hinte"},
   };
 
   for (unsigned i = 0; i < std::size(ArchExt); i++) {


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to