[llvm] [AArch64] Define GCS operations as SYS and SYSL aliases (PR #203564)

Jonathan Thackray via llvm-commits llvm-commits at lists.llvm.org
Sun Jun 28 19:21:39 PDT 2026


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

>From fe4ee664df025d22cf0f4feeb65f50dce0a7736f Mon Sep 17 00:00:00 2001
From: Jonathan Thackray <jonathan.thackray at arm.com>
Date: Fri, 12 Jun 2026 15:49:41 +0100
Subject: [PATCH 1/4] [AArch64] Define GCS operations as SYS and SYSL aliases

Move the remaining `GCS` instructions from dedicated opcodes to `SYSxt/SYSLxt`
aliases, keeping a tied `SYSL` pseudo for codegen where `GCS` preserves the`
input register when disabled at runtime.

Update `GCS` intrinsic selection, scheduling, disassembly aliases, and MC
coverage for the generic `SYS/SYSL` encodings.
---
 .../Target/AArch64/AArch64ISelDAGToDAG.cpp    | 12 +++-
 .../lib/Target/AArch64/AArch64InstrFormats.td | 23 ++++--
 llvm/lib/Target/AArch64/AArch64InstrInfo.td   | 72 ++++++-------------
 llvm/test/MC/AArch64/arm64-aliases.s          | 27 +++++++
 4 files changed, 78 insertions(+), 56 deletions(-)

diff --git a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
index 95f82f180e58c..7ef59a00cee8d 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
@@ -5190,10 +5190,16 @@ 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 CRm = CurDAG->getTargetConstant(7, DL, MVT::i32);
+      SDValue SS1Op2 = CurDAG->getTargetConstant(2, DL, MVT::i32);
+      SDValue SS1Ops[] = {Op1, CRm, CRm, 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, CRm, CRm, Op1, 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 daf53c99988b0..7a0ad621b69bb 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrFormats.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
@@ -2149,10 +2149,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;
@@ -2164,6 +2162,23 @@ class SystemLXtI<bit L, string asm>
   let Inst{7-5}   = op2;
 }
 
+class SystemLXtI<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), [], "$Rt = $_Rt">,
+    Sched<[WriteSys]> {
+  let mayLoad = 1;
+  let mayStore = 1;
+  let hasSideEffects = 1;
+  let Size = 4;
+}
+
 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 fc7aea5a4d5f5..bc8441067bbe3 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -1621,55 +1621,6 @@ def : TokenAlias<"INJ", "inj">;
 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> {
-  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]>;
 
@@ -2537,6 +2488,10 @@ def MSR_FPMR : Pseudo<(outs), (ins GPR64:$val),
 // Generic system instructions
 def SYSxt  : SystemXtI<"sys">;
 def SYSLxt : SystemLXtI<1, "sysl">;
+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,
@@ -2549,6 +2504,25 @@ def : InstAlias<"brb\tinj",
                 (SYSxt 1, 7, 2, 5, XZR), 2>, Requires<[HasBRBE]>;
 def : InstAlias<"trcit $Rt",
                 (SYSxt 3, 7, 2, 7, GPR64:$Rt), 2>, Requires<[HasITE]>;
+def : InstAlias<"gcspushx",
+                (SYSxt 0, 7, 7, 4, XZR), 2>, Requires<[HasGCS]>;
+def : InstAlias<"gcspopcx",
+                (SYSxt 0, 7, 7, 5, XZR), 2>, Requires<[HasGCS]>;
+def : InstAlias<"gcspopx",
+                (SYSxt 0, 7, 7, 6, XZR), 2>, Requires<[HasGCS]>;
+def : InstAlias<"gcspushm $Rt",
+                (SYSxt 3, 7, 7, 0, GPR64:$Rt), 2>, Requires<[HasGCS]>;
+def : InstAlias<"gcsss1 $Rt",
+                (SYSxt 3, 7, 7, 2, GPR64:$Rt), 2>, Requires<[HasGCS]>;
+def : InstAlias<"gcspopm",
+                (SYSLxt XZR, 3, 7, 7, 1), 3>, Requires<[HasGCS]>;
+def : InstAlias<"gcspopm $Rt",
+                (SYSLxt GPR64:$Rt, 3, 7, 7, 1), 2>, Requires<[HasGCS]>;
+def : InstAlias<"gcsss2 $Rt",
+                (SYSLxt GPR64:$Rt, 3, 7, 7, 3), 2>, 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/test/MC/AArch64/arm64-aliases.s b/llvm/test/MC/AArch64/arm64-aliases.s
index 06d7f3fed87cc..25c5180655dde 100644
--- a/llvm/test/MC/AArch64/arm64-aliases.s
+++ b/llvm/test/MC/AArch64/arm64-aliases.s
@@ -1,6 +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,+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
@@ -548,6 +550,31 @@ foo:
 ; CHECK-BRBE: brb inj
 ; CHECK-NO-BRBE: sys #1, c7, c2, #5
 
+  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 #6, c7, c0, #0, x3
 ; CHECK-RME: apas x3
   sys #6, c7, c0, #0

>From 07d95ba36da7b152cdf983f28ae4a193220644a4 Mon Sep 17 00:00:00 2001
From: Jonathan Thackray <jonathan.thackray at arm.com>
Date: Tue, 16 Jun 2026 13:29:41 +0100
Subject: [PATCH 2/4] fixup! Address CR comments

---
 llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp |  3 +++
 llvm/lib/Target/AArch64/AArch64InstrFormats.td  | 10 ++++------
 2 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
index 7ef59a00cee8d..7e3ac85c671cb 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
@@ -5186,6 +5186,9 @@ void AArch64DAGToDAGISel::Select(SDNode *Node) {
     default:
       break;
     case Intrinsic::aarch64_gcsss: {
+      if (!Subtarget->hasGCS())
+        break;
+
       SDLoc DL(Node);
       SDValue Chain = Node->getOperand(0);
       SDValue Val = Node->getOperand(2);
diff --git a/llvm/lib/Target/AArch64/AArch64InstrFormats.td b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
index 7a0ad621b69bb..c93e6eea6ff08 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrFormats.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
@@ -2149,8 +2149,10 @@ class SystemXtI<string asm>
   let hasSideEffects = 1;
 }
 
-class BaseSystemLXtI<bit L, dag oops, dag iops, string asm>
-  : RtSystemI<L, oops, iops, asm, "\t$Rt, $op1, $Cn, $Cm, $op2"> {
+class SystemLXtI<bit L, string asm>
+  : RtSystemI<L, (outs GPR64:$Rt),
+       (ins imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2),
+       asm, "\t$Rt, $op1, $Cn, $Cm, $op2"> {
   bits<3> op1;
   bits<4> Cn;
   bits<4> Cm;
@@ -2162,10 +2164,6 @@ class BaseSystemLXtI<bit L, dag oops, dag iops, string asm>
   let Inst{7-5}   = op2;
 }
 
-class SystemLXtI<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

>From af06d2eef707bcf81351ea61c06a552604996e80 Mon Sep 17 00:00:00 2001
From: Jonathan Thackray <jonathan.thackray at arm.com>
Date: Mon, 29 Jun 2026 03:07:53 +0100
Subject: [PATCH 3/4] fixup! Add mayLoad/mayStore

---
 llvm/lib/Target/AArch64/AArch64InstrFormats.td | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/llvm/lib/Target/AArch64/AArch64InstrFormats.td b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
index c93e6eea6ff08..58bc63c588a0d 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrFormats.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
@@ -2162,6 +2162,9 @@ class SystemLXtI<bit L, string asm>
   let Inst{15-12} = Cn;
   let Inst{11-8}  = Cm;
   let Inst{7-5}   = op2;
+  let mayLoad = 1;
+  let mayStore = 1;
+  let hasSideEffects = 1;
 }
 
 // Codegen-only GCS SYSL operations preserve the incoming Rt value when GCS is

>From 8a36dcf09598cfb3d7e3e071265663d9bcf9b548 Mon Sep 17 00:00:00 2001
From: Jonathan Thackray <jonathan.thackray at arm.com>
Date: Mon, 29 Jun 2026 03:17:19 +0100
Subject: [PATCH 4/4] fixup! Model GCS sysl insns properly

---
 .../lib/Target/AArch64/AArch64InstrFormats.td | 54 ++++++++-----------
 llvm/lib/Target/AArch64/AArch64InstrInfo.td   |  5 +-
 .../MCTargetDesc/AArch64InstPrinter.cpp       | 17 ++++++
 .../AArch64/Neoverse/V1-misc-instructions.s   |  2 +-
 4 files changed, 41 insertions(+), 37 deletions(-)

diff --git a/llvm/lib/Target/AArch64/AArch64InstrFormats.td b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
index 58bc63c588a0d..066f94203422f 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrFormats.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
@@ -2127,13 +2127,9 @@ def sys_cr_op : Operand<i32>, TImmLeaf<i32, [{
   let OperandType = "OPERAND_IMMEDIATE";
 }
 
-class SystemXtI<string asm>
-  : RtSystemI<0, (outs),
-       (ins imm32_0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm32_0_7:$op2,
-            GPR64:$Rt),
-       asm, "\t$op1, $Cn, $Cm, $op2, $Rt",
-       [(int_aarch64_sys timm32_0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm,
-                          timm32_0_7:$op2, GPR64:$Rt)]> {
+class BaseSystemXtI<bit L, dag oops, dag iops, string asm, string operands,
+                    list<dag> pattern = []>
+  : RtSystemI<L, oops, iops, asm, operands, pattern> {
   bits<3> op1;
   bits<4> Cn;
   bits<4> Cm;
@@ -2149,35 +2145,29 @@ class SystemXtI<string asm>
   let hasSideEffects = 1;
 }
 
+class SystemXtI<string asm>
+  : BaseSystemXtI<0, (outs),
+       (ins imm32_0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm32_0_7:$op2,
+            GPR64:$Rt),
+       asm, "\t$op1, $Cn, $Cm, $op2, $Rt",
+       [(int_aarch64_sys timm32_0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm,
+                          timm32_0_7:$op2, GPR64:$Rt)]>;
+
 class SystemLXtI<bit L, string asm>
-  : RtSystemI<L, (outs GPR64:$Rt),
+  : BaseSystemXtI<L, (outs GPR64:$Rt),
        (ins imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2),
-       asm, "\t$Rt, $op1, $Cn, $Cm, $op2"> {
-  bits<3> op1;
-  bits<4> Cn;
-  bits<4> Cm;
-  bits<3> op2;
-  let Inst{20-19} = 0b01;
-  let Inst{18-16} = op1;
-  let Inst{15-12} = Cn;
-  let Inst{11-8}  = Cm;
-  let Inst{7-5}   = op2;
-  let mayLoad = 1;
-  let mayStore = 1;
-  let hasSideEffects = 1;
-}
+       asm, "\t$Rt, $op1, $Cn, $Cm, $op2">;
 
-// 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),
+// GCS SYSL operations with register operands preserve the incoming Rt value
+// when GCS is disabled at runtime, so model them with a tied def/use through
+// the backend.
+class GCSTiedSystemLXtI<bit L, string asm>
+  : BaseSystemXtI<L, (outs GPR64:$Rt),
        (ins GPR64:$_Rt, imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm,
-            imm0_7:$op2), [], "$Rt = $_Rt">,
-    Sched<[WriteSys]> {
-  let mayLoad = 1;
-  let mayStore = 1;
-  let hasSideEffects = 1;
-  let Size = 4;
+            imm0_7:$op2),
+       asm, "\t$Rt, $op1, $Cn, $Cm, $op2"> {
+  let Constraints = "$Rt = $_Rt";
+  let DecoderNamespace = "GCS";
 }
 
 def RangePrefetchOperand : AsmOperandClass {
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index bc8441067bbe3..ff51fd61db276 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -2488,10 +2488,7 @@ def MSR_FPMR : Pseudo<(outs), (ins GPR64:$val),
 // Generic system instructions
 def SYSxt  : SystemXtI<"sys">;
 def SYSLxt : SystemLXtI<1, "sysl">;
-def SYSLxt_GCS : GCSTiedSystemLXtPseudo,
-                 PseudoInstExpansion<(SYSLxt GPR64:$Rt, imm0_7:$op1,
-                                            sys_cr_op:$Cn, sys_cr_op:$Cm,
-                                            imm0_7:$op2)>;
+def SYSLxt_GCS : GCSTiedSystemLXtI<1, "sysl">;
 
 def : InstAlias<"sys $op1, $Cn, $Cm, $op2",
                 (SYSxt timm32_0_7:$op1, sys_cr_op:$Cn,
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp
index 2783b559c8f5c..f86e77ea085b7 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp
@@ -90,6 +90,23 @@ void AArch64InstPrinter::printInst(const MCInst *MI, uint64_t Address,
       return;
     }
 
+  if (Opcode == AArch64::SYSLxt_GCS) {
+    unsigned Op2 = MI->getOperand(5).getImm();
+    StringRef Reg = getRegisterName(MI->getOperand(0).getReg());
+    if (Op2 == 1) {
+      O << "\tgcspopm";
+      if (Reg != "xzr")
+        O << "\t" << Reg;
+      printAnnotation(O, Annot);
+      return;
+    }
+    if (Op2 == 3) {
+      O << "\tgcsss2\t" << Reg;
+      printAnnotation(O, Annot);
+      return;
+    }
+  }
+
   if (Opcode == AArch64::SYSPxt || Opcode == AArch64::SYSPxt_XZR)
     if (printSyspAlias(MI, STI, O)) {
       printAnnotation(O, Annot);
diff --git a/llvm/test/tools/llvm-mca/AArch64/Neoverse/V1-misc-instructions.s b/llvm/test/tools/llvm-mca/AArch64/Neoverse/V1-misc-instructions.s
index 37975ab269d10..4818b72d83d8d 100644
--- a/llvm/test/tools/llvm-mca/AArch64/Neoverse/V1-misc-instructions.s
+++ b/llvm/test/tools/llvm-mca/AArch64/Neoverse/V1-misc-instructions.s
@@ -44,7 +44,7 @@ sysl x16, #5, c11, c8, #5
 # CHECK-NEXT:  1      1     0.13    *      *      U     pssbb
 # CHECK-NEXT:  1      1     0.13                  U     smc	#0x7e57
 # CHECK-NEXT:  1      1     0.13                  U     svc	#0x89cb
-# CHECK-NEXT:  1      1     0.13                  U     sysl	x16, #5, c11, c8, #5
+# CHECK-NEXT:  1      1     0.13    *      *      U     sysl	x16, #5, c11, c8, #5
 
 # CHECK:      Resources:
 # CHECK-NEXT: [0.0] - V1UnitB



More information about the llvm-commits mailing list