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
