llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-backend-x86 Author: Adhemerval Zanella (zatrazz) <details> <summary>Changes</summary> This series implements three additional Microsoft `intrin.h` intrinsics in clang so MSVC-compatible code can build with clang. | Target | Intrinsic | Description | |--------|-----------|-------------| | AArch64 | `__svc` | Supervisor Call (`SVC #imm`) | | AArch64 | `__hvc` | Hypervisor Call (`HVC #imm`) | | AArch64 | `_InterlockedCompareExchangePointer_nf` | Pointer compare-and-exchange, no memory barrier (relaxed) | `__hvc` and `__svc` each require a new LLVM intrinsic (`llvm.aarch64.hvc` / `llvm.aarch64.svc`) to carry the immediate operand down to instruction selection. `_InterlockedCompareExchangePointer_nf` is the relaxed (`_nf`, "no fence") form of the existing `_InterlockedCompareExchangePointer` family and is wired up for both the ARM and AArch64 targets. These follow the MSVC semantics, where the intrinsics behave like inline assembly: the compiler emits the requested instruction directly and does not verify that the target's enabled ISA actually supports it. The `__hvc` / `__svc` immediate is range-checked as a compile-time constant (matching `cl`), but there is no feature/`-march` gating — emitting the instruction is the user's responsibility. --- Full diff: https://github.com/llvm/llvm-project/pull/202582.diff 11 Files Affected: - (modified) clang/include/clang/Basic/BuiltinsAArch64.td (+3) - (modified) clang/lib/CodeGen/TargetBuiltins/ARM.cpp (+13) - (modified) clang/lib/Headers/intrin.h (+2) - (modified) clang/lib/Sema/SemaARM.cpp (+6) - (modified) clang/test/CodeGen/arm64-microsoft-intrinsics.c (+20) - (modified) clang/test/CodeGen/ms-intrinsics.c (+8) - (modified) clang/test/Sema/builtins-microsoft-arm64.c (+12) - (modified) llvm/include/llvm/IR/IntrinsicsAArch64.td (+6) - (modified) llvm/lib/Target/AArch64/AArch64InstrInfo.td (+4-2) - (added) llvm/test/CodeGen/AArch64/arm64-hvc.ll (+10) - (added) llvm/test/CodeGen/AArch64/arm64-svc.ll (+10) ``````````diff diff --git a/clang/include/clang/Basic/BuiltinsAArch64.td b/clang/include/clang/Basic/BuiltinsAArch64.td index 15257f3db5b41..0d2e936d7b7b3 100644 --- a/clang/include/clang/Basic/BuiltinsAArch64.td +++ b/clang/include/clang/Basic/BuiltinsAArch64.td @@ -253,6 +253,7 @@ let Attributes = [NoThrow, RequireDeclaration], Languages = "ALL_MS_LANGUAGES", def _InterlockedCompareExchange64_nf : AArch64NoPrefixTargetLibBuiltin<"long long int (long long int volatile *, long long int, long long int)">; def _InterlockedCompareExchange64_rel : AArch64NoPrefixTargetLibBuiltin<"long long int (long long int volatile *, long long int, long long int)">; def _InterlockedCompareExchangePointer_acq : AArch64NoPrefixTargetLibBuiltin<"void * (void * volatile *, void *, void *)">; + def _InterlockedCompareExchangePointer_nf : AArch64NoPrefixTargetLibBuiltin<"void * (void * volatile *, void *, void *)">; def _InterlockedCompareExchangePointer_rel : AArch64NoPrefixTargetLibBuiltin<"void * (void * volatile *, void *, void *)">; } @@ -408,4 +409,6 @@ 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 ece8ff21561cf..00b90eee21565 100644 --- a/clang/lib/CodeGen/TargetBuiltins/ARM.cpp +++ b/clang/lib/CodeGen/TargetBuiltins/ARM.cpp @@ -106,6 +106,7 @@ translateAarch64ToMsvcIntrin(unsigned BuiltinID) { case clang::AArch64::BI_InterlockedCompareExchange16_nf: case clang::AArch64::BI_InterlockedCompareExchange_nf: case clang::AArch64::BI_InterlockedCompareExchange64_nf: + case clang::AArch64::BI_InterlockedCompareExchangePointer_nf: return MSVCIntrin::_InterlockedCompareExchange_nf; case clang::AArch64::BI_InterlockedCompareExchange128: return MSVCIntrin::_InterlockedCompareExchange128; @@ -5327,6 +5328,18 @@ 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 == 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 4cb8cac960bcf..7dcb5a526afb2 100644 --- a/clang/lib/Headers/intrin.h +++ b/clang/lib/Headers/intrin.h @@ -448,6 +448,8 @@ unsigned int _CountTrailingZeros(unsigned long); 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 5e7504fab416d..664525fdb3232 100644 --- a/clang/lib/Sema/SemaARM.cpp +++ b/clang/lib/Sema/SemaARM.cpp @@ -1189,6 +1189,12 @@ 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 (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 e6a415a0d8805..5bb7d1f9f4a7d 100644 --- a/clang/test/CodeGen/arm64-microsoft-intrinsics.c +++ b/clang/test/CodeGen/arm64-microsoft-intrinsics.c @@ -147,6 +147,26 @@ 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' + +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/CodeGen/ms-intrinsics.c b/clang/test/CodeGen/ms-intrinsics.c index 8b719ef8cc1fd..8e1c721ac4bc0 100644 --- a/clang/test/CodeGen/ms-intrinsics.c +++ b/clang/test/CodeGen/ms-intrinsics.c @@ -283,6 +283,14 @@ void *test_InterlockedCompareExchangePointer_nf(void * volatile *Destination, // CHECK: %[[RESULT:[0-9]+]] = inttoptr [[iPTR]] %[[EXTRACT]] to ptr // CHECK: ret ptr %[[RESULT:[0-9]+]] // CHECK: } +// CHECK-ARM64: define{{.*}}ptr @test_InterlockedCompareExchangePointer_nf(ptr {{.*}}%Destination, ptr {{[a-z_ ]*}}%Exchange, ptr {{[a-z_ ]*}}%Comparand){{.*}}{ +// CHECK-ARM64: %[[EXCHANGE:[0-9]+]] = ptrtoint ptr %Exchange to [[iPTR]] +// CHECK-ARM64: %[[COMPARAND:[0-9]+]] = ptrtoint ptr %Comparand to [[iPTR]] +// CHECK-ARM64: %[[XCHG:[0-9]+]] = cmpxchg volatile ptr %[[DEST:.+]], [[iPTR]] %[[COMPARAND:[0-9]+]], [[iPTR]] %[[EXCHANGE:[0-9]+]] monotonic monotonic, align {{4|8}} +// CHECK-ARM64: %[[EXTRACT:[0-9]+]] = extractvalue { [[iPTR]], i1 } %[[XCHG]], 0 +// CHECK-ARM64: %[[RESULT:[0-9]+]] = inttoptr [[iPTR]] %[[EXTRACT]] to ptr +// CHECK-ARM64: ret ptr %[[RESULT:[0-9]+]] +// CHECK-ARM64: } #if defined(__arm__) || defined(__aarch64__) void *test_InterlockedCompareExchangePointer_acq(void * volatile *Destination, diff --git a/clang/test/Sema/builtins-microsoft-arm64.c b/clang/test/Sema/builtins-microsoft-arm64.c index 22163ab3fa851..6e07a75af9a46 100644 --- a/clang/test/Sema/builtins-microsoft-arm64.c +++ b/clang/test/Sema/builtins-microsoft-arm64.c @@ -14,6 +14,18 @@ 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__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}} diff --git a/llvm/include/llvm/IR/IntrinsicsAArch64.td b/llvm/include/llvm/IR/IntrinsicsAArch64.td index ba0d7c02bf427..ecccf6eddfc64 100644 --- a/llvm/include/llvm/IR/IntrinsicsAArch64.td +++ b/llvm/include/llvm/IR/IntrinsicsAArch64.td @@ -72,6 +72,12 @@ 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], + [IntrNoMem, IntrHasSideEffects, ImmArg<ArgIndex<0>>]>; + +def int_aarch64_svc : Intrinsic<[], [llvm_i32_ty], + [IntrNoMem, 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 200808665c93e..aa33c34ce7ab2 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td @@ -3759,9 +3759,11 @@ 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">; +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">; +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-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/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 `````````` </details> https://github.com/llvm/llvm-project/pull/202582 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
