Skip to content

Add __hlt intrinsic for Windows ARM. #96578

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jul 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions clang/include/clang/Basic/BuiltinsAArch64.def
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,8 @@ TARGET_HEADER_BUILTIN(_CountOneBits64, "UiULLi", "nh", INTRIN_H, ALL_MS_LANGUAGE

TARGET_HEADER_BUILTIN(__prefetch, "vvC*", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")

TARGET_HEADER_BUILTIN(__hlt, "UiUi.", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")

#undef BUILTIN
#undef LANGBUILTIN
#undef TARGET_BUILTIN
Expand Down
9 changes: 9 additions & 0 deletions clang/lib/CodeGen/CGBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11475,6 +11475,15 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
return Builder.CreateCall(F, {Address, RW, Locality, Data});
}

if (BuiltinID == AArch64::BI__hlt) {
Function *F = CGM.getIntrinsic(Intrinsic::aarch64_hlt);
Builder.CreateCall(F, {EmitScalarExpr(E->getArg(0))});

// Return 0 for convenience, even though MSVC returns some other undefined
// value.
return ConstantInt::get(Builder.getInt32Ty(), 0);
}

// Handle MSVC intrinsics before argument evaluation to prevent double
// evaluation.
if (std::optional<MSVCIntrin> MsvcIntId =
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Headers/intrin.h
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,10 @@ unsigned int _CountLeadingSigns64(__int64);
unsigned int _CountOneBits(unsigned long);
unsigned int _CountOneBits64(unsigned __int64);

unsigned int __hlt(unsigned int, ...);

void __cdecl __prefetch(const void *);

#endif

/*----------------------------------------------------------------------------*\
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Sema/SemaARM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1112,6 +1112,9 @@ bool SemaARM::CheckAArch64BuiltinFunctionCall(const TargetInfo &TI,
if (BuiltinID == AArch64::BI__break)
return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 0xffff);

if (BuiltinID == AArch64::BI__hlt)
return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 0xffff);

if (CheckNeonBuiltinFunctionCall(TI, BuiltinID, TheCall))
return true;

Expand Down
9 changes: 9 additions & 0 deletions clang/test/CodeGen/arm64-microsoft-intrinsics.c
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,15 @@ void check__break() {
// CHECK-MSVC: call void @llvm.aarch64.break(i32 0)
// CHECK-LINUX: error: call to undeclared function '__break'

void check__hlt() {
__hlt(0);
__hlt(1, 2, 3, 4, 5);
int x = __hlt(0);
}

// CHECK-MSVC: call void @llvm.aarch64.hlt(i32 0)
// CHECK-LINUX: error: call to undeclared function '__hlt'

unsigned __int64 check__getReg(void) {
unsigned volatile __int64 reg;
reg = __getReg(18);
Expand Down
5 changes: 5 additions & 0 deletions clang/test/Sema/builtins-microsoft-arm64.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ void check__break(int x) {
__break(x); // expected-error {{argument to '__break' must be a constant integer}}
}

void check__hlt() {
__hlt(-1); // expected-error-re {{argument value {{.*}} is outside the valid range}}
__hlt(65536); // expected-error-re {{argument value {{.*}} is outside the valid range}}
}

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}}
Expand Down
3 changes: 3 additions & 0 deletions llvm/include/llvm/IR/IntrinsicsAArch64.td
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ def int_aarch64_frint64x
: DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], [ LLVMMatchType<0> ],
[ IntrNoMem ]>;


//===----------------------------------------------------------------------===//
// HINT

Expand All @@ -65,6 +66,8 @@ def int_aarch64_hint : DefaultAttrsIntrinsic<[], [llvm_i32_ty]>;
def int_aarch64_break : Intrinsic<[], [llvm_i32_ty],
[IntrNoMem, IntrHasSideEffects, IntrNoReturn, IntrCold, ImmArg<ArgIndex<0>>]>;

def int_aarch64_hlt : Intrinsic<[], [llvm_i32_ty],
[IntrNoMem, IntrHasSideEffects, IntrNoReturn, IntrCold, ImmArg<ArgIndex<0>>]>;

def int_aarch64_prefetch : Intrinsic<[],
[llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty],
Expand Down
3 changes: 2 additions & 1 deletion llvm/lib/Target/AArch64/AArch64InstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -3076,7 +3076,8 @@ def BRK : ExceptionGeneration<0b001, 0b00, "brk",
def DCPS1 : ExceptionGeneration<0b101, 0b01, "dcps1">;
def DCPS2 : ExceptionGeneration<0b101, 0b10, "dcps2">;
def DCPS3 : ExceptionGeneration<0b101, 0b11, "dcps3">, Requires<[HasEL3]>;
def HLT : ExceptionGeneration<0b010, 0b00, "hlt">;
def HLT : ExceptionGeneration<0b010, 0b00, "hlt",
[(int_aarch64_hlt timm32_0_65535:$imm)]>;
def HVC : ExceptionGeneration<0b000, 0b10, "hvc">;
def SMC : ExceptionGeneration<0b000, 0b11, "smc">, Requires<[HasEL3]>;
def SVC : ExceptionGeneration<0b000, 0b01, "svc">;
Expand Down
10 changes: 10 additions & 0 deletions llvm/test/CodeGen/AArch64/arm64-hlt.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
; RUN: llc < %s -mtriple=arm64-eabi | FileCheck %s

define void @foo() nounwind {
; CHECK-LABEL: foo
; CHECK: hlt #0x2
tail call void @llvm.aarch64.hlt(i32 2)
ret void
}

declare void @llvm.aarch64.hlt(i32 immarg) nounwind
Loading