Skip to content

Commit f28224b

Browse files
[AArch64][llvm] Armv9.7-A: Add support for FEAT_CMH and FEAT_LSCP (#163155)
Add the following instructions to support: * `FEAT_CMH`: Contention Management Hints extension * `SHUH` instruction * `FEAT_LSCP`: Load-acquire and store-release pair extension * `STLP` instruction * `LDAP` instruction * `LDAPP` instruction and system registers: - `TLBIDIDR_EL1` - `VTLBID<n>_EL2` - `VTLBIDOS<n>_EL2` as documented here: * https://developer.arm.com/documentation/109697/2025_09/2025-Architecture-Extensions * https://developer.arm.com/documentation/ddi0602/2025-09/ Co-authored-by: Martin Wehking <martin.wehking@arm.com>
1 parent 7ac2900 commit f28224b

File tree

13 files changed

+387
-1
lines changed

13 files changed

+387
-1
lines changed

clang/test/Driver/aarch64-v97a.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,11 @@
1717
// GENERICV97A-BE: "-cc1"{{.*}} "-triple" "aarch64_be{{.*}}" "-target-cpu" "generic" "-target-feature" "+v9.7a"{{.*}}
1818

1919
// ===== Features supported on aarch64 =====
20+
21+
// RUN: %clang -target aarch64 -march=armv9.7a+cmh -### -c %s 2>&1 | FileCheck -check-prefix=V97A-CMH %s
22+
// RUN: %clang -target aarch64 -march=armv9.7-a+cmh -### -c %s 2>&1 | FileCheck -check-prefix=V97A-CMH %s
23+
// V97A-CMH: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "generic" "-target-feature" "+v9.7a"{{.*}} "-target-feature" "+cmh"
24+
25+
// RUN: %clang -target aarch64 -march=armv9.7a+lscp -### -c %s 2>&1 | FileCheck -check-prefix=V97A-LSCP %s
26+
// RUN: %clang -target aarch64 -march=armv9.7-a+lscp -### -c %s 2>&1 | FileCheck -check-prefix=V97A-LSCP %s
27+
// V97A-LSCP: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "generic" "-target-feature" "+v9.7a"{{.*}} "-target-feature" "+lscp"

clang/test/Driver/print-supported-extensions-aarch64.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
// CHECK-NEXT: bf16 FEAT_BF16 Enable BFloat16 Extension
99
// CHECK-NEXT: brbe FEAT_BRBE Enable Branch Record Buffer Extension
1010
// CHECK-NEXT: bti FEAT_BTI Enable Branch Target Identification
11+
// CHECK-NEXT: cmh FEAT_CMH Enable Armv9.7-A Contention Management Hints
1112
// CHECK-NEXT: cmpbr FEAT_CMPBR Enable Armv9.6-A base compare and branch instructions
1213
// CHECK-NEXT: fcma FEAT_FCMA Enable Armv8.3-A Floating-point complex number support
1314
// CHECK-NEXT: cpa FEAT_CPA Enable Armv9.5-A Checked Pointer Arithmetic
@@ -37,6 +38,7 @@
3738
// CHECK-NEXT: ite FEAT_ITE Enable Armv9.4-A Instrumentation Extension
3839
// CHECK-NEXT: jscvt FEAT_JSCVT Enable Armv8.3-A JavaScript FP conversion instructions
3940
// CHECK-NEXT: ls64 FEAT_LS64, FEAT_LS64_V, FEAT_LS64_ACCDATA Enable Armv8.7-A LD64B/ST64B Accelerator Extension
41+
// CHECK-NEXT: lscp FEAT_LSCP Enable Armv9.7-A Load-acquire and store-release pair extension
4042
// CHECK-NEXT: lse FEAT_LSE Enable Armv8.1-A Large System Extension (LSE) atomic instructions
4143
// CHECK-NEXT: lse128 FEAT_LSE128 Enable Armv9.4-A 128-bit Atomic instructions
4244
// CHECK-NEXT: lsfe FEAT_LSFE Enable Armv9.6-A base Atomic floating-point in-memory instructions

llvm/lib/Target/AArch64/AArch64Features.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -589,6 +589,11 @@ def FeatureSSVE_FEXPA : ExtensionWithMArch<"ssve-fexpa", "SSVE_FEXPA", "FEAT_SSV
589589
// Armv9.7 Architecture Extensions
590590
//===----------------------------------------------------------------------===//
591591

592+
def FeatureCMH : ExtensionWithMArch<"cmh", "CMH", "FEAT_CMH",
593+
"Enable Armv9.7-A Contention Management Hints">;
594+
595+
def FeatureLSCP : ExtensionWithMArch<"lscp", "LSCP", "FEAT_LSCP",
596+
"Enable Armv9.7-A Load-acquire and store-release pair extension">;
592597

593598
//===----------------------------------------------------------------------===//
594599
// Other Features

llvm/lib/Target/AArch64/AArch64InstrFormats.td

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1894,6 +1894,21 @@ def btihint_op : Operand<i32> {
18941894
}];
18951895
}
18961896

1897+
def CMHPriorityHintOperand : AsmOperandClass {
1898+
let Name = "CMHPriorityHint";
1899+
let ParserMethod = "tryParseCMHPriorityHint";
1900+
}
1901+
1902+
def CMHPriorityHint_op : Operand<i32> {
1903+
let ParserMatchClass = CMHPriorityHintOperand;
1904+
let PrintMethod = "printCMHPriorityHintOp";
1905+
let MCOperandPredicate = [{
1906+
if (!MCOp.isImm())
1907+
return false;
1908+
return AArch64CMHPriorityHint::lookupCMHPriorityHintByEncoding(MCOp.getImm()) != nullptr;
1909+
}];
1910+
}
1911+
18971912
class MRSI : RtSystemI<1, (outs GPR64:$Rt), (ins mrs_sysreg_op:$systemreg),
18981913
"mrs", "\t$Rt, $systemreg"> {
18991914
bits<16> systemreg;
@@ -4636,6 +4651,48 @@ multiclass StorePairOffset<bits<2> opc, bit V, RegisterOperand regtype,
46364651
GPR64sp:$Rn, 0)>;
46374652
}
46384653

4654+
class BaseLoadStoreAcquirePairOffset<bits<4> opc, bit L, dag oops, dag iops,
4655+
string asm>
4656+
: I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, #0]", "", []> {
4657+
bits<5> Rt;
4658+
bits<5> Rt2;
4659+
bits<5> Rn;
4660+
let Inst{31-23} = 0b110110010;
4661+
let Inst{22} = L;
4662+
let Inst{21} = 0b0;
4663+
let Inst{20-16} = Rt2;
4664+
let Inst{15-12} = opc;
4665+
let Inst{11-10} = 0b10;
4666+
let Inst{9-5} = Rn;
4667+
let Inst{4-0} = Rt;
4668+
}
4669+
4670+
multiclass LoadAcquirePairOffset<bits<4> opc, string asm> {
4671+
let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
4672+
def i : BaseLoadStoreAcquirePairOffset<opc, 0b1,
4673+
(outs GPR64:$Rt, GPR64:$Rt2),
4674+
(ins GPR64sp:$Rn), asm>,
4675+
Sched<[WriteAtomic, WriteLDHi]>;
4676+
4677+
def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4678+
(!cast<Instruction>(NAME # "i") GPR64:$Rt, GPR64:$Rt2,
4679+
GPR64sp:$Rn)>;
4680+
}
4681+
4682+
4683+
multiclass StoreAcquirePairOffset<bits<4> opc, string asm> {
4684+
let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
4685+
def i : BaseLoadStoreAcquirePairOffset<opc, 0b0, (outs),
4686+
(ins GPR64:$Rt, GPR64:$Rt2,
4687+
GPR64sp:$Rn),
4688+
asm>,
4689+
Sched<[WriteSTP]>;
4690+
4691+
def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4692+
(!cast<Instruction>(NAME # "i") GPR64:$Rt, GPR64:$Rt2,
4693+
GPR64sp:$Rn)>;
4694+
}
4695+
46394696
// (pre-indexed)
46404697
class BaseLoadStorePairPreIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
46414698
string asm>
@@ -13227,3 +13284,34 @@ multiclass SIMDThreeSameVectorFP8MatrixMul<string asm>{
1322713284
let Predicates = [HasNEON, HasF8F32MM];
1322813285
}
1322913286
}
13287+
13288+
//----------------------------------------------------------------------------
13289+
// Contention Management Hints - FEAT_CMH
13290+
//----------------------------------------------------------------------------
13291+
13292+
class SHUHInst<string asm> : I<
13293+
(outs),
13294+
(ins CMHPriorityHint_op:$priority),
13295+
asm, "\t$priority", "", []>, Sched<[]> {
13296+
bits<1> priority;
13297+
let Inst{31-12} = 0b11010101000000110010;
13298+
let Inst{11-8} = 0b0110;
13299+
let Inst{7-6} = 0b01;
13300+
let Inst{5} = priority;
13301+
let Inst{4-0} = 0b11111;
13302+
}
13303+
13304+
multiclass SHUH<string asm> {
13305+
def NAME : SHUHInst<asm>;
13306+
def : InstAlias<asm, (!cast<Instruction>(NAME) 0), 1>;
13307+
}
13308+
13309+
class STCPHInst<string asm> : I<
13310+
(outs),
13311+
(ins),
13312+
asm, "", "", []>, Sched<[]> {
13313+
let Inst{31-12} = 0b11010101000000110010;
13314+
let Inst{11-8} = 0b0110;
13315+
let Inst{7-5} = 0b100;
13316+
let Inst{4-0} = 0b11111;
13317+
}

llvm/lib/Target/AArch64/AArch64InstrInfo.td

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,11 @@ def HasLSUI : Predicate<"Subtarget->hasLSUI()">,
242242
def HasOCCMO : Predicate<"Subtarget->hasOCCMO()">,
243243
AssemblerPredicateWithAll<(all_of FeatureOCCMO), "occmo">;
244244

245+
def HasCMH : Predicate<"Subtarget->hasCMH()">,
246+
AssemblerPredicateWithAll<(all_of FeatureCMH), "cmh">;
247+
def HasLSCP : Predicate<"Subtarget->hasLSCP()">,
248+
AssemblerPredicateWithAll<(all_of FeatureLSCP), "lscp">;
249+
245250
// A subset of SVE(2) instructions are legal in Streaming SVE execution mode,
246251
// they should be enabled if either has been specified.
247252
def HasSVE_or_SME
@@ -3692,6 +3697,12 @@ def UDF : UDFType<0, "udf">;
36923697
// Load instructions.
36933698
//===----------------------------------------------------------------------===//
36943699

3700+
let Predicates = [HasLSCP] in {
3701+
defm LDAP : LoadAcquirePairOffset<0b0101, "ldap">;
3702+
defm LDAPP : LoadAcquirePairOffset<0b0111, "ldapp">;
3703+
defm STLP : StoreAcquirePairOffset<0b0101, "stlp">;
3704+
}
3705+
36953706
// Pair (indexed, offset)
36963707
defm LDPW : LoadPairOffset<0b00, 0, GPR32z, simm7s4, "ldp">;
36973708
defm LDPX : LoadPairOffset<0b10, 0, GPR64z, simm7s8, "ldp">;
@@ -11247,6 +11258,15 @@ let Predicates = [HasLSFE] in {
1124711258
let Uses = [FPMR, FPCR] in
1124811259
defm FMMLA : SIMDThreeSameVectorFP8MatrixMul<"fmmla">;
1124911260

11261+
//===----------------------------------------------------------------------===//
11262+
// Contention Management Hints (FEAT_CMH)
11263+
//===----------------------------------------------------------------------===//
11264+
11265+
let Predicates = [HasCMH] in {
11266+
defm SHUH : SHUH<"shuh">; // Shared Update Hint instruction
11267+
def STCPH : STCPHInst<"stcph">; // Store Concurrent Priority Hint instruction
11268+
}
11269+
1125011270
include "AArch64InstrAtomics.td"
1125111271
include "AArch64SVEInstrInfo.td"
1125211272
include "AArch64SMEInstrInfo.td"

llvm/lib/Target/AArch64/AArch64SystemOperands.td

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -812,6 +812,21 @@ def : BTI<"c", 0b010>;
812812
def : BTI<"j", 0b100>;
813813
def : BTI<"jc", 0b110>;
814814

815+
//===----------------------------------------------------------------------===//
816+
// CMHPriority instruction options.
817+
//===----------------------------------------------------------------------===//
818+
819+
class CMHPriorityHint<string name, bits<1> encoding> : SearchableTable {
820+
let SearchableFields = ["Name", "Encoding"];
821+
let EnumValueField = "Encoding";
822+
823+
string Name = name;
824+
bits<1> Encoding;
825+
let Encoding = encoding;
826+
}
827+
828+
def : CMHPriorityHint<"ph", 0b1>;
829+
815830
//===----------------------------------------------------------------------===//
816831
// TLBI (translation lookaside buffer invalidate) instruction options.
817832
//===----------------------------------------------------------------------===//
@@ -2412,3 +2427,16 @@ def : DC<"CIVAPS", 0b000, 0b0111, 0b1111, 0b001>;
24122427
let Requires = [{ {AArch64::FeaturePoPS, AArch64::FeatureMTE} }] in {
24132428
def : DC<"CIGDVAPS", 0b000, 0b0111, 0b1111, 0b101>;
24142429
}
2430+
2431+
// v9.7a TLBI domains system registers (MemSys)
2432+
foreach n = 0-3 in {
2433+
defvar nb = !cast<bits<3>>(n);
2434+
def : RWSysReg<"VTLBID"#n#"_EL2", 0b11, 0b100, 0b0010, 0b1000, nb>;
2435+
}
2436+
2437+
foreach n = 0-3 in {
2438+
defvar nb = !cast<bits<3>>(n);
2439+
def : RWSysReg<"VTLBIDOS"#n#"_EL2", 0b11, 0b100, 0b0010, 0b1001, nb>;
2440+
}
2441+
2442+
def : ROSysReg<"TLBIDIDR_EL1", 0b11, 0b000, 0b1010, 0b0100, 0b110>;

llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,7 @@ class AArch64AsmParser : public MCTargetAsmParser {
266266
ParseStatus tryParseRPRFMOperand(OperandVector &Operands);
267267
ParseStatus tryParsePSBHint(OperandVector &Operands);
268268
ParseStatus tryParseBTIHint(OperandVector &Operands);
269+
ParseStatus tryParseCMHPriorityHint(OperandVector &Operands);
269270
ParseStatus tryParseAdrpLabel(OperandVector &Operands);
270271
ParseStatus tryParseAdrLabel(OperandVector &Operands);
271272
template <bool AddFPZeroAsLiteral>
@@ -370,6 +371,7 @@ class AArch64Operand : public MCParsedAsmOperand {
370371
k_PSBHint,
371372
k_PHint,
372373
k_BTIHint,
374+
k_CMHPriorityHint,
373375
} Kind;
374376

375377
SMLoc StartLoc, EndLoc;
@@ -499,6 +501,11 @@ class AArch64Operand : public MCParsedAsmOperand {
499501
unsigned Length;
500502
unsigned Val;
501503
};
504+
struct CMHPriorityHintOp {
505+
const char *Data;
506+
unsigned Length;
507+
unsigned Val;
508+
};
502509

503510
struct SVCROp {
504511
const char *Data;
@@ -525,6 +532,7 @@ class AArch64Operand : public MCParsedAsmOperand {
525532
struct PSBHintOp PSBHint;
526533
struct PHintOp PHint;
527534
struct BTIHintOp BTIHint;
535+
struct CMHPriorityHintOp CMHPriorityHint;
528536
struct ShiftExtendOp ShiftExtend;
529537
struct SVCROp SVCR;
530538
};
@@ -595,6 +603,9 @@ class AArch64Operand : public MCParsedAsmOperand {
595603
case k_BTIHint:
596604
BTIHint = o.BTIHint;
597605
break;
606+
case k_CMHPriorityHint:
607+
CMHPriorityHint = o.CMHPriorityHint;
608+
break;
598609
case k_ShiftExtend:
599610
ShiftExtend = o.ShiftExtend;
600611
break;
@@ -769,6 +780,16 @@ class AArch64Operand : public MCParsedAsmOperand {
769780
return StringRef(BTIHint.Data, BTIHint.Length);
770781
}
771782

783+
unsigned getCMHPriorityHint() const {
784+
assert(Kind == k_CMHPriorityHint && "Invalid access!");
785+
return CMHPriorityHint.Val;
786+
}
787+
788+
StringRef getCMHPriorityHintName() const {
789+
assert(Kind == k_CMHPriorityHint && "Invalid access!");
790+
return StringRef(CMHPriorityHint.Data, CMHPriorityHint.Length);
791+
}
792+
772793
StringRef getSVCR() const {
773794
assert(Kind == k_SVCR && "Invalid access!");
774795
return StringRef(SVCR.Data, SVCR.Length);
@@ -1511,6 +1532,7 @@ class AArch64Operand : public MCParsedAsmOperand {
15111532
bool isPSBHint() const { return Kind == k_PSBHint; }
15121533
bool isPHint() const { return Kind == k_PHint; }
15131534
bool isBTIHint() const { return Kind == k_BTIHint; }
1535+
bool isCMHPriorityHint() const { return Kind == k_CMHPriorityHint; }
15141536
bool isShiftExtend() const { return Kind == k_ShiftExtend; }
15151537
bool isShifter() const {
15161538
if (!isShiftExtend())
@@ -2196,6 +2218,11 @@ class AArch64Operand : public MCParsedAsmOperand {
21962218
Inst.addOperand(MCOperand::createImm(getBTIHint()));
21972219
}
21982220

2221+
void addCMHPriorityHintOperands(MCInst &Inst, unsigned N) const {
2222+
assert(N == 1 && "Invalid number of operands!");
2223+
Inst.addOperand(MCOperand::createImm(getCMHPriorityHint()));
2224+
}
2225+
21992226
void addShifterOperands(MCInst &Inst, unsigned N) const {
22002227
assert(N == 1 && "Invalid number of operands!");
22012228
unsigned Imm =
@@ -2546,6 +2573,17 @@ class AArch64Operand : public MCParsedAsmOperand {
25462573
return Op;
25472574
}
25482575

2576+
static std::unique_ptr<AArch64Operand>
2577+
CreateCMHPriorityHint(unsigned Val, StringRef Str, SMLoc S, MCContext &Ctx) {
2578+
auto Op = std::make_unique<AArch64Operand>(k_CMHPriorityHint, Ctx);
2579+
Op->CMHPriorityHint.Val = Val;
2580+
Op->CMHPriorityHint.Data = Str.data();
2581+
Op->CMHPriorityHint.Length = Str.size();
2582+
Op->StartLoc = S;
2583+
Op->EndLoc = S;
2584+
return Op;
2585+
}
2586+
25492587
static std::unique_ptr<AArch64Operand>
25502588
CreateMatrixRegister(unsigned RegNum, unsigned ElementWidth, MatrixKind Kind,
25512589
SMLoc S, SMLoc E, MCContext &Ctx) {
@@ -2656,6 +2694,9 @@ void AArch64Operand::print(raw_ostream &OS, const MCAsmInfo &MAI) const {
26562694
case k_BTIHint:
26572695
OS << getBTIHintName();
26582696
break;
2697+
case k_CMHPriorityHint:
2698+
OS << getCMHPriorityHintName();
2699+
break;
26592700
case k_MatrixRegister:
26602701
OS << "<matrix " << getMatrixReg() << ">";
26612702
break;
@@ -3279,6 +3320,24 @@ ParseStatus AArch64AsmParser::tryParseBTIHint(OperandVector &Operands) {
32793320
return ParseStatus::Success;
32803321
}
32813322

3323+
/// tryParseCMHPriorityHint - Try to parse a CMHPriority operand
3324+
ParseStatus AArch64AsmParser::tryParseCMHPriorityHint(OperandVector &Operands) {
3325+
SMLoc S = getLoc();
3326+
const AsmToken &Tok = getTok();
3327+
if (Tok.isNot(AsmToken::Identifier))
3328+
return TokError("invalid operand for instruction");
3329+
3330+
auto CMHPriority =
3331+
AArch64CMHPriorityHint::lookupCMHPriorityHintByName(Tok.getString());
3332+
if (!CMHPriority)
3333+
return TokError("invalid operand for instruction");
3334+
3335+
Operands.push_back(AArch64Operand::CreateCMHPriorityHint(
3336+
CMHPriority->Encoding, Tok.getString(), S, getContext()));
3337+
Lex(); // Eat identifier token.
3338+
return ParseStatus::Success;
3339+
}
3340+
32823341
/// tryParseAdrpLabel - Parse and validate a source label for the ADRP
32833342
/// instruction.
32843343
ParseStatus AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
@@ -3824,6 +3883,8 @@ static const struct Extension {
38243883
{"ssve-bitperm", {AArch64::FeatureSSVE_BitPerm}},
38253884
{"sme-mop4", {AArch64::FeatureSME_MOP4}},
38263885
{"sme-tmop", {AArch64::FeatureSME_TMOP}},
3886+
{"cmh", {AArch64::FeatureCMH}},
3887+
{"lscp", {AArch64::FeatureLSCP}},
38273888
};
38283889

38293890
static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str) {

llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1508,6 +1508,17 @@ void AArch64InstPrinter::printBTIHintOp(const MCInst *MI, unsigned OpNum,
15081508
markup(O, Markup::Immediate) << '#' << formatImm(btihintop);
15091509
}
15101510

1511+
void AArch64InstPrinter::printCMHPriorityHintOp(const MCInst *MI,
1512+
unsigned OpNum,
1513+
const MCSubtargetInfo &STI,
1514+
raw_ostream &O) {
1515+
unsigned priorityhint_op = MI->getOperand(OpNum).getImm();
1516+
auto PHint =
1517+
AArch64CMHPriorityHint::lookupCMHPriorityHintByEncoding(priorityhint_op);
1518+
if (PHint)
1519+
O << PHint->Name;
1520+
}
1521+
15111522
void AArch64InstPrinter::printFPImmOperand(const MCInst *MI, unsigned OpNum,
15121523
const MCSubtargetInfo &STI,
15131524
raw_ostream &O) {

llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,9 @@ class AArch64InstPrinter : public MCInstPrinter {
151151
void printBTIHintOp(const MCInst *MI, unsigned OpNum,
152152
const MCSubtargetInfo &STI, raw_ostream &O);
153153

154+
void printCMHPriorityHintOp(const MCInst *MI, unsigned OpNum,
155+
const MCSubtargetInfo &STI, raw_ostream &O);
156+
154157
void printFPImmOperand(const MCInst *MI, unsigned OpNum,
155158
const MCSubtargetInfo &STI, raw_ostream &O);
156159

0 commit comments

Comments
 (0)