[llvm] [AArch64][llvm] Redefine some insns as an alias of `SYS` (PR #187004)
Jonathan Thackray via llvm-commits
llvm-commits at lists.llvm.org
Tue Apr 14 07:05:07 PDT 2026
https://github.com/jthackray updated https://github.com/llvm/llvm-project/pull/187004
>From 66157f65a29782dba94e6e5837de8de7eed42588 Mon Sep 17 00:00:00 2001
From: Jonathan Thackray <jonathan.thackray at arm.com>
Date: Mon, 16 Mar 2026 20:41:14 +0000
Subject: [PATCH 1/7] [AArch64][llvm] Redefine some isns as an alias of `SYS`
Some instructions are not currently defined as an alias of `SYS`
when they should be, so they don't disassemble back into the
native instruction, but instead disassemble into `SYS`.
Fix these cases and add additional testcase.
Note that I've left `GCSPUSHM` due to a `mayStore`, `GCSSS1` and
`GCSSS2` as they're used in AArch64ISelDAGToDAG.cpp, and `GCSPOPM`
has an intrinsic pattern in AArch64InstrInfo.td. They will disassemble
correctly though, as they use `InstAlias`.
---
.../lib/Target/AArch64/AArch64InstrFormats.td | 19 ---
llvm/lib/Target/AArch64/AArch64InstrInfo.td | 47 +++----
.../MCTargetDesc/AArch64InstPrinter.cpp | 116 ++++++++++++++++++
llvm/test/MC/AArch64/armv8.9a-debug-pmu.s | 5 +
llvm/test/MC/AArch64/armv9.4a-gcs.s | 40 ++++++
llvm/test/MC/AArch64/armv9.6a-rme-gpc3.s | 5 +
llvm/test/MC/AArch64/brbe.s | 8 +-
7 files changed, 196 insertions(+), 44 deletions(-)
diff --git a/llvm/lib/Target/AArch64/AArch64InstrFormats.td b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
index 406ac2fa62df2..0c2bd5313cf0e 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrFormats.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
@@ -1843,12 +1843,6 @@ class RegInputSystemI<bits<4> CRm, bits<3> Op2, string asm,
let Inst{7-5} = Op2;
}
-class APASI : SimpleSystemI<0, (ins GPR64:$Xt), "apas", "\t$Xt">, Sched<[]> {
- bits<5> Xt;
- let Inst{20-5} = 0b0111001110000000;
- let Inst{4-0} = Xt;
-}
-
// Hint instructions that take both a CRm and a 3-bit immediate.
// NOTE: ideally, this would have mayStore = 0, mayLoad = 0, but we cannot
// model patterns with sufficiently fine granularity
@@ -13062,19 +13056,6 @@ class LRCPC3NEONLdStSingle<bit L, dag oops, dag iops, string asm, string cst>
let hasSideEffects = 1;
}
-//---
-// Instrumentation Extension (FEAT_ITE)
-//---
-
-let Predicates = [HasITE] in
-def TRCIT : RtSystemI<0b0, (outs), (ins GPR64:$Rt), "trcit", "\t$Rt"> {
- let Inst{20-19} = 0b01;
- let Inst{18-16} = 0b011;
- let Inst{15-12} = 0b0111;
- let Inst{11-8} = 0b0010;
- let Inst{7-5} = 0b111;
-}
-
// * RCWCAS family
// * RCW<OP> family
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index 129e49f645633..09a8a9a63fb7d 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -1627,16 +1627,6 @@ def WFET : RegInputSystemI<0b0000, 0b000, "wfet">;
def WFIT : RegInputSystemI<0b0000, 0b001, "wfit">;
}
-// Branch Record Buffer two-word mnemonic instructions
-class BRBEI<bits<3> op2, string keyword>
- : SimpleSystemI<0, (ins), "brb", keyword>, Sched<[WriteSys]> {
- let Inst{31-8} = 0b110101010000100101110010;
- let Inst{7-5} = op2;
- let Predicates = [HasBRBE];
-}
-def BRB_IALL: BRBEI<0b100, "\tiall">;
-def BRB_INJ: BRBEI<0b101, "\tinj">;
-
}
// Allow uppercase and lowercase keyword arguments for BRB IALL and BRB INJ
@@ -1645,16 +1635,6 @@ def : TokenAlias<"IALL", "iall">;
// ARMv9.4-A Guarded Control Stack
-class GCSNoOp<bits<3> op2, string mnemonic>
- : SimpleSystemI<0, (ins), mnemonic, "">, Sched<[]> {
- let Inst{20-8} = 0b0100001110111;
- let Inst{7-5} = op2;
- let Predicates = [HasGCS];
-}
-def GCSPUSHX : GCSNoOp<0b100, "gcspushx">;
-def GCSPOPCX : GCSNoOp<0b101, "gcspopcx">;
-def GCSPOPX : GCSNoOp<0b110, "gcspopx">;
-
class GCSRtIn<bits<3> op1, bits<3> op2, string mnemonic,
list<dag> pattern = []>
: RtSystemI<0, (outs), (ins GPR64:$Rt), mnemonic, "\t$Rt", pattern> {
@@ -2565,6 +2545,30 @@ def SYSLxt : SystemLXtI<1, "sysl">;
def : InstAlias<"sys $op1, $Cn, $Cm, $op2",
(SYSxt timm32_0_7:$op1, sys_cr_op:$Cn,
sys_cr_op:$Cm, timm32_0_7:$op2, XZR)>;
+def : InstAlias<"apas $Xt",
+ (SYSxt 6, 7, 0, 0, GPR64:$Xt)>;
+def : InstAlias<"brb\tiall",
+ (SYSxt 1, 7, 2, 4, XZR)>, Requires<[HasBRBE]>;
+def : InstAlias<"brb\tinj",
+ (SYSxt 1, 7, 2, 5, XZR)>, Requires<[HasBRBE]>;
+def : InstAlias<"trcit $Rt",
+ (SYSxt 3, 7, 2, 7, GPR64:$Rt)>, Requires<[HasITE]>;
+def : InstAlias<"gcspushx",
+ (SYSxt 0, 7, 7, 4, XZR)>, Requires<[HasGCS]>;
+def : InstAlias<"gcspopcx",
+ (SYSxt 0, 7, 7, 5, XZR)>, Requires<[HasGCS]>;
+def : InstAlias<"gcspopx",
+ (SYSxt 0, 7, 7, 6, XZR)>, Requires<[HasGCS]>;
+def : InstAlias<"gcspushm $Rt",
+ (SYSxt 3, 7, 7, 0, GPR64:$Rt)>, Requires<[HasGCS]>;
+def : InstAlias<"gcsss1 $Rt",
+ (SYSxt 3, 7, 7, 2, GPR64:$Rt)>, Requires<[HasGCS]>;
+def : InstAlias<"gcspopm",
+ (SYSLxt XZR, 3, 7, 7, 1)>, Requires<[HasGCS]>;
+def : InstAlias<"gcspopm $Rt",
+ (SYSLxt GPR64:$Rt, 3, 7, 7, 1)>, Requires<[HasGCS]>;
+def : InstAlias<"gcsss2 $Rt",
+ (SYSLxt GPR64:$Rt, 3, 7, 7, 3)>, Requires<[HasGCS]>;
//===----------------------------------------------------------------------===//
@@ -3094,9 +3098,6 @@ let Predicates = [HasLSUI] in {
defm : STOPregisterLSUI<"sttset","LDTSET">; // STTSETx
}
-// v9.6-a FEAT_RME_GPC3
-def APAS : APASI;
-
// v8.1 atomic LD<OP>(register). Performs load and then ST<OP>(register)
defm LDADD : LDOPregister<0b000, "add", 0, 0, "">;
defm LDADDA : LDOPregister<0b000, "add", 1, 0, "a">;
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp
index 2f4b3fa016336..979a16baa9df8 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp
@@ -925,6 +925,13 @@ bool AArch64InstPrinter::printSysAlias(const MCInst *MI,
default: return false;
// MLBI aliases
case 0: {
+ if (Op1Val == 6 && Op2Val == 0) {
+ NeedsReg = true;
+ Ins = "apas";
+ Name = "";
+ break;
+ }
+
const AArch64MLBI::MLBI *MLBI =
AArch64MLBI::lookupMLBIByEncoding(Encoding);
if (!MLBI || !MLBI->haveFeatures(STI.getFeatureBits()))
@@ -941,6 +948,41 @@ bool AArch64InstPrinter::printSysAlias(const MCInst *MI,
case 0: goto Search_IC;
case 3: goto Search_PRCTX;
}
+ // BRB aliases.
+ case 2: {
+ switch (Op1Val) {
+ default:
+ return false;
+ case 1:
+ if (!(STI.hasFeature(AArch64::FeatureAll) ||
+ STI.hasFeature(AArch64::FeatureBRBE)))
+ return false;
+
+ NeedsReg = false;
+ switch (Op2Val) {
+ default:
+ return false;
+ case 4:
+ Ins = "brb\t";
+ Name = "iall";
+ break;
+ case 5:
+ Ins = "brb\t";
+ Name = "inj";
+ break;
+ }
+ break;
+ case 3:
+ if (Op2Val != 7 || !(STI.hasFeature(AArch64::FeatureAll) ||
+ STI.hasFeature(AArch64::FeatureITE)))
+ return false;
+
+ NeedsReg = true;
+ Ins = "trcit";
+ Name = "";
+ break;
+ }
+ } break;
// Prediction Restriction aliases
case 3: {
Search_PRCTX:
@@ -1014,6 +1056,47 @@ bool AArch64InstPrinter::printSysAlias(const MCInst *MI,
return false;
}
} break;
+ // GCS aliases.
+ case 7: {
+ if (!(STI.hasFeature(AArch64::FeatureAll) ||
+ STI.hasFeature(AArch64::FeatureGCS)))
+ return false;
+
+ Name = "";
+ switch (Op1Val) {
+ default:
+ return false;
+ case 0:
+ NeedsReg = false;
+ switch (Op2Val) {
+ default:
+ return false;
+ case 4:
+ Ins = "gcspushx";
+ break;
+ case 5:
+ Ins = "gcspopcx";
+ break;
+ case 6:
+ Ins = "gcspopx";
+ break;
+ }
+ break;
+ case 3:
+ NeedsReg = true;
+ switch (Op2Val) {
+ default:
+ return false;
+ case 0:
+ Ins = "gcspushm";
+ break;
+ case 2:
+ Ins = "gcsss1";
+ break;
+ }
+ break;
+ }
+ } break;
}
} else if (CnVal == 8 || CnVal == 9) {
// TLBI aliases
@@ -1071,6 +1154,13 @@ bool AArch64InstPrinter::printSysAlias(const MCInst *MI,
if (NotXZR && !NeedsReg && !OptionalReg)
return false;
+ if (Name.empty()) {
+ O << '\t' << Ins;
+ if (NeedsReg || (OptionalReg && NotXZR))
+ O << '\t' << Reg;
+ return true;
+ }
+
std::string Str = Ins + Name;
llvm::transform(Str, Str.begin(), ::tolower);
@@ -1110,6 +1200,7 @@ bool AArch64InstPrinter::printSyslAlias(const MCInst *MI,
std::string Ins;
std::string Name;
+ bool OptionalReg = false;
if (CnVal == 12) {
if (CmVal == 3) {
@@ -1123,9 +1214,34 @@ bool AArch64InstPrinter::printSyslAlias(const MCInst *MI,
Name = std::string(GICR->Name);
} else
return false;
+ } else if (CnVal == 7 && CmVal == 7) {
+ if (!(STI.hasFeature(AArch64::FeatureAll) ||
+ STI.hasFeature(AArch64::FeatureGCS)) ||
+ Op1Val != 3)
+ return false;
+
+ Name = "";
+ switch (Op2Val) {
+ default:
+ return false;
+ case 1:
+ Ins = "gcspopm";
+ OptionalReg = true;
+ break;
+ case 3:
+ Ins = "gcsss2";
+ break;
+ }
} else
return false;
+ if (Name.empty()) {
+ O << '\t' << Ins;
+ if (!OptionalReg || Reg != "xzr")
+ O << '\t' << Reg.str();
+ return true;
+ }
+
llvm::transform(Name, Name.begin(), ::tolower);
O << '\t' << Ins << '\t' << Reg.str() << ", " << Name;
diff --git a/llvm/test/MC/AArch64/armv8.9a-debug-pmu.s b/llvm/test/MC/AArch64/armv8.9a-debug-pmu.s
index db5cb0701036d..ea058d484d852 100644
--- a/llvm/test/MC/AArch64/armv8.9a-debug-pmu.s
+++ b/llvm/test/MC/AArch64/armv8.9a-debug-pmu.s
@@ -1773,6 +1773,11 @@ trcit x1
// CHECK-ERROR: error: instruction requires: ite
// CHECK-UNKNOWN: d50b72e1 sys #3, c7, c2, #7, x1
+sys #3, c7, c2, #7, x2
+// CHECK-INST: trcit x2
+// CHECK-ENCODING: encoding: [0xe2,0x72,0x0b,0xd5]
+// CHECK-UNKNOWN: d50b72e2 sys #3, c7, c2, #7, x2
+
// FEAT_SPE_FDS
mrs x3, PMSDSFR_EL1
// CHECK-INST: mrs x3, PMSDSFR_EL1
diff --git a/llvm/test/MC/AArch64/armv9.4a-gcs.s b/llvm/test/MC/AArch64/armv9.4a-gcs.s
index f702c947543ac..78b3f3639892e 100644
--- a/llvm/test/MC/AArch64/armv9.4a-gcs.s
+++ b/llvm/test/MC/AArch64/armv9.4a-gcs.s
@@ -119,24 +119,44 @@ gcsss1 x21
// CHECK-ERROR: error: instruction requires: gcs
// CHECK-UNKNOWN: d50b7755 sys #3, c7, c7, #2, x21
+sys #3, c7, c7, #2, x20
+// CHECK-INST: gcsss1 x20
+// CHECK-ENCODING: encoding: [0x54,0x77,0x0b,0xd5]
+// CHECK-UNKNOWN: d50b7754 sys #3, c7, c7, #2, x20
+
gcsss2 x22
// CHECK-INST: gcsss2 x22
// CHECK-ENCODING: encoding: [0x76,0x77,0x2b,0xd5]
// CHECK-ERROR: error: instruction requires: gcs
// CHECK-UNKNOWN: d52b7776 sysl x22, #3, c7, c7, #3
+sysl x23, #3, c7, c7, #3
+// CHECK-INST: gcsss2 x23
+// CHECK-ENCODING: encoding: [0x77,0x77,0x2b,0xd5]
+// CHECK-UNKNOWN: d52b7777 sysl x23, #3, c7, c7, #3
+
gcspushm x25
// CHECK-INST: gcspushm x25
// CHECK-ENCODING: encoding: [0x19,0x77,0x0b,0xd5]
// CHECK-ERROR: error: instruction requires: gcs
// CHECK-UNKNOWN: d50b7719 sys #3, c7, c7, #0, x25
+sys #3, c7, c7, #0, x24
+// CHECK-INST: gcspushm x24
+// CHECK-ENCODING: encoding: [0x18,0x77,0x0b,0xd5]
+// CHECK-UNKNOWN: d50b7718 sys #3, c7, c7, #0, x24
+
gcspopm
// CHECK-INST: gcspopm
// CHECK-ENCODING: encoding: [0x3f,0x77,0x2b,0xd5]
// CHECK-ERROR: error: instruction requires: gcs
// CHECK-UNKNOWN: d52b773f sysl xzr, #3, c7, c7, #1
+sysl xzr, #3, c7, c7, #1
+// CHECK-INST: gcspopm
+// CHECK-ENCODING: encoding: [0x3f,0x77,0x2b,0xd5]
+// CHECK-UNKNOWN: d52b773f sysl xzr, #3, c7, c7, #1
+
gcspopm xzr
// CHECK-INST: gcspopm
// CHECK-ENCODING: encoding: [0x3f,0x77,0x2b,0xd5]
@@ -149,6 +169,11 @@ gcspopm x25
// CHECK-ERROR: error: instruction requires: gcs
// CHECK-UNKNOWN: d52b7739 sysl x25, #3, c7, c7, #1
+sysl x24, #3, c7, c7, #1
+// CHECK-INST: gcspopm x24
+// CHECK-ENCODING: encoding: [0x38,0x77,0x2b,0xd5]
+// CHECK-UNKNOWN: d52b7738 sysl x24, #3, c7, c7, #1
+
gcsstr x26, [x27]
// CHECK-INST: gcsstr x26, [x27]
// CHECK-ENCODING: encoding: [0x7a,0x0f,0x1f,0xd9]
@@ -179,18 +204,33 @@ gcspushx
// CHECK-ERROR: error: instruction requires: gcs
// CHECK-UNKNOWN: d508779f sys #0, c7, c7, #4
+sys #0, c7, c7, #4
+// CHECK-INST: gcspushx
+// CHECK-ENCODING: encoding: [0x9f,0x77,0x08,0xd5]
+// CHECK-UNKNOWN: d508779f sys #0, c7, c7, #4
+
gcspopcx
// CHECK-INST: gcspopcx
// CHECK-ENCODING: encoding: [0xbf,0x77,0x08,0xd5]
// CHECK-ERROR: error: instruction requires: gcs
// CHECK-UNKNOWN: d50877bf sys #0, c7, c7, #5
+sys #0, c7, c7, #5
+// CHECK-INST: gcspopcx
+// CHECK-ENCODING: encoding: [0xbf,0x77,0x08,0xd5]
+// CHECK-UNKNOWN: d50877bf sys #0, c7, c7, #5
+
gcspopx
// CHECK-INST: gcspopx
// CHECK-ENCODING: encoding: [0xdf,0x77,0x08,0xd5]
// CHECK-ERROR: error: instruction requires: gcs
// CHECK-UNKNOWN: d50877df sys #0, c7, c7, #6
+sys #0, c7, c7, #6
+// CHECK-INST: gcspopx
+// CHECK-ENCODING: encoding: [0xdf,0x77,0x08,0xd5]
+// CHECK-UNKNOWN: d50877df sys #0, c7, c7, #6
+
gcsb dsync
// CHECK-INST: gcsb dsync
// CHECK-ENCODING: encoding: [0x7f,0x22,0x03,0xd5]
diff --git a/llvm/test/MC/AArch64/armv9.6a-rme-gpc3.s b/llvm/test/MC/AArch64/armv9.6a-rme-gpc3.s
index 2a1943ac22a27..bb431de9add13 100644
--- a/llvm/test/MC/AArch64/armv9.6a-rme-gpc3.s
+++ b/llvm/test/MC/AArch64/armv9.6a-rme-gpc3.s
@@ -34,6 +34,11 @@
// CHECK-ENCODING: encoding: [0x1e,0x70,0x0e,0xd5]
// CHECK-UNKNOWN: d50e701e apas x30
+ sys #6, c7, c0, #0, x3
+// CHECK-INST: apas x3
+// CHECK-ENCODING: encoding: [0x03,0x70,0x0e,0xd5]
+// CHECK-UNKNOWN: d50e7003 apas x3
+
mrs x3, GPCBW_EL3
// CHECK-INST: mrs x3, GPCBW_EL3
// CHECK-ENCODING: encoding: [0xa3,0x21,0x3e,0xd5]
diff --git a/llvm/test/MC/AArch64/brbe.s b/llvm/test/MC/AArch64/brbe.s
index f02017dae8e5e..8c493f08b8982 100644
--- a/llvm/test/MC/AArch64/brbe.s
+++ b/llvm/test/MC/AArch64/brbe.s
@@ -136,10 +136,14 @@ mrs x5, BRBTGT31_EL1
brb iall
brb inj
+sys #1, c7, c2, #4
+sys #1, c7, c2, #5
// CHECK: brb iall // encoding: [0x9f,0x72,0x09,0xd5]
// CHECK: brb inj // encoding: [0xbf,0x72,0x09,0xd5]
-// ERROR-NO-BRBE: [[@LINE-4]]:1: error: instruction requires: brbe
-// ERROR-NO-BRBE: [[@LINE-4]]:1: error: instruction requires: brbe
+// CHECK: brb iall // encoding: [0x9f,0x72,0x09,0xd5]
+// CHECK: brb inj // encoding: [0xbf,0x72,0x09,0xd5]
+// ERROR-NO-BRBE: [[@LINE-8]]:1: error: instruction requires: brbe
+// ERROR-NO-BRBE: [[@LINE-8]]:1: error: instruction requires: brbe
brb IALL
brb INJ
>From 537b32c06128149ab491cae0196a8bbc1a722f9e Mon Sep 17 00:00:00 2001
From: Jonathan Thackray <jonathan.thackray at arm.com>
Date: Fri, 27 Mar 2026 22:45:04 +0000
Subject: [PATCH 2/7] fixup! Move new tests into arm64-aliases.s
---
llvm/test/MC/AArch64/arm64-aliases.s | 32 ++++++++++++++++++
llvm/test/MC/AArch64/armv8.9a-debug-pmu.s | 5 ---
llvm/test/MC/AArch64/armv9.4a-gcs.s | 40 -----------------------
llvm/test/MC/AArch64/armv9.6a-rme-gpc3.s | 5 ---
llvm/test/MC/AArch64/armv9a-sysp-pairs.s | 25 ++++++++++++++
llvm/test/MC/AArch64/brbe.s | 8 ++---
6 files changed, 59 insertions(+), 56 deletions(-)
create mode 100644 llvm/test/MC/AArch64/armv9a-sysp-pairs.s
diff --git a/llvm/test/MC/AArch64/arm64-aliases.s b/llvm/test/MC/AArch64/arm64-aliases.s
index ae157c676c95f..f61809e559a00 100644
--- a/llvm/test/MC/AArch64/arm64-aliases.s
+++ b/llvm/test/MC/AArch64/arm64-aliases.s
@@ -1,4 +1,8 @@
; RUN: llvm-mc -triple arm64-apple-darwin -mattr=neon -output-asm-variant=1 -show-encoding -print-imm-hex < %s | FileCheck %s
+; RUN: llvm-mc -triple arm64-apple-darwin -mattr=neon,+ite -filetype=obj < %s | llvm-objdump -d --mattr=+ite --no-print-imm-hex - | FileCheck %s --check-prefix=CHECK-ITE
+; RUN: llvm-mc -triple arm64-apple-darwin -mattr=neon,+gcs -filetype=obj < %s | llvm-objdump -d --mattr=+gcs --no-print-imm-hex - | FileCheck %s --check-prefix=CHECK-GCS
+; RUN: llvm-mc -triple arm64-apple-darwin -mattr=neon,+brbe -filetype=obj < %s | llvm-objdump -d --mattr=+brbe --no-print-imm-hex - | FileCheck %s --check-prefix=CHECK-BRBE
+; RUN: llvm-mc -triple arm64-apple-darwin -mattr=neon -filetype=obj < %s | llvm-objdump -d --no-print-imm-hex - | FileCheck %s --check-prefix=CHECK-RME
foo:
;-----------------------------------------------------------------------------
@@ -526,6 +530,34 @@ foo:
sys #4, c8, c7, #6, x31
; CHECK: tlbi vmalls12e1
+ sys #3, c7, c2, #7, x2
+; CHECK-ITE: trcit x2
+
+ sys #3, c7, c7, #2, x20
+; CHECK-GCS: gcsss1 x20
+ sysl x23, #3, c7, c7, #3
+; CHECK-GCS: gcsss2 x23
+ sys #3, c7, c7, #0, x24
+; CHECK-GCS: gcspushm x24
+ sysl xzr, #3, c7, c7, #1
+; CHECK-GCS: gcspopm
+ sysl x24, #3, c7, c7, #1
+; CHECK-GCS: gcspopm x24
+ sys #0, c7, c7, #4
+; CHECK-GCS: gcspushx
+ sys #0, c7, c7, #5
+; CHECK-GCS: gcspopcx
+ sys #0, c7, c7, #6
+; CHECK-GCS: gcspopx
+
+ sys #1, c7, c2, #4
+; CHECK-BRBE: brb iall
+ sys #1, c7, c2, #5
+; CHECK-BRBE: brb inj
+
+ sys #6, c7, c0, #0, x3
+; CHECK-RME: apas x3
+
ic ialluis
; CHECK: ic ialluis ; encoding: [0x1f,0x71,0x08,0xd5]
ic iallu
diff --git a/llvm/test/MC/AArch64/armv8.9a-debug-pmu.s b/llvm/test/MC/AArch64/armv8.9a-debug-pmu.s
index ea058d484d852..db5cb0701036d 100644
--- a/llvm/test/MC/AArch64/armv8.9a-debug-pmu.s
+++ b/llvm/test/MC/AArch64/armv8.9a-debug-pmu.s
@@ -1773,11 +1773,6 @@ trcit x1
// CHECK-ERROR: error: instruction requires: ite
// CHECK-UNKNOWN: d50b72e1 sys #3, c7, c2, #7, x1
-sys #3, c7, c2, #7, x2
-// CHECK-INST: trcit x2
-// CHECK-ENCODING: encoding: [0xe2,0x72,0x0b,0xd5]
-// CHECK-UNKNOWN: d50b72e2 sys #3, c7, c2, #7, x2
-
// FEAT_SPE_FDS
mrs x3, PMSDSFR_EL1
// CHECK-INST: mrs x3, PMSDSFR_EL1
diff --git a/llvm/test/MC/AArch64/armv9.4a-gcs.s b/llvm/test/MC/AArch64/armv9.4a-gcs.s
index 78b3f3639892e..f702c947543ac 100644
--- a/llvm/test/MC/AArch64/armv9.4a-gcs.s
+++ b/llvm/test/MC/AArch64/armv9.4a-gcs.s
@@ -119,44 +119,24 @@ gcsss1 x21
// CHECK-ERROR: error: instruction requires: gcs
// CHECK-UNKNOWN: d50b7755 sys #3, c7, c7, #2, x21
-sys #3, c7, c7, #2, x20
-// CHECK-INST: gcsss1 x20
-// CHECK-ENCODING: encoding: [0x54,0x77,0x0b,0xd5]
-// CHECK-UNKNOWN: d50b7754 sys #3, c7, c7, #2, x20
-
gcsss2 x22
// CHECK-INST: gcsss2 x22
// CHECK-ENCODING: encoding: [0x76,0x77,0x2b,0xd5]
// CHECK-ERROR: error: instruction requires: gcs
// CHECK-UNKNOWN: d52b7776 sysl x22, #3, c7, c7, #3
-sysl x23, #3, c7, c7, #3
-// CHECK-INST: gcsss2 x23
-// CHECK-ENCODING: encoding: [0x77,0x77,0x2b,0xd5]
-// CHECK-UNKNOWN: d52b7777 sysl x23, #3, c7, c7, #3
-
gcspushm x25
// CHECK-INST: gcspushm x25
// CHECK-ENCODING: encoding: [0x19,0x77,0x0b,0xd5]
// CHECK-ERROR: error: instruction requires: gcs
// CHECK-UNKNOWN: d50b7719 sys #3, c7, c7, #0, x25
-sys #3, c7, c7, #0, x24
-// CHECK-INST: gcspushm x24
-// CHECK-ENCODING: encoding: [0x18,0x77,0x0b,0xd5]
-// CHECK-UNKNOWN: d50b7718 sys #3, c7, c7, #0, x24
-
gcspopm
// CHECK-INST: gcspopm
// CHECK-ENCODING: encoding: [0x3f,0x77,0x2b,0xd5]
// CHECK-ERROR: error: instruction requires: gcs
// CHECK-UNKNOWN: d52b773f sysl xzr, #3, c7, c7, #1
-sysl xzr, #3, c7, c7, #1
-// CHECK-INST: gcspopm
-// CHECK-ENCODING: encoding: [0x3f,0x77,0x2b,0xd5]
-// CHECK-UNKNOWN: d52b773f sysl xzr, #3, c7, c7, #1
-
gcspopm xzr
// CHECK-INST: gcspopm
// CHECK-ENCODING: encoding: [0x3f,0x77,0x2b,0xd5]
@@ -169,11 +149,6 @@ gcspopm x25
// CHECK-ERROR: error: instruction requires: gcs
// CHECK-UNKNOWN: d52b7739 sysl x25, #3, c7, c7, #1
-sysl x24, #3, c7, c7, #1
-// CHECK-INST: gcspopm x24
-// CHECK-ENCODING: encoding: [0x38,0x77,0x2b,0xd5]
-// CHECK-UNKNOWN: d52b7738 sysl x24, #3, c7, c7, #1
-
gcsstr x26, [x27]
// CHECK-INST: gcsstr x26, [x27]
// CHECK-ENCODING: encoding: [0x7a,0x0f,0x1f,0xd9]
@@ -204,33 +179,18 @@ gcspushx
// CHECK-ERROR: error: instruction requires: gcs
// CHECK-UNKNOWN: d508779f sys #0, c7, c7, #4
-sys #0, c7, c7, #4
-// CHECK-INST: gcspushx
-// CHECK-ENCODING: encoding: [0x9f,0x77,0x08,0xd5]
-// CHECK-UNKNOWN: d508779f sys #0, c7, c7, #4
-
gcspopcx
// CHECK-INST: gcspopcx
// CHECK-ENCODING: encoding: [0xbf,0x77,0x08,0xd5]
// CHECK-ERROR: error: instruction requires: gcs
// CHECK-UNKNOWN: d50877bf sys #0, c7, c7, #5
-sys #0, c7, c7, #5
-// CHECK-INST: gcspopcx
-// CHECK-ENCODING: encoding: [0xbf,0x77,0x08,0xd5]
-// CHECK-UNKNOWN: d50877bf sys #0, c7, c7, #5
-
gcspopx
// CHECK-INST: gcspopx
// CHECK-ENCODING: encoding: [0xdf,0x77,0x08,0xd5]
// CHECK-ERROR: error: instruction requires: gcs
// CHECK-UNKNOWN: d50877df sys #0, c7, c7, #6
-sys #0, c7, c7, #6
-// CHECK-INST: gcspopx
-// CHECK-ENCODING: encoding: [0xdf,0x77,0x08,0xd5]
-// CHECK-UNKNOWN: d50877df sys #0, c7, c7, #6
-
gcsb dsync
// CHECK-INST: gcsb dsync
// CHECK-ENCODING: encoding: [0x7f,0x22,0x03,0xd5]
diff --git a/llvm/test/MC/AArch64/armv9.6a-rme-gpc3.s b/llvm/test/MC/AArch64/armv9.6a-rme-gpc3.s
index bb431de9add13..2a1943ac22a27 100644
--- a/llvm/test/MC/AArch64/armv9.6a-rme-gpc3.s
+++ b/llvm/test/MC/AArch64/armv9.6a-rme-gpc3.s
@@ -34,11 +34,6 @@
// CHECK-ENCODING: encoding: [0x1e,0x70,0x0e,0xd5]
// CHECK-UNKNOWN: d50e701e apas x30
- sys #6, c7, c0, #0, x3
-// CHECK-INST: apas x3
-// CHECK-ENCODING: encoding: [0x03,0x70,0x0e,0xd5]
-// CHECK-UNKNOWN: d50e7003 apas x3
-
mrs x3, GPCBW_EL3
// CHECK-INST: mrs x3, GPCBW_EL3
// CHECK-ENCODING: encoding: [0xa3,0x21,0x3e,0xd5]
diff --git a/llvm/test/MC/AArch64/armv9a-sysp-pairs.s b/llvm/test/MC/AArch64/armv9a-sysp-pairs.s
new file mode 100644
index 0000000000000..87990fb122ecc
--- /dev/null
+++ b/llvm/test/MC/AArch64/armv9a-sysp-pairs.s
@@ -0,0 +1,25 @@
+// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+d128,+tlb-rmi < %s \
+// RUN: | FileCheck %s --check-prefixes=CHECK-ASM,CHECK-ENCODING
+// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+d128,+tlb-rmi < %s \
+// RUN: | llvm-objdump -d --mattr=-d128,-tlb-rmi --no-print-imm-hex - \
+// RUN: | FileCheck %s --check-prefix=CHECK-DIS
+
+sysp #0, c8, c2, #2, x8, x9
+// CHECK-ASM: sysp #0, c8, c2, #2, x8, x9
+// CHECK-ENCODING: encoding: [0x48,0x82,0x48,0xd5]
+// CHECK-DIS: sysp #0, c8, c2, #2, x8, x9
+
+sysp #0, c8, c2, #2, xzr, xzr
+// CHECK-ASM: sysp #0, c8, c2, #2
+// CHECK-ENCODING: encoding: [0x5f,0x82,0x48,0xd5]
+// CHECK-DIS: sysp #0, c8, c2, #2
+
+tlbip VAE1, x8, x9
+// CHECK-ASM: tlbip vae1, x8, x9
+// CHECK-ENCODING: encoding: [0x28,0x87,0x48,0xd5]
+// CHECK-DIS: sysp #0, c8, c7, #1, x8, x9
+
+tlbip VAE1, xzr, xzr
+// CHECK-ASM: tlbip vae1, xzr, xzr
+// CHECK-ENCODING: encoding: [0x3f,0x87,0x48,0xd5]
+// CHECK-DIS: sysp #0, c8, c7, #1
diff --git a/llvm/test/MC/AArch64/brbe.s b/llvm/test/MC/AArch64/brbe.s
index 8c493f08b8982..f02017dae8e5e 100644
--- a/llvm/test/MC/AArch64/brbe.s
+++ b/llvm/test/MC/AArch64/brbe.s
@@ -136,14 +136,10 @@ mrs x5, BRBTGT31_EL1
brb iall
brb inj
-sys #1, c7, c2, #4
-sys #1, c7, c2, #5
// CHECK: brb iall // encoding: [0x9f,0x72,0x09,0xd5]
// CHECK: brb inj // encoding: [0xbf,0x72,0x09,0xd5]
-// CHECK: brb iall // encoding: [0x9f,0x72,0x09,0xd5]
-// CHECK: brb inj // encoding: [0xbf,0x72,0x09,0xd5]
-// ERROR-NO-BRBE: [[@LINE-8]]:1: error: instruction requires: brbe
-// ERROR-NO-BRBE: [[@LINE-8]]:1: error: instruction requires: brbe
+// ERROR-NO-BRBE: [[@LINE-4]]:1: error: instruction requires: brbe
+// ERROR-NO-BRBE: [[@LINE-4]]:1: error: instruction requires: brbe
brb IALL
brb INJ
>From 865fa12f2e0b32eb07177bf312f939ea777dc1cd Mon Sep 17 00:00:00 2001
From: Jonathan Thackray <jonathan.thackray at arm.com>
Date: Fri, 27 Mar 2026 23:34:07 +0000
Subject: [PATCH 3/7] fixup! Parse instructions in AArch64AsmParser.cpp
---
llvm/lib/Target/AArch64/AArch64InstrInfo.td | 14 ---
.../AArch64/AsmParser/AArch64AsmParser.cpp | 92 ++++++++++++++++++-
2 files changed, 87 insertions(+), 19 deletions(-)
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index 09a8a9a63fb7d..68b2b7257616e 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -2545,20 +2545,6 @@ def SYSLxt : SystemLXtI<1, "sysl">;
def : InstAlias<"sys $op1, $Cn, $Cm, $op2",
(SYSxt timm32_0_7:$op1, sys_cr_op:$Cn,
sys_cr_op:$Cm, timm32_0_7:$op2, XZR)>;
-def : InstAlias<"apas $Xt",
- (SYSxt 6, 7, 0, 0, GPR64:$Xt)>;
-def : InstAlias<"brb\tiall",
- (SYSxt 1, 7, 2, 4, XZR)>, Requires<[HasBRBE]>;
-def : InstAlias<"brb\tinj",
- (SYSxt 1, 7, 2, 5, XZR)>, Requires<[HasBRBE]>;
-def : InstAlias<"trcit $Rt",
- (SYSxt 3, 7, 2, 7, GPR64:$Rt)>, Requires<[HasITE]>;
-def : InstAlias<"gcspushx",
- (SYSxt 0, 7, 7, 4, XZR)>, Requires<[HasGCS]>;
-def : InstAlias<"gcspopcx",
- (SYSxt 0, 7, 7, 5, XZR)>, Requires<[HasGCS]>;
-def : InstAlias<"gcspopx",
- (SYSxt 0, 7, 7, 6, XZR)>, Requires<[HasGCS]>;
def : InstAlias<"gcspushm $Rt",
(SYSxt 3, 7, 7, 0, GPR64:$Rt)>, Requires<[HasGCS]>;
def : InstAlias<"gcsss1 $Rt",
diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
index 906117a066dd6..6690faae36619 100644
--- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -4033,9 +4033,9 @@ void AArch64AsmParser::createSysAlias(uint16_t Encoding, OperandVector &Operands
AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
}
-/// parseSysAlias - The IC, DC, AT, TLBI, MLBI and GIC{R} and GSB instructions
-/// are simple aliases for the SYS instruction. Parse them specially so that
-/// we create a SYS MCInst.
+/// parseSysAlias - The IC, DC, AT, TLBI, MLBI, APAS, BRB, TRCIT, GCS aliases,
+/// GIC{R} and GSB instructions are simple aliases for the SYS instruction.
+/// Parse them specially so that we create a SYS MCInst.
bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
OperandVector &Operands) {
if (Name.contains('.'))
@@ -4044,6 +4044,85 @@ bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
Mnemonic = Name;
Operands.push_back(AArch64Operand::CreateToken("sys", NameLoc, getContext()));
+ if (Mnemonic == "apas") {
+ const uint16_t Encoding = (6 << 11) | (7 << 7);
+ createSysAlias(Encoding, Operands, getLoc());
+
+ if (parseRegister(Operands))
+ return TokError("expected register operand");
+
+ if (parseToken(AsmToken::EndOfStatement,
+ "unexpected token in argument list"))
+ return true;
+
+ return false;
+ }
+
+ if (Mnemonic == "trcit") {
+ if (!(getSTI().hasFeature(AArch64::FeatureAll) ||
+ getSTI().hasFeature(AArch64::FeatureITE)))
+ return Error(NameLoc, "instruction requires: ite");
+
+ const uint16_t Encoding = (3 << 11) | (7 << 7) | (2 << 3) | 7;
+ createSysAlias(Encoding, Operands, getLoc());
+
+ if (parseRegister(Operands))
+ return TokError("expected register operand");
+
+ if (parseToken(AsmToken::EndOfStatement,
+ "unexpected token in argument list"))
+ return true;
+
+ return false;
+ }
+
+ if (Mnemonic == "gcspushx" || Mnemonic == "gcspopcx" || Mnemonic == "gcspopx") {
+ if (!(getSTI().hasFeature(AArch64::FeatureAll) ||
+ getSTI().hasFeature(AArch64::FeatureGCS)))
+ return Error(NameLoc, "instruction requires: gcs");
+
+ uint16_t Encoding = (7 << 7) | (7 << 3);
+ if (Mnemonic == "gcspushx")
+ Encoding |= 4;
+ else if (Mnemonic == "gcspopcx")
+ Encoding |= 5;
+ else
+ Encoding |= 6;
+ createSysAlias(Encoding, Operands, getLoc());
+
+ if (parseToken(AsmToken::EndOfStatement,
+ "unexpected token in argument list"))
+ return true;
+
+ return false;
+ }
+
+ if (Mnemonic == "brb") {
+ if (!(getSTI().hasFeature(AArch64::FeatureAll) ||
+ getSTI().hasFeature(AArch64::FeatureBRBE)))
+ return Error(NameLoc, "instruction requires: brbe");
+
+ const AsmToken &Tok = getTok();
+ StringRef Op = Tok.getString();
+ SMLoc S = Tok.getLoc();
+ uint16_t Encoding = 0;
+ if (Op.equals_insensitive("iall"))
+ Encoding = (1 << 11) | (7 << 7) | (2 << 3) | 4;
+ else if (Op.equals_insensitive("inj"))
+ Encoding = (1 << 11) | (7 << 7) | (2 << 3) | 5;
+ else
+ return TokError("invalid operand for BRB instruction");
+
+ createSysAlias(Encoding, Operands, S);
+ Lex(); // Eat operand.
+
+ if (parseToken(AsmToken::EndOfStatement,
+ "unexpected token in argument list"))
+ return true;
+
+ return false;
+ }
+
const AsmToken &Tok = getTok();
StringRef Op = Tok.getString();
SMLoc S = Tok.getLoc();
@@ -5506,11 +5585,14 @@ bool AArch64AsmParser::parseInstruction(ParseInstructionInfo &Info,
size_t Start = 0, Next = Name.find('.');
StringRef Head = Name.slice(Start, Next);
- // IC, DC, AT, TLBI, MLBI, PLBI, GIC{R}, GSB and Prediction invalidation
+ // IC, DC, AT, TLBI, MLBI, PLBI, APAS, BRB, TRCIT, GCS aliases, GIC{R},
+ // GSB and Prediction invalidation
// instructions are aliases for the SYS instruction.
if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi" ||
Head == "cfp" || Head == "dvp" || Head == "cpp" || Head == "cosp" ||
- Head == "mlbi" || Head == "plbi" || Head == "gic" || Head == "gsb")
+ Head == "mlbi" || Head == "plbi" || Head == "gic" || Head == "gsb" ||
+ Head == "apas" || Head == "brb" || Head == "trcit" ||
+ Head == "gcspushx" || Head == "gcspopcx" || Head == "gcspopx")
return parseSysAlias(Head, NameLoc, Operands);
// GICR instructions are aliases for the SYSL instruction.
>From b4582a214515b5f367c2251fb685ef4e927ae8f2 Mon Sep 17 00:00:00 2001
From: Jonathan Thackray <jonathan.thackray at arm.com>
Date: Mon, 30 Mar 2026 11:23:29 +0100
Subject: [PATCH 4/7] fixup! Improve printing code for tabs and commas
---
.../AArch64/MCTargetDesc/AArch64InstPrinter.cpp | 13 +++++--------
1 file changed, 5 insertions(+), 8 deletions(-)
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp
index 979a16baa9df8..e5a80900df25e 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp
@@ -919,6 +919,7 @@ bool AArch64InstPrinter::printSysAlias(const MCInst *MI,
bool OptionalReg = false;
std::string Ins;
std::string Name;
+ StringRef RegSep = ", ";
if (CnVal == 7) {
switch (CmVal) {
@@ -929,6 +930,7 @@ bool AArch64InstPrinter::printSysAlias(const MCInst *MI,
NeedsReg = true;
Ins = "apas";
Name = "";
+ RegSep = "\t";
break;
}
@@ -980,6 +982,7 @@ bool AArch64InstPrinter::printSysAlias(const MCInst *MI,
NeedsReg = true;
Ins = "trcit";
Name = "";
+ RegSep = "\t";
break;
}
} break;
@@ -1063,6 +1066,7 @@ bool AArch64InstPrinter::printSysAlias(const MCInst *MI,
return false;
Name = "";
+ RegSep = "\t";
switch (Op1Val) {
default:
return false;
@@ -1154,13 +1158,6 @@ bool AArch64InstPrinter::printSysAlias(const MCInst *MI,
if (NotXZR && !NeedsReg && !OptionalReg)
return false;
- if (Name.empty()) {
- O << '\t' << Ins;
- if (NeedsReg || (OptionalReg && NotXZR))
- O << '\t' << Reg;
- return true;
- }
-
std::string Str = Ins + Name;
llvm::transform(Str, Str.begin(), ::tolower);
@@ -1169,7 +1166,7 @@ bool AArch64InstPrinter::printSysAlias(const MCInst *MI,
// For optional registers, don't print the value if it's xzr/x31
// since this defaults to xzr/x31 if register is not specified.
if (NeedsReg || (OptionalReg && NotXZR))
- O << ", " << Reg;
+ O << RegSep << Reg;
return true;
}
>From c4a194fc2e813f579bf0f2f70fa2fdcf1cb1b684 Mon Sep 17 00:00:00 2001
From: Jonathan Thackray <jonathan.thackray at arm.com>
Date: Thu, 2 Apr 2026 19:16:39 +0100
Subject: [PATCH 5/7] fixup! Ensure GCSPUSHM, GCSSS1, GCSPOPM and GCSSS2 are
all converted
---
.../Target/AArch64/AArch64ISelDAGToDAG.cpp | 14 ++++--
.../lib/Target/AArch64/AArch64InstrFormats.td | 23 +++++++--
llvm/lib/Target/AArch64/AArch64InstrInfo.td | 50 ++++---------------
.../AArch64/AArch64SchedFalkorDetails.td | 2 +-
.../AArch64/AsmParser/AArch64AsmParser.cpp | 3 +-
.../MCTargetDesc/AArch64InstPrinter.cpp | 15 +++---
6 files changed, 51 insertions(+), 56 deletions(-)
diff --git a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
index 09ff2209a67eb..93e0aedcb0304 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
@@ -5077,10 +5077,18 @@ void AArch64DAGToDAGISel::Select(SDNode *Node) {
SDValue Chain = Node->getOperand(0);
SDValue Val = Node->getOperand(2);
SDValue Zero = CurDAG->getCopyFromReg(Chain, DL, AArch64::XZR, MVT::i64);
+ SDValue Op1 = CurDAG->getTargetConstant(3, DL, MVT::i32);
+ SDValue Cn = CurDAG->getTargetConstant(7, DL, MVT::i32);
+ SDValue Cm = CurDAG->getTargetConstant(7, DL, MVT::i32);
+ SDValue SS1Op2 = CurDAG->getTargetConstant(2, DL, MVT::i32);
+ SDValue SS2Op2 = CurDAG->getTargetConstant(3, DL, MVT::i32);
+ SDValue SS1Ops[] = {Op1, Cn, Cm, SS1Op2, Val, Chain};
SDNode *SS1 =
- CurDAG->getMachineNode(AArch64::GCSSS1, DL, MVT::Other, Val, Chain);
- SDNode *SS2 = CurDAG->getMachineNode(AArch64::GCSSS2, DL, MVT::i64,
- MVT::Other, Zero, SDValue(SS1, 0));
+ CurDAG->getMachineNode(AArch64::SYSxt, DL, MVT::Other, SS1Ops);
+ SDValue SS2Ops[] = {Zero, Op1, Cn, Cm, SS2Op2, SDValue(SS1, 0)};
+ SDNode *SS2 = CurDAG->getMachineNode(
+ AArch64::SYSLxt_GCS, DL, CurDAG->getVTList(MVT::i64, MVT::Other),
+ SS2Ops);
ReplaceNode(Node, SS2);
return;
}
diff --git a/llvm/lib/Target/AArch64/AArch64InstrFormats.td b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
index 0c2bd5313cf0e..4d62ce5e6d822 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrFormats.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
@@ -2143,10 +2143,8 @@ class SystemXtI<string asm>
let hasSideEffects = 1;
}
-class SystemLXtI<bit L, string asm>
- : RtSystemI<L, (outs),
- (ins GPR64:$Rt, imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2),
- asm, "\t$Rt, $op1, $Cn, $Cm, $op2"> {
+class BaseSystemLXtI<bit L, dag oops, dag iops, string asm>
+ : RtSystemI<L, oops, iops, asm, "\t$Rt, $op1, $Cn, $Cm, $op2"> {
bits<3> op1;
bits<4> Cn;
bits<4> Cm;
@@ -2158,6 +2156,23 @@ class SystemLXtI<bit L, string asm>
let Inst{7-5} = op2;
}
+class SystemLXtI<bit L, string asm>
+ : BaseSystemLXtI<L, (outs),
+ (ins GPR64:$Rt, imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm,
+ imm0_7:$op2), asm>;
+
+// GCS SYSL operations preserve the old destination value when GCS is disabled
+// at runtime, so codegen needs a tied def/use form for those cases only.
+class GCSTiedSystemLXtI<bit L, string asm>
+ : BaseSystemLXtI<L, (outs GPR64:$Rt),
+ (ins GPR64:$src, imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm,
+ imm0_7:$op2), asm> {
+ let mayLoad = 1;
+ let mayStore = 1;
+ let hasSideEffects = 1;
+ let Constraints = "$src = $Rt";
+}
+
def RangePrefetchOperand : AsmOperandClass {
let Name = "RangePrefetch";
let ParserMethod = "tryParseRPRFMOperand";
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index 68b2b7257616e..079c12e722350 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -1635,44 +1635,6 @@ def : TokenAlias<"IALL", "iall">;
// ARMv9.4-A Guarded Control Stack
-class GCSRtIn<bits<3> op1, bits<3> op2, string mnemonic,
- list<dag> pattern = []>
- : RtSystemI<0, (outs), (ins GPR64:$Rt), mnemonic, "\t$Rt", pattern> {
- let Inst{20-19} = 0b01;
- let Inst{18-16} = op1;
- let Inst{15-8} = 0b01110111;
- let Inst{7-5} = op2;
- let Predicates = [HasGCS];
- let hasSideEffects = 1;
-}
-
-let mayStore = 1, mayLoad = 1 in
-def GCSSS1 : GCSRtIn<0b011, 0b010, "gcsss1">;
-let mayStore = 1 in
-def GCSPUSHM : GCSRtIn<0b011, 0b000, "gcspushm">;
-
-class GCSRtOut<bits<3> op1, bits<3> op2, string mnemonic,
- list<dag> pattern = []>
- : RtSystemI<1, (outs GPR64:$Rt), (ins GPR64:$src), mnemonic, "\t$Rt", pattern> {
- let Inst{20-19} = 0b01;
- let Inst{18-16} = op1;
- let Inst{15-8} = 0b01110111;
- let Inst{7-5} = op2;
- let Predicates = [HasGCS];
- let hasSideEffects = 1;
- // The input register is unchanged when GCS is disabled, so we need it as
- // both an input and output operand.
- let Constraints = "$src = $Rt";
-}
-
-let mayStore = 1, mayLoad = 1 in
-def GCSSS2 : GCSRtOut<0b011, 0b011, "gcsss2">;
-// FIXME: mayStore = 1 only needed to match the intrinsic definition
-let mayStore = 1, mayLoad = 1 in
-def GCSPOPM : GCSRtOut<0b011, 0b001, "gcspopm",
- [(set GPR64:$Rt, (int_aarch64_gcspopm GPR64:$src))]>;
-def GCSPOPM_NoOp : InstAlias<"gcspopm", (GCSPOPM XZR)>, Requires<[HasGCS]>; // Rt defaults to XZR if absent
-
def GCSB_DSYNC_disable : InstAlias<"gcsb\tdsync", (HINT 19), 0>;
def GCSB_DSYNC : InstAlias<"gcsb\tdsync", (HINT 19), 1>, Requires<[HasGCS]>;
@@ -2541,6 +2503,9 @@ def MSR_FPMR : Pseudo<(outs), (ins GPR64:$val),
// Generic system instructions
def SYSxt : SystemXtI<"sys">;
def SYSLxt : SystemLXtI<1, "sysl">;
+def SYSLxt_GCS : GCSTiedSystemLXtI<1, "sysl"> {
+ let isCodeGenOnly = 1;
+}
def : InstAlias<"sys $op1, $Cn, $Cm, $op2",
(SYSxt timm32_0_7:$op1, sys_cr_op:$Cn,
@@ -2550,11 +2515,14 @@ def : InstAlias<"gcspushm $Rt",
def : InstAlias<"gcsss1 $Rt",
(SYSxt 3, 7, 7, 2, GPR64:$Rt)>, Requires<[HasGCS]>;
def : InstAlias<"gcspopm",
- (SYSLxt XZR, 3, 7, 7, 1)>, Requires<[HasGCS]>;
+ (SYSLxt_GCS XZR, 3, 7, 7, 1)>, Requires<[HasGCS]>;
def : InstAlias<"gcspopm $Rt",
- (SYSLxt GPR64:$Rt, 3, 7, 7, 1)>, Requires<[HasGCS]>;
+ (SYSLxt_GCS GPR64:$Rt, 3, 7, 7, 1)>, Requires<[HasGCS]>;
def : InstAlias<"gcsss2 $Rt",
- (SYSLxt GPR64:$Rt, 3, 7, 7, 3)>, Requires<[HasGCS]>;
+ (SYSLxt_GCS GPR64:$Rt, 3, 7, 7, 3)>, Requires<[HasGCS]>;
+let Predicates = [HasGCS] in
+def : Pat<(int_aarch64_gcspopm GPR64:$Rt),
+ (SYSLxt_GCS GPR64:$Rt, 3, 7, 7, 1)>;
//===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/AArch64/AArch64SchedFalkorDetails.td b/llvm/lib/Target/AArch64/AArch64SchedFalkorDetails.td
index 375e3652c9e87..cc864cb2bf5ec 100644
--- a/llvm/lib/Target/AArch64/AArch64SchedFalkorDetails.td
+++ b/llvm/lib/Target/AArch64/AArch64SchedFalkorDetails.td
@@ -1243,7 +1243,7 @@ def : InstRW<[WriteSequence<[FalkorWr_1LD_3cyc, FalkorWr_1XYZ_1cyc]>],
// -----------------------------------------------------------------------------
def : InstRW<[FalkorWr_1LD_0cyc], (instrs CLREX, DMB, DSB)>;
def : InstRW<[FalkorWr_1none_0cyc], (instrs BRK, DCPS1, DCPS2, DCPS3, HINT, HLT, HVC, ISB, SMC, SVC)>;
-def : InstRW<[FalkorWr_1ST_0cyc], (instrs SYSxt, SYSLxt)>;
+def : InstRW<[FalkorWr_1ST_0cyc], (instrs SYSxt, SYSLxt, SYSLxt_GCS)>;
def : InstRW<[FalkorWr_1Z_0cyc], (instrs MSRpstateImm1, MSRpstateImm4)>;
def : InstRW<[FalkorWr_1LD_3cyc, FalkorReadIncLd],
diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
index 6690faae36619..de10cf0557d69 100644
--- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -4076,7 +4076,8 @@ bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
return false;
}
- if (Mnemonic == "gcspushx" || Mnemonic == "gcspopcx" || Mnemonic == "gcspopx") {
+ if (Mnemonic == "gcspushx" || Mnemonic == "gcspopcx" ||
+ Mnemonic == "gcspopx") {
if (!(getSTI().hasFeature(AArch64::FeatureAll) ||
getSTI().hasFeature(AArch64::FeatureGCS)))
return Error(NameLoc, "instruction requires: gcs");
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp
index e5a80900df25e..8306e49207700 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp
@@ -84,7 +84,7 @@ void AArch64InstPrinter::printInst(const MCInst *MI, uint64_t Address,
return;
}
- if (Opcode == AArch64::SYSLxt)
+ if (Opcode == AArch64::SYSLxt || Opcode == AArch64::SYSLxt_GCS)
if (printSyslAlias(MI, STI, O)) {
printAnnotation(O, Annot);
return;
@@ -1176,14 +1176,17 @@ bool AArch64InstPrinter::printSyslAlias(const MCInst *MI,
raw_ostream &O) {
#ifndef NDEBUG
unsigned Opcode = MI->getOpcode();
- assert(Opcode == AArch64::SYSLxt && "Invalid opcode for SYSL alias!");
+ assert((Opcode == AArch64::SYSLxt || Opcode == AArch64::SYSLxt_GCS) &&
+ "Invalid opcode for SYSL alias!");
#endif
+ unsigned OpOffset = Opcode == AArch64::SYSLxt_GCS ? 1 : 0;
+
StringRef Reg = getRegisterName(MI->getOperand(0).getReg());
- const MCOperand &Op1 = MI->getOperand(1);
- const MCOperand &Cn = MI->getOperand(2);
- const MCOperand &Cm = MI->getOperand(3);
- const MCOperand &Op2 = MI->getOperand(4);
+ const MCOperand &Op1 = MI->getOperand(OpOffset + 1);
+ const MCOperand &Cn = MI->getOperand(OpOffset + 2);
+ const MCOperand &Cm = MI->getOperand(OpOffset + 3);
+ const MCOperand &Op2 = MI->getOperand(OpOffset + 4);
unsigned Op1Val = Op1.getImm();
unsigned CnVal = Cn.getImm();
>From 4bc3ec9a05a47f2ddfc2a92dfa56e223e35ca1ce Mon Sep 17 00:00:00 2001
From: Jonathan Thackray <jonathan.thackray at arm.com>
Date: Mon, 13 Apr 2026 15:27:20 +0100
Subject: [PATCH 6/7] fixup! Add negative tests, and revert 391c34289 (move to
aliases in Tablegen)
---
.../lib/Target/AArch64/AArch64InstrFormats.td | 8 +-
llvm/lib/Target/AArch64/AArch64InstrInfo.td | 14 +++
.../AArch64/AsmParser/AArch64AsmParser.cpp | 93 +------------------
.../MCTargetDesc/AArch64InstPrinter.cpp | 4 +-
llvm/test/MC/AArch64/arm64-aliases.s | 14 +++
llvm/test/MC/AArch64/armv9a-sysp-pairs.s | 25 -----
llvm/test/MC/AArch64/armv9a-sysp.s | 8 ++
llvm/test/MC/AArch64/armv9a-tlbip.s | 7 ++
8 files changed, 54 insertions(+), 119 deletions(-)
delete mode 100644 llvm/test/MC/AArch64/armv9a-sysp-pairs.s
diff --git a/llvm/lib/Target/AArch64/AArch64InstrFormats.td b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
index 4d62ce5e6d822..f1c9300024373 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrFormats.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
@@ -2161,16 +2161,16 @@ class SystemLXtI<bit L, string asm>
(ins GPR64:$Rt, imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm,
imm0_7:$op2), asm>;
-// GCS SYSL operations preserve the old destination value when GCS is disabled
-// at runtime, so codegen needs a tied def/use form for those cases only.
+// Codegen-only GCS SYSL operations need a tied def/use on Rt because they
+// preserve the old destination value when GCS is disabled at runtime.
class GCSTiedSystemLXtI<bit L, string asm>
: BaseSystemLXtI<L, (outs GPR64:$Rt),
- (ins GPR64:$src, imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm,
+ (ins GPR64:$_Rt, imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm,
imm0_7:$op2), asm> {
let mayLoad = 1;
let mayStore = 1;
let hasSideEffects = 1;
- let Constraints = "$src = $Rt";
+ let Constraints = "$Rt = $_Rt";
}
def RangePrefetchOperand : AsmOperandClass {
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index 079c12e722350..2f1562afa9b41 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -2510,6 +2510,20 @@ def SYSLxt_GCS : GCSTiedSystemLXtI<1, "sysl"> {
def : InstAlias<"sys $op1, $Cn, $Cm, $op2",
(SYSxt timm32_0_7:$op1, sys_cr_op:$Cn,
sys_cr_op:$Cm, timm32_0_7:$op2, XZR)>;
+def : InstAlias<"apas $Xt",
+ (SYSxt 6, 7, 0, 0, GPR64:$Xt)>;
+def : InstAlias<"brb\tiall",
+ (SYSxt 1, 7, 2, 4, XZR)>, Requires<[HasBRBE]>;
+def : InstAlias<"brb\tinj",
+ (SYSxt 1, 7, 2, 5, XZR)>, Requires<[HasBRBE]>;
+def : InstAlias<"trcit $Rt",
+ (SYSxt 3, 7, 2, 7, GPR64:$Rt)>, Requires<[HasITE]>;
+def : InstAlias<"gcspushx",
+ (SYSxt 0, 7, 7, 4, XZR)>, Requires<[HasGCS]>;
+def : InstAlias<"gcspopcx",
+ (SYSxt 0, 7, 7, 5, XZR)>, Requires<[HasGCS]>;
+def : InstAlias<"gcspopx",
+ (SYSxt 0, 7, 7, 6, XZR)>, Requires<[HasGCS]>;
def : InstAlias<"gcspushm $Rt",
(SYSxt 3, 7, 7, 0, GPR64:$Rt)>, Requires<[HasGCS]>;
def : InstAlias<"gcsss1 $Rt",
diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
index de10cf0557d69..906117a066dd6 100644
--- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -4033,9 +4033,9 @@ void AArch64AsmParser::createSysAlias(uint16_t Encoding, OperandVector &Operands
AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
}
-/// parseSysAlias - The IC, DC, AT, TLBI, MLBI, APAS, BRB, TRCIT, GCS aliases,
-/// GIC{R} and GSB instructions are simple aliases for the SYS instruction.
-/// Parse them specially so that we create a SYS MCInst.
+/// parseSysAlias - The IC, DC, AT, TLBI, MLBI and GIC{R} and GSB instructions
+/// are simple aliases for the SYS instruction. Parse them specially so that
+/// we create a SYS MCInst.
bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
OperandVector &Operands) {
if (Name.contains('.'))
@@ -4044,86 +4044,6 @@ bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
Mnemonic = Name;
Operands.push_back(AArch64Operand::CreateToken("sys", NameLoc, getContext()));
- if (Mnemonic == "apas") {
- const uint16_t Encoding = (6 << 11) | (7 << 7);
- createSysAlias(Encoding, Operands, getLoc());
-
- if (parseRegister(Operands))
- return TokError("expected register operand");
-
- if (parseToken(AsmToken::EndOfStatement,
- "unexpected token in argument list"))
- return true;
-
- return false;
- }
-
- if (Mnemonic == "trcit") {
- if (!(getSTI().hasFeature(AArch64::FeatureAll) ||
- getSTI().hasFeature(AArch64::FeatureITE)))
- return Error(NameLoc, "instruction requires: ite");
-
- const uint16_t Encoding = (3 << 11) | (7 << 7) | (2 << 3) | 7;
- createSysAlias(Encoding, Operands, getLoc());
-
- if (parseRegister(Operands))
- return TokError("expected register operand");
-
- if (parseToken(AsmToken::EndOfStatement,
- "unexpected token in argument list"))
- return true;
-
- return false;
- }
-
- if (Mnemonic == "gcspushx" || Mnemonic == "gcspopcx" ||
- Mnemonic == "gcspopx") {
- if (!(getSTI().hasFeature(AArch64::FeatureAll) ||
- getSTI().hasFeature(AArch64::FeatureGCS)))
- return Error(NameLoc, "instruction requires: gcs");
-
- uint16_t Encoding = (7 << 7) | (7 << 3);
- if (Mnemonic == "gcspushx")
- Encoding |= 4;
- else if (Mnemonic == "gcspopcx")
- Encoding |= 5;
- else
- Encoding |= 6;
- createSysAlias(Encoding, Operands, getLoc());
-
- if (parseToken(AsmToken::EndOfStatement,
- "unexpected token in argument list"))
- return true;
-
- return false;
- }
-
- if (Mnemonic == "brb") {
- if (!(getSTI().hasFeature(AArch64::FeatureAll) ||
- getSTI().hasFeature(AArch64::FeatureBRBE)))
- return Error(NameLoc, "instruction requires: brbe");
-
- const AsmToken &Tok = getTok();
- StringRef Op = Tok.getString();
- SMLoc S = Tok.getLoc();
- uint16_t Encoding = 0;
- if (Op.equals_insensitive("iall"))
- Encoding = (1 << 11) | (7 << 7) | (2 << 3) | 4;
- else if (Op.equals_insensitive("inj"))
- Encoding = (1 << 11) | (7 << 7) | (2 << 3) | 5;
- else
- return TokError("invalid operand for BRB instruction");
-
- createSysAlias(Encoding, Operands, S);
- Lex(); // Eat operand.
-
- if (parseToken(AsmToken::EndOfStatement,
- "unexpected token in argument list"))
- return true;
-
- return false;
- }
-
const AsmToken &Tok = getTok();
StringRef Op = Tok.getString();
SMLoc S = Tok.getLoc();
@@ -5586,14 +5506,11 @@ bool AArch64AsmParser::parseInstruction(ParseInstructionInfo &Info,
size_t Start = 0, Next = Name.find('.');
StringRef Head = Name.slice(Start, Next);
- // IC, DC, AT, TLBI, MLBI, PLBI, APAS, BRB, TRCIT, GCS aliases, GIC{R},
- // GSB and Prediction invalidation
+ // IC, DC, AT, TLBI, MLBI, PLBI, GIC{R}, GSB and Prediction invalidation
// instructions are aliases for the SYS instruction.
if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi" ||
Head == "cfp" || Head == "dvp" || Head == "cpp" || Head == "cosp" ||
- Head == "mlbi" || Head == "plbi" || Head == "gic" || Head == "gsb" ||
- Head == "apas" || Head == "brb" || Head == "trcit" ||
- Head == "gcspushx" || Head == "gcspopcx" || Head == "gcspopx")
+ Head == "mlbi" || Head == "plbi" || Head == "gic" || Head == "gsb")
return parseSysAlias(Head, NameLoc, Operands);
// GICR instructions are aliases for the SYSL instruction.
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp
index 8306e49207700..d513d47ebd52f 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp
@@ -1065,8 +1065,8 @@ bool AArch64InstPrinter::printSysAlias(const MCInst *MI,
STI.hasFeature(AArch64::FeatureGCS)))
return false;
- Name = "";
RegSep = "\t";
+ Name = "";
switch (Op1Val) {
default:
return false;
@@ -1174,8 +1174,8 @@ bool AArch64InstPrinter::printSysAlias(const MCInst *MI,
bool AArch64InstPrinter::printSyslAlias(const MCInst *MI,
const MCSubtargetInfo &STI,
raw_ostream &O) {
-#ifndef NDEBUG
unsigned Opcode = MI->getOpcode();
+#ifndef NDEBUG
assert((Opcode == AArch64::SYSLxt || Opcode == AArch64::SYSLxt_GCS) &&
"Invalid opcode for SYSL alias!");
#endif
diff --git a/llvm/test/MC/AArch64/arm64-aliases.s b/llvm/test/MC/AArch64/arm64-aliases.s
index f61809e559a00..4d7444fb67afe 100644
--- a/llvm/test/MC/AArch64/arm64-aliases.s
+++ b/llvm/test/MC/AArch64/arm64-aliases.s
@@ -1,7 +1,10 @@
; RUN: llvm-mc -triple arm64-apple-darwin -mattr=neon -output-asm-variant=1 -show-encoding -print-imm-hex < %s | FileCheck %s
; RUN: llvm-mc -triple arm64-apple-darwin -mattr=neon,+ite -filetype=obj < %s | llvm-objdump -d --mattr=+ite --no-print-imm-hex - | FileCheck %s --check-prefix=CHECK-ITE
+; RUN: llvm-mc -triple arm64-apple-darwin -mattr=neon,+ite -filetype=obj < %s | llvm-objdump -d --mattr=-ite --no-print-imm-hex - | FileCheck %s --check-prefix=CHECK-NO-ITE
; RUN: llvm-mc -triple arm64-apple-darwin -mattr=neon,+gcs -filetype=obj < %s | llvm-objdump -d --mattr=+gcs --no-print-imm-hex - | FileCheck %s --check-prefix=CHECK-GCS
+; RUN: llvm-mc -triple arm64-apple-darwin -mattr=neon,+gcs -filetype=obj < %s | llvm-objdump -d --mattr=-gcs --no-print-imm-hex - | FileCheck %s --check-prefix=CHECK-NO-GCS
; RUN: llvm-mc -triple arm64-apple-darwin -mattr=neon,+brbe -filetype=obj < %s | llvm-objdump -d --mattr=+brbe --no-print-imm-hex - | FileCheck %s --check-prefix=CHECK-BRBE
+; RUN: llvm-mc -triple arm64-apple-darwin -mattr=neon,+brbe -filetype=obj < %s | llvm-objdump -d --mattr=-brbe --no-print-imm-hex - | FileCheck %s --check-prefix=CHECK-NO-BRBE
; RUN: llvm-mc -triple arm64-apple-darwin -mattr=neon -filetype=obj < %s | llvm-objdump -d --no-print-imm-hex - | FileCheck %s --check-prefix=CHECK-RME
foo:
@@ -532,28 +535,39 @@ foo:
sys #3, c7, c2, #7, x2
; CHECK-ITE: trcit x2
+; CHECK-NO-ITE: sys #3, c7, c2, #7, x2
sys #3, c7, c7, #2, x20
; CHECK-GCS: gcsss1 x20
+; CHECK-NO-GCS: sys #3, c7, c7, #2, x20
sysl x23, #3, c7, c7, #3
; CHECK-GCS: gcsss2 x23
+; CHECK-NO-GCS: sysl x23, #3, c7, c7, #3
sys #3, c7, c7, #0, x24
; CHECK-GCS: gcspushm x24
+; CHECK-NO-GCS: sys #3, c7, c7, #0, x24
sysl xzr, #3, c7, c7, #1
; CHECK-GCS: gcspopm
+; CHECK-NO-GCS: sysl xzr, #3, c7, c7, #1
sysl x24, #3, c7, c7, #1
; CHECK-GCS: gcspopm x24
+; CHECK-NO-GCS: sysl x24, #3, c7, c7, #1
sys #0, c7, c7, #4
; CHECK-GCS: gcspushx
+; CHECK-NO-GCS: sys #0, c7, c7, #4
sys #0, c7, c7, #5
; CHECK-GCS: gcspopcx
+; CHECK-NO-GCS: sys #0, c7, c7, #5
sys #0, c7, c7, #6
; CHECK-GCS: gcspopx
+; CHECK-NO-GCS: sys #0, c7, c7, #6
sys #1, c7, c2, #4
; CHECK-BRBE: brb iall
+; CHECK-NO-BRBE: sys #1, c7, c2, #4
sys #1, c7, c2, #5
; CHECK-BRBE: brb inj
+; CHECK-NO-BRBE: sys #1, c7, c2, #5
sys #6, c7, c0, #0, x3
; CHECK-RME: apas x3
diff --git a/llvm/test/MC/AArch64/armv9a-sysp-pairs.s b/llvm/test/MC/AArch64/armv9a-sysp-pairs.s
deleted file mode 100644
index 87990fb122ecc..0000000000000
--- a/llvm/test/MC/AArch64/armv9a-sysp-pairs.s
+++ /dev/null
@@ -1,25 +0,0 @@
-// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+d128,+tlb-rmi < %s \
-// RUN: | FileCheck %s --check-prefixes=CHECK-ASM,CHECK-ENCODING
-// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+d128,+tlb-rmi < %s \
-// RUN: | llvm-objdump -d --mattr=-d128,-tlb-rmi --no-print-imm-hex - \
-// RUN: | FileCheck %s --check-prefix=CHECK-DIS
-
-sysp #0, c8, c2, #2, x8, x9
-// CHECK-ASM: sysp #0, c8, c2, #2, x8, x9
-// CHECK-ENCODING: encoding: [0x48,0x82,0x48,0xd5]
-// CHECK-DIS: sysp #0, c8, c2, #2, x8, x9
-
-sysp #0, c8, c2, #2, xzr, xzr
-// CHECK-ASM: sysp #0, c8, c2, #2
-// CHECK-ENCODING: encoding: [0x5f,0x82,0x48,0xd5]
-// CHECK-DIS: sysp #0, c8, c2, #2
-
-tlbip VAE1, x8, x9
-// CHECK-ASM: tlbip vae1, x8, x9
-// CHECK-ENCODING: encoding: [0x28,0x87,0x48,0xd5]
-// CHECK-DIS: sysp #0, c8, c7, #1, x8, x9
-
-tlbip VAE1, xzr, xzr
-// CHECK-ASM: tlbip vae1, xzr, xzr
-// CHECK-ENCODING: encoding: [0x3f,0x87,0x48,0xd5]
-// CHECK-DIS: sysp #0, c8, c7, #1
diff --git a/llvm/test/MC/AArch64/armv9a-sysp.s b/llvm/test/MC/AArch64/armv9a-sysp.s
index f1e039f3e8770..9ed1027ad88c1 100644
--- a/llvm/test/MC/AArch64/armv9a-sysp.s
+++ b/llvm/test/MC/AArch64/armv9a-sysp.s
@@ -45,6 +45,14 @@ sysp #4, c2, c1, #0, x0, x1// VTTBR_EL2 3 4 2 1 0
// CHECK-INST: sysp #4, c2, c1, #0, x0, x1
// CHECK-ENCODING: encoding: [0x00,0x21,0x4c,0xd5]
+sysp #0, c8, c2, #2, x8, x9
+// CHECK-INST: sysp #0, c8, c2, #2, x8, x9
+// CHECK-ENCODING: encoding: [0x48,0x82,0x48,0xd5]
+
+sysp #0, c8, c2, #2, xzr, xzr
+// CHECK-INST: sysp #0, c8, c2, #2
+// CHECK-ENCODING: encoding: [0x5f,0x82,0x48,0xd5]
+
sysp #0, c2, c0, #0, x0, x1
// CHECK-INST: sysp #0, c2, c0, #0, x0, x1
// CHECK-ENCODING: encoding: [0x00,0x20,0x48,0xd5]
diff --git a/llvm/test/MC/AArch64/armv9a-tlbip.s b/llvm/test/MC/AArch64/armv9a-tlbip.s
index 8764a83809472..9e3937726989a 100644
--- a/llvm/test/MC/AArch64/armv9a-tlbip.s
+++ b/llvm/test/MC/AArch64/armv9a-tlbip.s
@@ -55,6 +55,13 @@ tlbip VAE1, x8, x9
// CHECK-TLBID: error: instruction requires: d128
// CHECK-UNKNOWN: d5488728 sysp #0, c8, c7, #1, x8, x9
+tlbip VAE1, xzr, xzr
+// CHECK-INST: tlbip vae1, xzr, xzr
+// CHECK-ENCODING: encoding: [0x3f,0x87,0x48,0xd5]
+// CHECK-ERROR: error: instruction requires: d128
+// CHECK-TLBID: error: instruction requires: d128
+// CHECK-UNKNOWN: d548873f sysp #0, c8, c7, #1
+
tlbip VAE1NXS, x8, x9
// CHECK-INST: tlbip vae1nxs, x8, x9
// CHECK-ENCODING: encoding: [0x28,0x97,0x48,0xd5]
>From ab3cc369e4129565a0a3a410b51c0c3a2b389a30 Mon Sep 17 00:00:00 2001
From: Jonathan Thackray <jonathan.thackray at arm.com>
Date: Tue, 14 Apr 2026 14:08:16 +0100
Subject: [PATCH 7/7] fixup! SYSL only has dest register
---
.../lib/Target/AArch64/AArch64InstrFormats.td | 18 ++++++------
llvm/lib/Target/AArch64/AArch64InstrInfo.td | 13 +++++----
.../MCTargetDesc/AArch64InstPrinter.cpp | 29 +++++--------------
3 files changed, 23 insertions(+), 37 deletions(-)
diff --git a/llvm/lib/Target/AArch64/AArch64InstrFormats.td b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
index f1c9300024373..fb483f88931aa 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrFormats.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
@@ -2157,20 +2157,20 @@ class BaseSystemLXtI<bit L, dag oops, dag iops, string asm>
}
class SystemLXtI<bit L, string asm>
- : BaseSystemLXtI<L, (outs),
- (ins GPR64:$Rt, imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm,
- imm0_7:$op2), asm>;
-
-// Codegen-only GCS SYSL operations need a tied def/use on Rt because they
-// preserve the old destination value when GCS is disabled at runtime.
-class GCSTiedSystemLXtI<bit L, string asm>
: BaseSystemLXtI<L, (outs GPR64:$Rt),
+ (ins imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2), asm>;
+
+// Codegen-only GCS SYSL operations preserve the incoming Rt value when GCS is
+// disabled at runtime, so keep a tied def/use pseudo until asm emission.
+class GCSTiedSystemLXtPseudo
+ : Pseudo<(outs GPR64:$Rt),
(ins GPR64:$_Rt, imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm,
- imm0_7:$op2), asm> {
+ imm0_7:$op2), [], "$Rt = $_Rt">,
+ Sched<[WriteSys]> {
let mayLoad = 1;
let mayStore = 1;
let hasSideEffects = 1;
- let Constraints = "$Rt = $_Rt";
+ let Size = 4;
}
def RangePrefetchOperand : AsmOperandClass {
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index 2f1562afa9b41..826ac70f47375 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -2503,9 +2503,10 @@ def MSR_FPMR : Pseudo<(outs), (ins GPR64:$val),
// Generic system instructions
def SYSxt : SystemXtI<"sys">;
def SYSLxt : SystemLXtI<1, "sysl">;
-def SYSLxt_GCS : GCSTiedSystemLXtI<1, "sysl"> {
- let isCodeGenOnly = 1;
-}
+def SYSLxt_GCS : GCSTiedSystemLXtPseudo,
+ PseudoInstExpansion<(SYSLxt GPR64:$Rt, imm0_7:$op1,
+ sys_cr_op:$Cn, sys_cr_op:$Cm,
+ imm0_7:$op2)>;
def : InstAlias<"sys $op1, $Cn, $Cm, $op2",
(SYSxt timm32_0_7:$op1, sys_cr_op:$Cn,
@@ -2529,11 +2530,11 @@ def : InstAlias<"gcspushm $Rt",
def : InstAlias<"gcsss1 $Rt",
(SYSxt 3, 7, 7, 2, GPR64:$Rt)>, Requires<[HasGCS]>;
def : InstAlias<"gcspopm",
- (SYSLxt_GCS XZR, 3, 7, 7, 1)>, Requires<[HasGCS]>;
+ (SYSLxt XZR, 3, 7, 7, 1)>, Requires<[HasGCS]>;
def : InstAlias<"gcspopm $Rt",
- (SYSLxt_GCS GPR64:$Rt, 3, 7, 7, 1)>, Requires<[HasGCS]>;
+ (SYSLxt GPR64:$Rt, 3, 7, 7, 1)>, Requires<[HasGCS]>;
def : InstAlias<"gcsss2 $Rt",
- (SYSLxt_GCS GPR64:$Rt, 3, 7, 7, 3)>, Requires<[HasGCS]>;
+ (SYSLxt GPR64:$Rt, 3, 7, 7, 3)>, Requires<[HasGCS]>;
let Predicates = [HasGCS] in
def : Pat<(int_aarch64_gcspopm GPR64:$Rt),
(SYSLxt_GCS GPR64:$Rt, 3, 7, 7, 1)>;
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp
index d513d47ebd52f..3006c757901a7 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp
@@ -84,7 +84,7 @@ void AArch64InstPrinter::printInst(const MCInst *MI, uint64_t Address,
return;
}
- if (Opcode == AArch64::SYSLxt || Opcode == AArch64::SYSLxt_GCS)
+ if (Opcode == AArch64::SYSLxt)
if (printSyslAlias(MI, STI, O)) {
printAnnotation(O, Annot);
return;
@@ -926,14 +926,6 @@ bool AArch64InstPrinter::printSysAlias(const MCInst *MI,
default: return false;
// MLBI aliases
case 0: {
- if (Op1Val == 6 && Op2Val == 0) {
- NeedsReg = true;
- Ins = "apas";
- Name = "";
- RegSep = "\t";
- break;
- }
-
const AArch64MLBI::MLBI *MLBI =
AArch64MLBI::lookupMLBIByEncoding(Encoding);
if (!MLBI || !MLBI->haveFeatures(STI.getFeatureBits()))
@@ -979,11 +971,7 @@ bool AArch64InstPrinter::printSysAlias(const MCInst *MI,
STI.hasFeature(AArch64::FeatureITE)))
return false;
- NeedsReg = true;
- Ins = "trcit";
- Name = "";
- RegSep = "\t";
- break;
+ return false;
}
} break;
// Prediction Restriction aliases
@@ -1176,17 +1164,14 @@ bool AArch64InstPrinter::printSyslAlias(const MCInst *MI,
raw_ostream &O) {
unsigned Opcode = MI->getOpcode();
#ifndef NDEBUG
- assert((Opcode == AArch64::SYSLxt || Opcode == AArch64::SYSLxt_GCS) &&
- "Invalid opcode for SYSL alias!");
+ assert(Opcode == AArch64::SYSLxt && "Invalid opcode for SYSL alias!");
#endif
- unsigned OpOffset = Opcode == AArch64::SYSLxt_GCS ? 1 : 0;
-
StringRef Reg = getRegisterName(MI->getOperand(0).getReg());
- const MCOperand &Op1 = MI->getOperand(OpOffset + 1);
- const MCOperand &Cn = MI->getOperand(OpOffset + 2);
- const MCOperand &Cm = MI->getOperand(OpOffset + 3);
- const MCOperand &Op2 = MI->getOperand(OpOffset + 4);
+ const MCOperand &Op1 = MI->getOperand(1);
+ const MCOperand &Cn = MI->getOperand(2);
+ const MCOperand &Cm = MI->getOperand(3);
+ const MCOperand &Op2 = MI->getOperand(4);
unsigned Op1Val = Op1.getImm();
unsigned CnVal = Cn.getImm();
More information about the llvm-commits
mailing list