[clang] [llvm] [AArch64] Fix _sys implemantation and MRS/MSR Sema checks (PR #187290)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Mar 19 09:29:54 PDT 2026
https://github.com/Lukacma updated https://github.com/llvm/llvm-project/pull/187290
>From 9855a9c8ed42ff4d2accc4566544c2d1723ff279 Mon Sep 17 00:00:00 2001
From: Marian Lukac <Marian.Lukac at arm.com>
Date: Wed, 18 Mar 2026 14:26:52 +0000
Subject: [PATCH 1/5] [AArch64] Fix _sys implemantation and MRS/MSR Sema checks
---
clang/lib/CodeGen/TargetBuiltins/ARM.cpp | 33 +++--
clang/lib/Sema/SemaARM.cpp | 9 +-
.../CodeGen/arm64-microsoft-status-reg.cpp | 2 +-
clang/test/CodeGen/arm64-microsoft-sys.c | 28 ++--
clang/test/Sema/builtins-microsoft-arm64.c | 13 ++
llvm/include/llvm/IR/IntrinsicsAArch64.td | 5 +-
.../lib/Target/AArch64/AArch64InstrFormats.td | 15 ++-
llvm/lib/Target/AArch64/AArch64InstrInfo.td | 6 +-
.../CodeGen/AArch64/aarch64-sys-intrinsic.ll | 126 ++++++++++++++++++
9 files changed, 195 insertions(+), 42 deletions(-)
create mode 100644 llvm/test/CodeGen/AArch64/aarch64-sys-intrinsic.ll
diff --git a/clang/lib/CodeGen/TargetBuiltins/ARM.cpp b/clang/lib/CodeGen/TargetBuiltins/ARM.cpp
index cdee440a5c60e..bda096f99d001 100644
--- a/clang/lib/CodeGen/TargetBuiltins/ARM.cpp
+++ b/clang/lib/CodeGen/TargetBuiltins/ARM.cpp
@@ -5639,20 +5639,15 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
}
if (BuiltinID == clang::AArch64::BI_ReadStatusReg ||
- BuiltinID == clang::AArch64::BI_WriteStatusReg ||
- BuiltinID == clang::AArch64::BI__sys) {
+ BuiltinID == clang::AArch64::BI_WriteStatusReg) {
LLVMContext &Context = CGM.getLLVMContext();
unsigned SysReg =
E->getArg(0)->EvaluateKnownConstInt(getContext()).getZExtValue();
std::string SysRegStr;
- unsigned SysRegOp0 = (BuiltinID == clang::AArch64::BI_ReadStatusReg ||
- BuiltinID == clang::AArch64::BI_WriteStatusReg)
- ? ((1 << 1) | ((SysReg >> 14) & 1))
- : 1;
llvm::raw_string_ostream(SysRegStr)
- << SysRegOp0 << ":" << ((SysReg >> 11) & 7) << ":"
+ << (SysReg >> 14) << ":" << ((SysReg >> 11) & 7) << ":"
<< ((SysReg >> 7) & 15) << ":" << ((SysReg >> 3) & 15) << ":"
<< (SysReg & 7);
@@ -5672,14 +5667,28 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
llvm::Function *F = CGM.getIntrinsic(Intrinsic::write_register, Types);
llvm::Value *ArgValue = EmitScalarExpr(E->getArg(1));
llvm::Value *Result = Builder.CreateCall(F, {Metadata, ArgValue});
- if (BuiltinID == clang::AArch64::BI__sys) {
- // Return 0 for convenience, even though MSVC returns some other undefined
- // value.
- Result = ConstantInt::get(Builder.getInt32Ty(), 0);
- }
+
return Result;
}
+ if (BuiltinID == clang::AArch64::BI__sys) {
+ unsigned SysReg =
+ E->getArg(0)->EvaluateKnownConstInt(getContext()).getZExtValue();
+ const unsigned Op1 = SysReg >> 11;
+ const unsigned CRn = (SysReg >> 7) & 0xf;
+ const unsigned CRm = (SysReg >> 3) & 0xf;
+ const unsigned Op2 = SysReg & 0x7;
+
+ Builder.CreateCall(CGM.getIntrinsic(Intrinsic::aarch64_sys),
+ {Builder.getInt32(Op1), Builder.getInt32(CRn),
+ Builder.getInt32(CRm), Builder.getInt32(Op2),
+ EmitScalarExpr(E->getArg(1))});
+
+ // Return 0 for convenience, even though MSVC returns some other undefined
+ // value.
+ return ConstantInt::get(Builder.getInt32Ty(), 0);
+ }
+
if (BuiltinID == clang::AArch64::BI_AddressOfReturnAddress) {
llvm::Function *F =
CGM.getIntrinsic(Intrinsic::addressofreturnaddress, AllocaInt8PtrTy);
diff --git a/clang/lib/Sema/SemaARM.cpp b/clang/lib/Sema/SemaARM.cpp
index 693a936b7b35b..fa4463c03b047 100644
--- a/clang/lib/Sema/SemaARM.cpp
+++ b/clang/lib/Sema/SemaARM.cpp
@@ -1260,11 +1260,14 @@ bool SemaARM::CheckAArch64BuiltinFunctionCall(const TargetInfo &TI,
return BuiltinARMSpecialReg(BuiltinID, TheCall, 0, 5, true);
// Only check the valid encoding range. Any constant in this range would be
- // converted to a register of the form S1_2_C3_C4_5. Let the hardware throw
+ // converted to a register of the form S2_2_C3_C4_5. Let the hardware throw
// an exception for incorrect registers. This matches MSVC behavior.
if (BuiltinID == AArch64::BI_ReadStatusReg ||
- BuiltinID == AArch64::BI_WriteStatusReg || BuiltinID == AArch64::BI__sys)
- return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 0x7fff);
+ BuiltinID == AArch64::BI_WriteStatusReg)
+ return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0x4000, 0xffff);
+
+ if (BuiltinID == AArch64::BI__sys)
+ return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 0x3fff);
if (BuiltinID == AArch64::BI__getReg)
return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 31);
diff --git a/clang/test/CodeGen/arm64-microsoft-status-reg.cpp b/clang/test/CodeGen/arm64-microsoft-status-reg.cpp
index 5a942169394e3..c182fdf062ab8 100644
--- a/clang/test/CodeGen/arm64-microsoft-status-reg.cpp
+++ b/clang/test/CodeGen/arm64-microsoft-status-reg.cpp
@@ -14,7 +14,7 @@
// From winnt.h
#define ARM64_SYSREG(op0, op1, crn, crm, op2) \
- ( ((op0 & 1) << 14) | \
+ ( ((op0 & 3) << 14) | \
((op1 & 7) << 11) | \
((crn & 15) << 7) | \
((crm & 15) << 3) | \
diff --git a/clang/test/CodeGen/arm64-microsoft-sys.c b/clang/test/CodeGen/arm64-microsoft-sys.c
index 5913a02d933ae..0abc9ea665fef 100644
--- a/clang/test/CodeGen/arm64-microsoft-sys.c
+++ b/clang/test/CodeGen/arm64-microsoft-sys.c
@@ -11,7 +11,7 @@
// From winnt.h
// op0=1 encodings, use with __sys
-#define ARM64_SYSINSTR(op0, op1, crn, crm, op2) \
+#define ARM64_SYSINSTR(op1, crn, crm, op2) \
( ((op1 & 7) << 11) | \
((crn & 15) << 7) | \
((crm & 15) << 3) | \
@@ -20,11 +20,11 @@
//
// Sampling of instructions
//
-#define ARM64_DC_CGDSW_EL1 ARM64_SYSINSTR(1,0, 7,10,6) // Clean of Data and Allocation Tags by Set/Way
-#define ARM64_IC_IALLU_EL1 ARM64_SYSINSTR(1,0, 7, 5,0) // Instruction Cache Invalidate All to PoU
-#define ARM64_AT_S1E2W ARM64_SYSINSTR(1,4, 7, 8,1) // Translate Stage1, EL2, write
-#define ARM64_TLBI_VMALLE1 ARM64_SYSINSTR(1,0, 8, 7,0) // Invalidate stage 1 TLB [CP15_TLBIALL]
-#define ARM64_CFP_RCTX ARM64_SYSINSTR(1,3, 7, 3,4) // Control Flow Prediction Restriction by Context
+#define ARM64_DC_CGDSW_EL1 ARM64_SYSINSTR(0, 7,10,6) // Clean of Data and Allocation Tags by Set/Way
+#define ARM64_IC_IALLU_EL1 ARM64_SYSINSTR(0, 7, 5,0) // Instruction Cache Invalidate All to PoU
+#define ARM64_AT_S1E2W ARM64_SYSINSTR(4, 7, 8,1) // Translate Stage1, EL2, write
+#define ARM64_TLBI_VMALLE1 ARM64_SYSINSTR(0, 8, 7,0) // Invalidate stage 1 TLB [CP15_TLBIALL]
+#define ARM64_CFP_RCTX ARM64_SYSINSTR(3, 7, 3,4) // Control Flow Prediction Restriction by Context
// From intrin.h
unsigned int __sys(int, __int64);
@@ -35,31 +35,25 @@ void check__sys(__int64 v) {
__sys(ARM64_DC_CGDSW_EL1, v);
// CHECK-ASM: msr S1_0_C7_C10_6, x8
// CHECK-IR: %[[VAR:.*]] = load i64,
-// CHECK-IR-NEXT: call void @llvm.write_register.i64(metadata ![[MD2:.*]], i64 %[[VAR]])
+// CHECK-IR-NEXT: call void @llvm.aarch64.sys(i32 0, i32 7, i32 10, i32 6, i64 %[[VAR]])
__sys(ARM64_IC_IALLU_EL1, v);
// CHECK-ASM: msr S1_0_C7_C5_0, x8
// CHECK-IR: %[[VAR:.*]] = load i64,
-// CHECK-IR-NEXT: call void @llvm.write_register.i64(metadata ![[MD3:.*]], i64 %[[VAR]])
+// CHECK-IR-NEXT: call void @llvm.aarch64.sys(i32 0, i32 7, i32 5, i32 0, i64 %[[VAR]])
__sys(ARM64_AT_S1E2W, v);
// CHECK-ASM: msr S1_4_C7_C8_1, x8
// CHECK-IR: %[[VAR:.*]] = load i64,
-// CHECK-IR-NEXT: call void @llvm.write_register.i64(metadata ![[MD4:.*]], i64 %[[VAR]])
+// CHECK-IR-NEXT: call void @llvm.aarch64.sys(i32 4, i32 7, i32 8, i32 1, i64 %[[VAR]])
__sys(ARM64_TLBI_VMALLE1, v);
// CHECK-ASM: msr S1_0_C8_C7_0, x8
// CHECK-IR: %[[VAR:.*]] = load i64,
-// CHECK-IR-NEXT: call void @llvm.write_register.i64(metadata ![[MD5:.*]], i64 %[[VAR]])
+// CHECK-IR-NEXT: call void @llvm.aarch64.sys(i32 0, i32 8, i32 7, i32 0, i64 %[[VAR]])
__sys(ARM64_CFP_RCTX, v);
// CHECK-ASM: msr S1_3_C7_C3_4, x8
// CHECK-IR: %[[VAR:.*]] = load i64,
-// CHECK-IR-NEXT: call void @llvm.write_register.i64(metadata ![[MD6:.*]], i64 %[[VAR]])
+// CHECK-IR-NEXT: call void @llvm.aarch64.sys(i32 3, i32 7, i32 3, i32 4, i64 %[[VAR]])
}
-
-// CHECK-IR: ![[MD2]] = !{!"1:0:7:10:6"}
-// CHECK-IR: ![[MD3]] = !{!"1:0:7:5:0"}
-// CHECK-IR: ![[MD4]] = !{!"1:4:7:8:1"}
-// CHECK-IR: ![[MD5]] = !{!"1:0:8:7:0"}
-// CHECK-IR: ![[MD6]] = !{!"1:3:7:3:4"}
diff --git a/clang/test/Sema/builtins-microsoft-arm64.c b/clang/test/Sema/builtins-microsoft-arm64.c
index a915a370cde14..738f8c6e02bd5 100644
--- a/clang/test/Sema/builtins-microsoft-arm64.c
+++ b/clang/test/Sema/builtins-microsoft-arm64.c
@@ -25,11 +25,24 @@ void check_ReadWriteStatusReg(int v) {
_WriteStatusReg(x, v); // expected-error {{argument to '_WriteStatusReg' must be a constant integer}}
}
+void check_ReadWriteStatusReg_range(int v) {
+ _ReadStatusReg(0x3fff); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ _ReadStatusReg(0x10000); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+
+ _WriteStatusReg(0x3fff, v); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ _WriteStatusReg(0x10000, v); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+}
+
void check__sys(int v) {
int x;
__sys(x, v); // expected-error {{argument to '__sys' must be a constant integer}}
}
+void check__sys_range(int v) {
+ __sys(-1, v); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __sys(0x4000, v); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+}
+
unsigned int check__sys_retval() {
return __sys(0, 1); // builtin has superfluous return value for MSVC compatibility
}
diff --git a/llvm/include/llvm/IR/IntrinsicsAArch64.td b/llvm/include/llvm/IR/IntrinsicsAArch64.td
index 75929cbc222ad..6f645548abe1d 100644
--- a/llvm/include/llvm/IR/IntrinsicsAArch64.td
+++ b/llvm/include/llvm/IR/IntrinsicsAArch64.td
@@ -57,7 +57,10 @@ def int_aarch64_frint64x
: DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], [ LLVMMatchType<0> ],
[ IntrNoMem ]>;
-
+def int_aarch64_sys : DefaultAttrsIntrinsic<[], [llvm_i32_ty, llvm_i32_ty,
+ llvm_i32_ty, llvm_i32_ty, llvm_i64_ty],
+ [IntrNoMem, IntrHasSideEffects, ImmArg<ArgIndex<0>>, ImmArg<ArgIndex<1>>, ImmArg<ArgIndex<2>>,
+ ImmArg<ArgIndex<3>>]>;
//===----------------------------------------------------------------------===//
// HINT
diff --git a/llvm/lib/Target/AArch64/AArch64InstrFormats.td b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
index 5fdb9814cc2e8..c9c4c3919b40f 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrFormats.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
@@ -2116,16 +2116,21 @@ def SysCRAsmOperand : AsmOperandClass {
let ParserMethod = "tryParseSysCROperand";
}
-def sys_cr_op : Operand<i32> {
+def sys_cr_op : Operand<i32>, TImmLeaf<i32, [{
+ return ((uint32_t)Imm) < 16;
+}]> {
let PrintMethod = "printSysCROperand";
let ParserMatchClass = SysCRAsmOperand;
let OperandType = "OPERAND_IMMEDIATE";
}
-class SystemXtI<bit L, string asm>
- : RtSystemI<L, (outs),
- (ins imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2, GPR64:$Rt),
- asm, "\t$op1, $Cn, $Cm, $op2, $Rt"> {
+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)]> {
bits<3> op1;
bits<4> Cn;
bits<4> Cm;
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index 2900cf073b5aa..5a91d4361a41f 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -2560,12 +2560,12 @@ def MSR_FPMR : Pseudo<(outs), (ins GPR64:$val),
Sched<[WriteSys]>;
// Generic system instructions
-def SYSxt : SystemXtI<0, "sys">;
+def SYSxt : SystemXtI<"sys">;
def SYSLxt : SystemLXtI<1, "sysl">;
def : InstAlias<"sys $op1, $Cn, $Cm, $op2",
- (SYSxt imm0_7:$op1, sys_cr_op:$Cn,
- sys_cr_op:$Cm, imm0_7:$op2, XZR)>;
+ (SYSxt timm32_0_7:$op1, sys_cr_op:$Cn,
+ sys_cr_op:$Cm, timm32_0_7:$op2, XZR)>;
//===----------------------------------------------------------------------===//
diff --git a/llvm/test/CodeGen/AArch64/aarch64-sys-intrinsic.ll b/llvm/test/CodeGen/AArch64/aarch64-sys-intrinsic.ll
new file mode 100644
index 0000000000000..79ee54a97e53a
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/aarch64-sys-intrinsic.ll
@@ -0,0 +1,126 @@
+; RUN: llc < %s -mtriple=aarch64 -asm-verbose=false | FileCheck %s --check-prefix=CHECK
+; RUN: llc < %s -mtriple=aarch64 -mattr=+predres -asm-verbose=false | FileCheck %s --check-prefix=PREDRES
+; RUN: llc < %s -mtriple=aarch64 -mattr=+specres2 -asm-verbose=false | FileCheck %s --check-prefix=SPECRES2
+; RUN: llc < %s -mtriple=aarch64 -mattr=+gcie -asm-verbose=false | FileCheck %s --check-prefix=GCIE
+; RUN: llc < %s -mtriple=aarch64 -mattr=+poe2 -asm-verbose=false | FileCheck %s --check-prefix=POE2
+; RUN: llc < %s -mtriple=aarch64 -mattr=+mpamv2 -asm-verbose=false | FileCheck %s --check-prefix=MPAMV2
+
+declare void @llvm.aarch64.sys(i32 immarg, i32 immarg, i32 immarg, i32 immarg,
+ i64)
+
+define void @sys_random(i64 %x) {
+; CHECK-LABEL: sys_random:
+; CHECK: sys #0, c7, c10, #6, x0
+; CHECK-NEXT: ret
+entry:
+ call void @llvm.aarch64.sys(i32 0, i32 7, i32 10, i32 6, i64 %x)
+ ret void
+}
+
+define void @sys_ic_iallu() {
+; CHECK-LABEL: sys_ic_iallu:
+; CHECK: ic iallu
+; CHECK-NEXT: ret
+entry:
+ call void @llvm.aarch64.sys(i32 0, i32 7, i32 5, i32 0, i64 0)
+ ret void
+}
+
+define void @sys_dc_cvac(i64 %x) {
+; CHECK-LABEL: sys_dc_cvac:
+; CHECK: dc cvac, x0
+; CHECK-NEXT: ret
+entry:
+ call void @llvm.aarch64.sys(i32 3, i32 7, i32 10, i32 1, i64 %x)
+ ret void
+}
+
+define void @sys_at_s1e2w(i64 %x) {
+; CHECK-LABEL: sys_at_s1e2w:
+; CHECK: at s1e2w, x0
+; CHECK-NEXT: ret
+entry:
+ call void @llvm.aarch64.sys(i32 4, i32 7, i32 8, i32 1, i64 %x)
+ ret void
+}
+
+define void @sys_tlbi_vmalle1() {
+; CHECK-LABEL: sys_tlbi_vmalle1:
+; CHECK: tlbi vmalle1
+; CHECK-NEXT: ret
+entry:
+ call void @llvm.aarch64.sys(i32 0, i32 8, i32 7, i32 0, i64 0)
+ ret void
+}
+
+define void @sys_cfp_rctx(i64 %x) {
+; PREDRES-LABEL: sys_cfp_rctx:
+; PREDRES: cfp rctx, x0
+; PREDRES-NEXT: ret
+entry:
+ call void @llvm.aarch64.sys(i32 3, i32 7, i32 3, i32 4, i64 %x)
+ ret void
+}
+
+define void @sys_dvp_rctx(i64 %x) {
+; PREDRES-LABEL: sys_dvp_rctx:
+; PREDRES: dvp rctx, x0
+; PREDRES-NEXT: ret
+entry:
+ call void @llvm.aarch64.sys(i32 3, i32 7, i32 3, i32 5, i64 %x)
+ ret void
+}
+
+define void @sys_cpp_rctx(i64 %x) {
+; PREDRES-LABEL: sys_cpp_rctx:
+; PREDRES: cpp rctx, x0
+; PREDRES-NEXT: ret
+entry:
+ call void @llvm.aarch64.sys(i32 3, i32 7, i32 3, i32 7, i64 %x)
+ ret void
+}
+
+define void @sys_cosp_rctx(i64 %x) {
+; SPECRES2-LABEL: sys_cosp_rctx:
+; SPECRES2: cosp rctx, x0
+; SPECRES2-NEXT: ret
+entry:
+ call void @llvm.aarch64.sys(i32 3, i32 7, i32 3, i32 6, i64 %x)
+ ret void
+}
+
+define void @sys_gic_cdaff(i64 %x) {
+; GCIE-LABEL: sys_gic_cdaff:
+; GCIE: gic cdaff, x0
+; GCIE-NEXT: ret
+entry:
+ call void @llvm.aarch64.sys(i32 0, i32 12, i32 1, i32 3, i64 %x)
+ ret void
+}
+
+define void @sys_gsb_sys() {
+; GCIE-LABEL: sys_gsb_sys:
+; GCIE: gsb sys
+; GCIE-NEXT: ret
+entry:
+ call void @llvm.aarch64.sys(i32 0, i32 12, i32 0, i32 0, i64 0)
+ ret void
+}
+
+define void @sys_plbi_vmalle1() {
+; POE2-LABEL: sys_plbi_vmalle1:
+; POE2: plbi vmalle1
+; POE2-NEXT: ret
+entry:
+ call void @llvm.aarch64.sys(i32 0, i32 10, i32 7, i32 0, i64 0)
+ ret void
+}
+
+define void @sys_mlbi_vmalle1() {
+; MPAMV2-LABEL: sys_mlbi_vmalle1:
+; MPAMV2: mlbi vmalle1
+; MPAMV2-NEXT: ret
+entry:
+ call void @llvm.aarch64.sys(i32 4, i32 7, i32 0, i32 5, i64 0)
+ ret void
+}
>From 86de7c98362f4f2782540d66b3ac666dabbc07fd Mon Sep 17 00:00:00 2001
From: Marian Lukac <Marian.Lukac at arm.com>
Date: Wed, 18 Mar 2026 15:39:02 +0000
Subject: [PATCH 2/5] update test
---
clang/test/CodeGen/arm64-microsoft-sys.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/clang/test/CodeGen/arm64-microsoft-sys.c b/clang/test/CodeGen/arm64-microsoft-sys.c
index 0abc9ea665fef..31df201fa37d3 100644
--- a/clang/test/CodeGen/arm64-microsoft-sys.c
+++ b/clang/test/CodeGen/arm64-microsoft-sys.c
@@ -33,27 +33,27 @@ void check__sys(__int64 v) {
__int64 ret;
__sys(ARM64_DC_CGDSW_EL1, v);
-// CHECK-ASM: msr S1_0_C7_C10_6, x8
+// CHECK-ASM: sys #0, c7, c10, #6, x8
// CHECK-IR: %[[VAR:.*]] = load i64,
// CHECK-IR-NEXT: call void @llvm.aarch64.sys(i32 0, i32 7, i32 10, i32 6, i64 %[[VAR]])
__sys(ARM64_IC_IALLU_EL1, v);
-// CHECK-ASM: msr S1_0_C7_C5_0, x8
+// CHECK-ASM: sys #0, c7, c5, #0, x8
// CHECK-IR: %[[VAR:.*]] = load i64,
// CHECK-IR-NEXT: call void @llvm.aarch64.sys(i32 0, i32 7, i32 5, i32 0, i64 %[[VAR]])
__sys(ARM64_AT_S1E2W, v);
-// CHECK-ASM: msr S1_4_C7_C8_1, x8
+// CHECK-ASM: at s1e2w, x8
// CHECK-IR: %[[VAR:.*]] = load i64,
// CHECK-IR-NEXT: call void @llvm.aarch64.sys(i32 4, i32 7, i32 8, i32 1, i64 %[[VAR]])
__sys(ARM64_TLBI_VMALLE1, v);
-// CHECK-ASM: msr S1_0_C8_C7_0, x8
+// CHECK-ASM: sys #0, c8, c7, #0, x8
// CHECK-IR: %[[VAR:.*]] = load i64,
// CHECK-IR-NEXT: call void @llvm.aarch64.sys(i32 0, i32 8, i32 7, i32 0, i64 %[[VAR]])
__sys(ARM64_CFP_RCTX, v);
-// CHECK-ASM: msr S1_3_C7_C3_4, x8
+// CHECK-ASM: sys #3, c7, c3, #4, x8
// CHECK-IR: %[[VAR:.*]] = load i64,
// CHECK-IR-NEXT: call void @llvm.aarch64.sys(i32 3, i32 7, i32 3, i32 4, i64 %[[VAR]])
}
>From d144e287849ee18d1888ce1b0ce61ed799bc6a35 Mon Sep 17 00:00:00 2001
From: Marian Lukac <Marian.Lukac at arm.com>
Date: Wed, 18 Mar 2026 17:16:46 +0000
Subject: [PATCH 3/5] address comments
---
clang/lib/CodeGen/TargetBuiltins/ARM.cpp | 2 +-
clang/lib/Sema/SemaARM.cpp | 2 +-
.../CodeGen/arm64-microsoft-status-reg.cpp | 2 +-
clang/test/CodeGen/arm64-microsoft-sys.c | 17 +++++---
clang/test/Sema/builtins-microsoft-arm64.c | 4 +-
llvm/include/llvm/IR/IntrinsicsAArch64.td | 6 +--
.../CodeGen/AArch64/aarch64-sys-intrinsic.s | 39 +++++++++++++++++++
7 files changed, 58 insertions(+), 14 deletions(-)
create mode 100644 llvm/test/CodeGen/AArch64/aarch64-sys-intrinsic.s
diff --git a/clang/lib/CodeGen/TargetBuiltins/ARM.cpp b/clang/lib/CodeGen/TargetBuiltins/ARM.cpp
index bda096f99d001..fa62e302383d1 100644
--- a/clang/lib/CodeGen/TargetBuiltins/ARM.cpp
+++ b/clang/lib/CodeGen/TargetBuiltins/ARM.cpp
@@ -5647,7 +5647,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
std::string SysRegStr;
llvm::raw_string_ostream(SysRegStr)
- << (SysReg >> 14) << ":" << ((SysReg >> 11) & 7) << ":"
+ << (0b10 | SysReg >> 14) << ":" << ((SysReg >> 11) & 7) << ":"
<< ((SysReg >> 7) & 15) << ":" << ((SysReg >> 3) & 15) << ":"
<< (SysReg & 7);
diff --git a/clang/lib/Sema/SemaARM.cpp b/clang/lib/Sema/SemaARM.cpp
index fa4463c03b047..23ca13b495cb0 100644
--- a/clang/lib/Sema/SemaARM.cpp
+++ b/clang/lib/Sema/SemaARM.cpp
@@ -1264,7 +1264,7 @@ bool SemaARM::CheckAArch64BuiltinFunctionCall(const TargetInfo &TI,
// an exception for incorrect registers. This matches MSVC behavior.
if (BuiltinID == AArch64::BI_ReadStatusReg ||
BuiltinID == AArch64::BI_WriteStatusReg)
- return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0x4000, 0xffff);
+ return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0x4000, 0x7fff);
if (BuiltinID == AArch64::BI__sys)
return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 0x3fff);
diff --git a/clang/test/CodeGen/arm64-microsoft-status-reg.cpp b/clang/test/CodeGen/arm64-microsoft-status-reg.cpp
index c182fdf062ab8..5a942169394e3 100644
--- a/clang/test/CodeGen/arm64-microsoft-status-reg.cpp
+++ b/clang/test/CodeGen/arm64-microsoft-status-reg.cpp
@@ -14,7 +14,7 @@
// From winnt.h
#define ARM64_SYSREG(op0, op1, crn, crm, op2) \
- ( ((op0 & 3) << 14) | \
+ ( ((op0 & 1) << 14) | \
((op1 & 7) << 11) | \
((crn & 15) << 7) | \
((crm & 15) << 3) | \
diff --git a/clang/test/CodeGen/arm64-microsoft-sys.c b/clang/test/CodeGen/arm64-microsoft-sys.c
index 31df201fa37d3..8a9b2cc084cc1 100644
--- a/clang/test/CodeGen/arm64-microsoft-sys.c
+++ b/clang/test/CodeGen/arm64-microsoft-sys.c
@@ -11,7 +11,7 @@
// From winnt.h
// op0=1 encodings, use with __sys
-#define ARM64_SYSINSTR(op1, crn, crm, op2) \
+#define ARM64_SYSINSTR(op0, op1, crn, crm, op2) \
( ((op1 & 7) << 11) | \
((crn & 15) << 7) | \
((crm & 15) << 3) | \
@@ -20,11 +20,11 @@
//
// Sampling of instructions
//
-#define ARM64_DC_CGDSW_EL1 ARM64_SYSINSTR(0, 7,10,6) // Clean of Data and Allocation Tags by Set/Way
-#define ARM64_IC_IALLU_EL1 ARM64_SYSINSTR(0, 7, 5,0) // Instruction Cache Invalidate All to PoU
-#define ARM64_AT_S1E2W ARM64_SYSINSTR(4, 7, 8,1) // Translate Stage1, EL2, write
-#define ARM64_TLBI_VMALLE1 ARM64_SYSINSTR(0, 8, 7,0) // Invalidate stage 1 TLB [CP15_TLBIALL]
-#define ARM64_CFP_RCTX ARM64_SYSINSTR(3, 7, 3,4) // Control Flow Prediction Restriction by Context
+#define ARM64_DC_CGDSW_EL1 ARM64_SYSINSTR(1,0, 7,10,6) // Clean of Data and Allocation Tags by Set/Way
+#define ARM64_IC_IALLU_EL1 ARM64_SYSINSTR(1,0, 7, 5,0) // Instruction Cache Invalidate All to PoU
+#define ARM64_AT_S1E2W ARM64_SYSINSTR(1,4, 7, 8,1) // Translate Stage1, EL2, write
+#define ARM64_TLBI_VMALLE1 ARM64_SYSINSTR(1,0, 8, 7,0) // Invalidate stage 1 TLB [CP15_TLBIALL]
+#define ARM64_CFP_RCTX ARM64_SYSINSTR(1,3, 7, 3,4) // Control Flow Prediction Restriction by Context
// From intrin.h
unsigned int __sys(int, __int64);
@@ -50,6 +50,11 @@ void check__sys(__int64 v) {
__sys(ARM64_TLBI_VMALLE1, v);
// CHECK-ASM: sys #0, c8, c7, #0, x8
// CHECK-IR: %[[VAR:.*]] = load i64,
+// CHECK-IR-NEXT: call void @llvm.aarch64.sys(i32 0, i32 8, i32 7, i32 0, i64 %[[VAR]])
+
+ __sys(ARM64_TLBI_VMALLE1, 0);
+// CHECK-ASM: sys #0, c8, c7, #0, x8
+// CHECK-IR: %[[VAR:.*]] = load i64,
// CHECK-IR-NEXT: call void @llvm.aarch64.sys(i32 0, i32 8, i32 7, i32 0, i64 %[[VAR]])
__sys(ARM64_CFP_RCTX, v);
diff --git a/clang/test/Sema/builtins-microsoft-arm64.c b/clang/test/Sema/builtins-microsoft-arm64.c
index 738f8c6e02bd5..22163ab3fa851 100644
--- a/clang/test/Sema/builtins-microsoft-arm64.c
+++ b/clang/test/Sema/builtins-microsoft-arm64.c
@@ -27,10 +27,10 @@ void check_ReadWriteStatusReg(int v) {
void check_ReadWriteStatusReg_range(int v) {
_ReadStatusReg(0x3fff); // expected-error-re {{argument value {{.*}} is outside the valid range}}
- _ReadStatusReg(0x10000); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ _ReadStatusReg(0x8000); // expected-error-re {{argument value {{.*}} is outside the valid range}}
_WriteStatusReg(0x3fff, v); // expected-error-re {{argument value {{.*}} is outside the valid range}}
- _WriteStatusReg(0x10000, v); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ _WriteStatusReg(0x8000, v); // expected-error-re {{argument value {{.*}} is outside the valid range}}
}
void check__sys(int v) {
diff --git a/llvm/include/llvm/IR/IntrinsicsAArch64.td b/llvm/include/llvm/IR/IntrinsicsAArch64.td
index 6f645548abe1d..63500beaa6521 100644
--- a/llvm/include/llvm/IR/IntrinsicsAArch64.td
+++ b/llvm/include/llvm/IR/IntrinsicsAArch64.td
@@ -58,9 +58,9 @@ def int_aarch64_frint64x
[ IntrNoMem ]>;
def int_aarch64_sys : DefaultAttrsIntrinsic<[], [llvm_i32_ty, llvm_i32_ty,
- llvm_i32_ty, llvm_i32_ty, llvm_i64_ty],
- [IntrNoMem, IntrHasSideEffects, ImmArg<ArgIndex<0>>, ImmArg<ArgIndex<1>>, ImmArg<ArgIndex<2>>,
- ImmArg<ArgIndex<3>>]>;
+ llvm_i32_ty, llvm_i32_ty, llvm_i64_ty],
+ [ImmArg<ArgIndex<0>>, ImmArg<ArgIndex<1>>, ImmArg<ArgIndex<2>>,
+ ImmArg<ArgIndex<3>>]>;
//===----------------------------------------------------------------------===//
// HINT
diff --git a/llvm/test/CodeGen/AArch64/aarch64-sys-intrinsic.s b/llvm/test/CodeGen/AArch64/aarch64-sys-intrinsic.s
new file mode 100644
index 0000000000000..7d2ccb9f459ca
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/aarch64-sys-intrinsic.s
@@ -0,0 +1,39 @@
+ .file "aarch64-sys-intrinsic.ll"
+ .text
+ .globl sys_cgdsw // -- Begin function sys_cgdsw
+ .p2align 2
+ .type sys_cgdsw, at function
+sys_cgdsw: // @sys_cgdsw
+ .cfi_startproc
+// %bb.0: // %entry
+ sys #0, c7, c10, #6, x0
+ ret
+.Lfunc_end0:
+ .size sys_cgdsw, .Lfunc_end0-sys_cgdsw
+ .cfi_endproc
+ // -- End function
+ .globl sys_s1e2w // -- Begin function sys_s1e2w
+ .p2align 2
+ .type sys_s1e2w, at function
+sys_s1e2w: // @sys_s1e2w
+ .cfi_startproc
+// %bb.0: // %entry
+ at s1e2w, x0
+ ret
+.Lfunc_end1:
+ .size sys_s1e2w, .Lfunc_end1-sys_s1e2w
+ .cfi_endproc
+ // -- End function
+ .globl sys_vmalle1 // -- Begin function sys_vmalle1
+ .p2align 2
+ .type sys_vmalle1, at function
+sys_vmalle1: // @sys_vmalle1
+ .cfi_startproc
+// %bb.0: // %entry
+ sys #0, c8, c7, #0, x0
+ ret
+.Lfunc_end2:
+ .size sys_vmalle1, .Lfunc_end2-sys_vmalle1
+ .cfi_endproc
+ // -- End function
+ .section ".note.GNU-stack","", at progbits
>From 8270373838e0b05342c11f11dacbe7aa57654a86 Mon Sep 17 00:00:00 2001
From: Marian Lukac <Marian.Lukac at arm.com>
Date: Wed, 18 Mar 2026 17:45:34 +0000
Subject: [PATCH 4/5] remove pointless test
---
clang/test/CodeGen/arm64-microsoft-sys.c | 5 -----
1 file changed, 5 deletions(-)
diff --git a/clang/test/CodeGen/arm64-microsoft-sys.c b/clang/test/CodeGen/arm64-microsoft-sys.c
index 8a9b2cc084cc1..0268584c5fd13 100644
--- a/clang/test/CodeGen/arm64-microsoft-sys.c
+++ b/clang/test/CodeGen/arm64-microsoft-sys.c
@@ -50,11 +50,6 @@ void check__sys(__int64 v) {
__sys(ARM64_TLBI_VMALLE1, v);
// CHECK-ASM: sys #0, c8, c7, #0, x8
// CHECK-IR: %[[VAR:.*]] = load i64,
-// CHECK-IR-NEXT: call void @llvm.aarch64.sys(i32 0, i32 8, i32 7, i32 0, i64 %[[VAR]])
-
- __sys(ARM64_TLBI_VMALLE1, 0);
-// CHECK-ASM: sys #0, c8, c7, #0, x8
-// CHECK-IR: %[[VAR:.*]] = load i64,
// CHECK-IR-NEXT: call void @llvm.aarch64.sys(i32 0, i32 8, i32 7, i32 0, i64 %[[VAR]])
__sys(ARM64_CFP_RCTX, v);
>From e87fa1ecbf4772d8139ec00b5dc9459df551724b Mon Sep 17 00:00:00 2001
From: Marian Lukac <Marian.Lukac at arm.com>
Date: Thu, 19 Mar 2026 16:29:01 +0000
Subject: [PATCH 5/5] remove s file
---
.../CodeGen/AArch64/aarch64-sys-intrinsic.s | 39 -------------------
1 file changed, 39 deletions(-)
delete mode 100644 llvm/test/CodeGen/AArch64/aarch64-sys-intrinsic.s
diff --git a/llvm/test/CodeGen/AArch64/aarch64-sys-intrinsic.s b/llvm/test/CodeGen/AArch64/aarch64-sys-intrinsic.s
deleted file mode 100644
index 7d2ccb9f459ca..0000000000000
--- a/llvm/test/CodeGen/AArch64/aarch64-sys-intrinsic.s
+++ /dev/null
@@ -1,39 +0,0 @@
- .file "aarch64-sys-intrinsic.ll"
- .text
- .globl sys_cgdsw // -- Begin function sys_cgdsw
- .p2align 2
- .type sys_cgdsw, at function
-sys_cgdsw: // @sys_cgdsw
- .cfi_startproc
-// %bb.0: // %entry
- sys #0, c7, c10, #6, x0
- ret
-.Lfunc_end0:
- .size sys_cgdsw, .Lfunc_end0-sys_cgdsw
- .cfi_endproc
- // -- End function
- .globl sys_s1e2w // -- Begin function sys_s1e2w
- .p2align 2
- .type sys_s1e2w, at function
-sys_s1e2w: // @sys_s1e2w
- .cfi_startproc
-// %bb.0: // %entry
- at s1e2w, x0
- ret
-.Lfunc_end1:
- .size sys_s1e2w, .Lfunc_end1-sys_s1e2w
- .cfi_endproc
- // -- End function
- .globl sys_vmalle1 // -- Begin function sys_vmalle1
- .p2align 2
- .type sys_vmalle1, at function
-sys_vmalle1: // @sys_vmalle1
- .cfi_startproc
-// %bb.0: // %entry
- sys #0, c8, c7, #0, x0
- ret
-.Lfunc_end2:
- .size sys_vmalle1, .Lfunc_end2-sys_vmalle1
- .cfi_endproc
- // -- End function
- .section ".note.GNU-stack","", at progbits
More information about the cfe-commits
mailing list