[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