https://github.com/zatrazz updated https://github.com/llvm/llvm-project/pull/202582
>From 0dfbf231f0fea7f59e3dd2ae614d84d3d7005cc0 Mon Sep 17 00:00:00 2001 From: Adhemerval Zanella <[email protected]> Date: Thu, 4 Jun 2026 15:24:16 -0300 Subject: [PATCH 1/4] [AArch64] Add llvm.aarch64.hvc intrinsic Add a new LLVM intrinsic llvm.aarch64.hvc alongside the existing llvm.aarch64.break and llvm.aarch64.hlt, wired to the existing HVC (Hypervisor Call) instruction in the AArch64 backend. It takes a 16-bit immediate operand. Unlike hlt/break, hvc does not have IntrNoReturn since the hypervisor can return control to the caller. --- llvm/include/llvm/IR/IntrinsicsAArch64.td | 3 +++ llvm/lib/Target/AArch64/AArch64InstrInfo.td | 4 +++- llvm/test/CodeGen/AArch64/arm64-hvc.ll | 10 ++++++++++ .../llvm-mca/AArch64/Neoverse/V1-misc-instructions.s | 2 +- 4 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 llvm/test/CodeGen/AArch64/arm64-hvc.ll diff --git a/llvm/include/llvm/IR/IntrinsicsAArch64.td b/llvm/include/llvm/IR/IntrinsicsAArch64.td index 6078e1438ceee..5f3850bf5022a 100644 --- a/llvm/include/llvm/IR/IntrinsicsAArch64.td +++ b/llvm/include/llvm/IR/IntrinsicsAArch64.td @@ -72,6 +72,9 @@ def int_aarch64_break : Intrinsic<[], [llvm_i32_ty], def int_aarch64_hlt : Intrinsic<[], [llvm_i32_ty], [IntrNoMem, IntrHasSideEffects, IntrNoReturn, IntrCold, ImmArg<ArgIndex<0>>]>; +def int_aarch64_hvc : Intrinsic<[], [llvm_i32_ty], + [IntrHasSideEffects, ImmArg<ArgIndex<0>>]>; + def int_aarch64_prefetch : Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [IntrInaccessibleMemOrArgMemOnly, IntrWillReturn, ReadOnly<ArgIndex<0>>, diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td index a7e97f23fa62b..d7d266effeaed 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td @@ -3768,7 +3768,9 @@ def DCPS2 : ExceptionGeneration<0b101, 0b10, "dcps2">; def DCPS3 : ExceptionGeneration<0b101, 0b11, "dcps3">, Requires<[HasEL3]>; def HLT : ExceptionGeneration<0b010, 0b00, "hlt", [(int_aarch64_hlt timm32_0_65535:$imm)]>; -def HVC : ExceptionGeneration<0b000, 0b10, "hvc">; +let mayLoad = 1, mayStore = 1 in +def HVC : ExceptionGeneration<0b000, 0b10, "hvc", + [(int_aarch64_hvc timm32_0_65535:$imm)]>; def SMC : ExceptionGeneration<0b000, 0b11, "smc">, Requires<[HasEL3]>; def SVC : ExceptionGeneration<0b000, 0b01, "svc">; diff --git a/llvm/test/CodeGen/AArch64/arm64-hvc.ll b/llvm/test/CodeGen/AArch64/arm64-hvc.ll new file mode 100644 index 0000000000000..14d7e22b4263f --- /dev/null +++ b/llvm/test/CodeGen/AArch64/arm64-hvc.ll @@ -0,0 +1,10 @@ +; RUN: llc < %s -mtriple=arm64-eabi | FileCheck %s + +define void @foo() nounwind { +; CHECK-LABEL: foo +; CHECK: hvc #0x2 + tail call void @llvm.aarch64.hvc(i32 2) + ret void +} + +declare void @llvm.aarch64.hvc(i32 immarg) nounwind 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..0edd3a0f0ee2a 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 @@ -39,7 +39,7 @@ sysl x16, #5, c11, c8, #5 # CHECK-NEXT: 1 1 0.13 U dcps3 # CHECK-NEXT: 1 1 0.13 * * U dmb sy # CHECK-NEXT: 1 1 0.13 U hlt #0x7a67 -# CHECK-NEXT: 1 1 0.13 U hvc #0xecb9 +# CHECK-NEXT: 1 1 0.13 * * U hvc #0xecb9 # CHECK-NEXT: 1 1 0.13 * * U isb # CHECK-NEXT: 1 1 0.13 * * U pssbb # CHECK-NEXT: 1 1 0.13 U smc #0x7e57 >From 9cb98699a642911a7af300c44adac076370312b6 Mon Sep 17 00:00:00 2001 From: Adhemerval Zanella <[email protected]> Date: Thu, 4 Jun 2026 15:24:17 -0300 Subject: [PATCH 2/4] [AArch64] Add the __hvc MS intrinsic Add support for the __hvc MS intrinsic on AArch64, which generates an HVC (Hypervisor Call) instruction with a 16-bit immediate operand, lowered via the llvm.aarch64.hvc intrinsic. --- clang/include/clang/Basic/BuiltinsAArch64.td | 1 + clang/lib/CodeGen/TargetBuiltins/ARM.cpp | 6 ++++++ clang/lib/Headers/intrin.h | 1 + clang/lib/Sema/SemaARM.cpp | 3 +++ clang/test/CodeGen/arm64-microsoft-intrinsics.c | 10 ++++++++++ clang/test/Sema/builtins-microsoft-arm64.c | 6 ++++++ 6 files changed, 27 insertions(+) diff --git a/clang/include/clang/Basic/BuiltinsAArch64.td b/clang/include/clang/Basic/BuiltinsAArch64.td index 15257f3db5b41..64380554b0509 100644 --- a/clang/include/clang/Basic/BuiltinsAArch64.td +++ b/clang/include/clang/Basic/BuiltinsAArch64.td @@ -408,4 +408,5 @@ let Attributes = [NoThrow, RequireDeclaration], Languages = "ALL_MS_LANGUAGES", let Attributes = [NoThrow, RequireDeclaration], Languages = "ALL_MS_LANGUAGES", Header = "intrin.h" in { def __hlt : AArch64NoPrefixTargetLibBuiltin<"unsigned int (unsigned int, ...)">; + def __hvc : AArch64NoPrefixTargetLibBuiltin<"unsigned int (unsigned int, ...)">; } diff --git a/clang/lib/CodeGen/TargetBuiltins/ARM.cpp b/clang/lib/CodeGen/TargetBuiltins/ARM.cpp index ba6c571d40f68..45da68f93f6c0 100644 --- a/clang/lib/CodeGen/TargetBuiltins/ARM.cpp +++ b/clang/lib/CodeGen/TargetBuiltins/ARM.cpp @@ -5263,6 +5263,12 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID, return ConstantInt::get(Builder.getInt32Ty(), 0); } + if (BuiltinID == AArch64::BI__hvc) { + Function *F = CGM.getIntrinsic(Intrinsic::aarch64_hvc); + Builder.CreateCall(F, {EmitScalarExpr(E->getArg(0))}); + return ConstantInt::get(Builder.getInt32Ty(), 0); + } + if (BuiltinID == NEON::BI__builtin_neon_vcvth_bf16_f32) return Builder.CreateFPTrunc( Builder.CreateBitCast(EmitScalarExpr(E->getArg(0)), diff --git a/clang/lib/Headers/intrin.h b/clang/lib/Headers/intrin.h index 4cb8cac960bcf..f8a7cbb4f8192 100644 --- a/clang/lib/Headers/intrin.h +++ b/clang/lib/Headers/intrin.h @@ -448,6 +448,7 @@ unsigned int _CountTrailingZeros(unsigned long); unsigned int _CountTrailingZeros64(unsigned __int64); unsigned int __hlt(unsigned int, ...); +unsigned int __hvc(unsigned int, ...); void __cdecl __prefetch(const void *); void __cdecl __prefetch2(const void *, unsigned char); diff --git a/clang/lib/Sema/SemaARM.cpp b/clang/lib/Sema/SemaARM.cpp index 5e7504fab416d..edcaf1ff029c4 100644 --- a/clang/lib/Sema/SemaARM.cpp +++ b/clang/lib/Sema/SemaARM.cpp @@ -1189,6 +1189,9 @@ bool SemaARM::CheckAArch64BuiltinFunctionCall(const TargetInfo &TI, if (BuiltinID == AArch64::BI__hlt) return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 0xffff); + if (BuiltinID == AArch64::BI__hvc) + return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 0xffff); + if (CheckNeonBuiltinFunctionCall(TI, BuiltinID, TheCall)) return true; diff --git a/clang/test/CodeGen/arm64-microsoft-intrinsics.c b/clang/test/CodeGen/arm64-microsoft-intrinsics.c index e6a415a0d8805..8c51290e078b7 100644 --- a/clang/test/CodeGen/arm64-microsoft-intrinsics.c +++ b/clang/test/CodeGen/arm64-microsoft-intrinsics.c @@ -147,6 +147,16 @@ void check__hlt() { // CHECK-MSVC: call void @llvm.aarch64.hlt(i32 0) // CHECK-LINUX: error: call to undeclared function '__hlt' +void check__hvc() { + __hvc(0); + __hvc(1); +} + +// CHECK-MSVC-LABEL: define {{.*}} void @check__hvc() +// CHECK-MSVC: call void @llvm.aarch64.hvc(i32 0) +// CHECK-MSVC: call void @llvm.aarch64.hvc(i32 1) +// CHECK-LINUX: error: call to undeclared function '__hvc' + unsigned __int64 check__getReg(void) { unsigned volatile __int64 reg; reg = __getReg(18); diff --git a/clang/test/Sema/builtins-microsoft-arm64.c b/clang/test/Sema/builtins-microsoft-arm64.c index 22163ab3fa851..f2359fdf452ac 100644 --- a/clang/test/Sema/builtins-microsoft-arm64.c +++ b/clang/test/Sema/builtins-microsoft-arm64.c @@ -14,6 +14,12 @@ void check__hlt() { __hlt(65536); // expected-error-re {{argument value {{.*}} is outside the valid range}} } +void check__hvc(unsigned int x) { + __hvc(-1); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __hvc(65536); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __hvc(x); // expected-error {{argument to '__hvc' must be a constant integer}} +} + void check__getReg(void) { __getReg(-1); // expected-error-re {{argument value {{.*}} is outside the valid range}} __getReg(32); // expected-error-re {{argument value {{.*}} is outside the valid range}} >From f88b227be5a8d1a99f41e4d3a64a21d29f28a959 Mon Sep 17 00:00:00 2001 From: Adhemerval Zanella <[email protected]> Date: Thu, 28 May 2026 13:51:44 -0300 Subject: [PATCH 3/4] [AArch64] Add the llvm.aarch64.svc intrinsic Add the llvm.aarch64.svc intrinsic alongside the existing llvm.aarch64.hvc, wired to the existing SVC instruction definition in the AArch64 backend. It generates the SVC (Supervisor Call) instruction with a 16-bit immediate operand. Like hvc, svc does not have IntrNoReturn since the supervisor can return control to the caller. --- llvm/include/llvm/IR/IntrinsicsAArch64.td | 3 +++ llvm/lib/Target/AArch64/AArch64InstrInfo.td | 4 +++- llvm/test/CodeGen/AArch64/arm64-svc.ll | 10 ++++++++++ .../llvm-mca/AArch64/Neoverse/V1-misc-instructions.s | 2 +- 4 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 llvm/test/CodeGen/AArch64/arm64-svc.ll diff --git a/llvm/include/llvm/IR/IntrinsicsAArch64.td b/llvm/include/llvm/IR/IntrinsicsAArch64.td index 5f3850bf5022a..d2b685ae48635 100644 --- a/llvm/include/llvm/IR/IntrinsicsAArch64.td +++ b/llvm/include/llvm/IR/IntrinsicsAArch64.td @@ -75,6 +75,9 @@ def int_aarch64_hlt : Intrinsic<[], [llvm_i32_ty], def int_aarch64_hvc : Intrinsic<[], [llvm_i32_ty], [IntrHasSideEffects, ImmArg<ArgIndex<0>>]>; +def int_aarch64_svc : Intrinsic<[], [llvm_i32_ty], + [IntrHasSideEffects, ImmArg<ArgIndex<0>>]>; + def int_aarch64_prefetch : Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [IntrInaccessibleMemOrArgMemOnly, IntrWillReturn, ReadOnly<ArgIndex<0>>, diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td index d7d266effeaed..f105718db90b9 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td @@ -3772,7 +3772,9 @@ let mayLoad = 1, mayStore = 1 in def HVC : ExceptionGeneration<0b000, 0b10, "hvc", [(int_aarch64_hvc timm32_0_65535:$imm)]>; def SMC : ExceptionGeneration<0b000, 0b11, "smc">, Requires<[HasEL3]>; -def SVC : ExceptionGeneration<0b000, 0b01, "svc">; +let mayLoad = 1, mayStore = 1 in +def SVC : ExceptionGeneration<0b000, 0b01, "svc", + [(int_aarch64_svc timm32_0_65535:$imm)]>; // DCPSn defaults to an immediate operand of zero if unspecified. def : InstAlias<"dcps1", (DCPS1 0)>; diff --git a/llvm/test/CodeGen/AArch64/arm64-svc.ll b/llvm/test/CodeGen/AArch64/arm64-svc.ll new file mode 100644 index 0000000000000..2bb0719413429 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/arm64-svc.ll @@ -0,0 +1,10 @@ +; RUN: llc < %s -mtriple=arm64-eabi | FileCheck %s + +define void @foo() nounwind { +; CHECK-LABEL: foo +; CHECK: svc #0x2 + tail call void @llvm.aarch64.svc(i32 2) + ret void +} + +declare void @llvm.aarch64.svc(i32 immarg) nounwind 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 0edd3a0f0ee2a..fc2710ae216bd 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 @@ -43,7 +43,7 @@ sysl x16, #5, c11, c8, #5 # CHECK-NEXT: 1 1 0.13 * * U isb # 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 svc #0x89cb # CHECK-NEXT: 1 1 0.13 U sysl x16, #5, c11, c8, #5 # CHECK: Resources: >From 863e61045bca1fd6145ac5a2a4a5992eb75878d0 Mon Sep 17 00:00:00 2001 From: Adhemerval Zanella <[email protected]> Date: Thu, 28 May 2026 13:52:04 -0300 Subject: [PATCH 4/4] [AArch64] Add the __svc MS intrinsic Add support for the __svc MS intrinsic on AArch64, lowering to the llvm.aarch64.svc intrinsic. It generates the SVC (Supervisor Call) instruction with a 16-bit immediate operand and mirrors the existing __hvc intrinsic. --- clang/include/clang/Basic/BuiltinsAArch64.td | 1 + clang/lib/CodeGen/TargetBuiltins/ARM.cpp | 6 ++++++ clang/lib/Headers/intrin.h | 1 + clang/lib/Sema/SemaARM.cpp | 3 +++ clang/test/CodeGen/arm64-microsoft-intrinsics.c | 10 ++++++++++ clang/test/Sema/builtins-microsoft-arm64.c | 6 ++++++ 6 files changed, 27 insertions(+) diff --git a/clang/include/clang/Basic/BuiltinsAArch64.td b/clang/include/clang/Basic/BuiltinsAArch64.td index 64380554b0509..4c49c874133fb 100644 --- a/clang/include/clang/Basic/BuiltinsAArch64.td +++ b/clang/include/clang/Basic/BuiltinsAArch64.td @@ -409,4 +409,5 @@ let Attributes = [NoThrow, RequireDeclaration], Languages = "ALL_MS_LANGUAGES", let Attributes = [NoThrow, RequireDeclaration], Languages = "ALL_MS_LANGUAGES", Header = "intrin.h" in { def __hlt : AArch64NoPrefixTargetLibBuiltin<"unsigned int (unsigned int, ...)">; def __hvc : AArch64NoPrefixTargetLibBuiltin<"unsigned int (unsigned int, ...)">; + def __svc : AArch64NoPrefixTargetLibBuiltin<"unsigned int (unsigned int, ...)">; } diff --git a/clang/lib/CodeGen/TargetBuiltins/ARM.cpp b/clang/lib/CodeGen/TargetBuiltins/ARM.cpp index 45da68f93f6c0..e220fe1c0fcec 100644 --- a/clang/lib/CodeGen/TargetBuiltins/ARM.cpp +++ b/clang/lib/CodeGen/TargetBuiltins/ARM.cpp @@ -5269,6 +5269,12 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID, return ConstantInt::get(Builder.getInt32Ty(), 0); } + if (BuiltinID == AArch64::BI__svc) { + Function *F = CGM.getIntrinsic(Intrinsic::aarch64_svc); + Builder.CreateCall(F, {EmitScalarExpr(E->getArg(0))}); + return ConstantInt::get(Builder.getInt32Ty(), 0); + } + if (BuiltinID == NEON::BI__builtin_neon_vcvth_bf16_f32) return Builder.CreateFPTrunc( Builder.CreateBitCast(EmitScalarExpr(E->getArg(0)), diff --git a/clang/lib/Headers/intrin.h b/clang/lib/Headers/intrin.h index f8a7cbb4f8192..7dcb5a526afb2 100644 --- a/clang/lib/Headers/intrin.h +++ b/clang/lib/Headers/intrin.h @@ -449,6 +449,7 @@ unsigned int _CountTrailingZeros64(unsigned __int64); unsigned int __hlt(unsigned int, ...); unsigned int __hvc(unsigned int, ...); +unsigned int __svc(unsigned int, ...); void __cdecl __prefetch(const void *); void __cdecl __prefetch2(const void *, unsigned char); diff --git a/clang/lib/Sema/SemaARM.cpp b/clang/lib/Sema/SemaARM.cpp index edcaf1ff029c4..664525fdb3232 100644 --- a/clang/lib/Sema/SemaARM.cpp +++ b/clang/lib/Sema/SemaARM.cpp @@ -1192,6 +1192,9 @@ bool SemaARM::CheckAArch64BuiltinFunctionCall(const TargetInfo &TI, if (BuiltinID == AArch64::BI__hvc) return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 0xffff); + if (BuiltinID == AArch64::BI__svc) + return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 0xffff); + if (CheckNeonBuiltinFunctionCall(TI, BuiltinID, TheCall)) return true; diff --git a/clang/test/CodeGen/arm64-microsoft-intrinsics.c b/clang/test/CodeGen/arm64-microsoft-intrinsics.c index 8c51290e078b7..5bb7d1f9f4a7d 100644 --- a/clang/test/CodeGen/arm64-microsoft-intrinsics.c +++ b/clang/test/CodeGen/arm64-microsoft-intrinsics.c @@ -157,6 +157,16 @@ void check__hvc() { // CHECK-MSVC: call void @llvm.aarch64.hvc(i32 1) // CHECK-LINUX: error: call to undeclared function '__hvc' +void check__svc() { + __svc(0); + __svc(1); +} + +// CHECK-MSVC-LABEL: define {{.*}} void @check__svc() +// CHECK-MSVC: call void @llvm.aarch64.svc(i32 0) +// CHECK-MSVC: call void @llvm.aarch64.svc(i32 1) +// CHECK-LINUX: error: call to undeclared function '__svc' + unsigned __int64 check__getReg(void) { unsigned volatile __int64 reg; reg = __getReg(18); diff --git a/clang/test/Sema/builtins-microsoft-arm64.c b/clang/test/Sema/builtins-microsoft-arm64.c index f2359fdf452ac..6e07a75af9a46 100644 --- a/clang/test/Sema/builtins-microsoft-arm64.c +++ b/clang/test/Sema/builtins-microsoft-arm64.c @@ -20,6 +20,12 @@ void check__hvc(unsigned int x) { __hvc(x); // expected-error {{argument to '__hvc' must be a constant integer}} } +void check__svc(unsigned int x) { + __svc(-1); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __svc(65536); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __svc(x); // expected-error {{argument to '__svc' must be a constant integer}} +} + void check__getReg(void) { __getReg(-1); // expected-error-re {{argument value {{.*}} is outside the valid range}} __getReg(32); // expected-error-re {{argument value {{.*}} is outside the valid range}} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
