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

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Fri Jun 12 08:27:51 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-aarch64

Author: Jonathan Thackray (jthackray)

<details>
<summary>Changes</summary>

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.

---
Full diff: https://github.com/llvm/llvm-project/pull/203564.diff


5 Files Affected:

- (modified) llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp (+9-3) 
- (modified) llvm/lib/Target/AArch64/AArch64InstrFormats.td (+19-4) 
- (modified) llvm/lib/Target/AArch64/AArch64InstrInfo.td (+23-49) 
- (modified) llvm/lib/Target/AArch64/AArch64SchedFalkorDetails.td (+1-1) 
- (modified) llvm/test/MC/AArch64/arm64-aliases.s (+27) 


``````````diff
diff --git a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
index 9c454349dc12d..fa9008b166cf3 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
@@ -5151,10 +5151,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 787a11401cb6e..36971be67542b 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 a8afffceaa961..3711a9eb2ea92 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]>;
 
@@ -2538,6 +2489,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,
@@ -2550,6 +2505,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/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/test/MC/AArch64/arm64-aliases.s b/llvm/test/MC/AArch64/arm64-aliases.s
index fd529791eb679..93bb2600ad9b3 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
@@ -538,6 +540,31 @@ foo:
 ; CHECK-ITE: trcit xzr
 ; CHECK-NO-ITE: sys #3, c7, c2, #7
 
+  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

``````````

</details>


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


More information about the llvm-branch-commits mailing list