[clang] ae7ab04 - Add __hlt intrinsic for Windows ARM. (#96578)

via cfe-commits cfe-commits at lists.llvm.org
Mon Jul 8 12:59:08 PDT 2024


Author: Amy Huang
Date: 2024-07-08T12:59:02-07:00
New Revision: ae7ab043f2d8077ed00bb2d3239da4b96ad4b387

URL: https://github.com/llvm/llvm-project/commit/ae7ab043f2d8077ed00bb2d3239da4b96ad4b387
DIFF: https://github.com/llvm/llvm-project/commit/ae7ab043f2d8077ed00bb2d3239da4b96ad4b387.diff

LOG: Add __hlt intrinsic for Windows ARM. (#96578)

Add __hlt, which is a MSVC ARM64 intrinsic. 

This intrinsic is just the HLT instruction. MSVC's version seems to
return something undefined; in this patch
it will just return zero. 

MSVC intrinsics are defined here
https://learn.microsoft.com/en-us/cpp/intrinsics/arm64-intrinsics.
I used unsigned int as the return type, because that is what the MSVC
intrin.h header uses, even though
it conflicts with the documentation.

Added: 
    llvm/test/CodeGen/AArch64/arm64-hlt.ll

Modified: 
    clang/include/clang/Basic/BuiltinsAArch64.def
    clang/lib/CodeGen/CGBuiltin.cpp
    clang/lib/Headers/intrin.h
    clang/lib/Sema/SemaARM.cpp
    clang/test/CodeGen/arm64-microsoft-intrinsics.c
    clang/test/Sema/builtins-microsoft-arm64.c
    llvm/include/llvm/IR/IntrinsicsAArch64.td
    llvm/lib/Target/AArch64/AArch64InstrInfo.td

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Basic/BuiltinsAArch64.def b/clang/include/clang/Basic/BuiltinsAArch64.def
index 5fb199b1b2b032..36bd2b69dbbcb9 100644
--- a/clang/include/clang/Basic/BuiltinsAArch64.def
+++ b/clang/include/clang/Basic/BuiltinsAArch64.def
@@ -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

diff  --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 268137b319f76f..6cc0d9485720c0 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -11506,6 +11506,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 =

diff  --git a/clang/lib/Headers/intrin.h b/clang/lib/Headers/intrin.h
index d2250926ce5e10..6308c865ca9136 100644
--- a/clang/lib/Headers/intrin.h
+++ b/clang/lib/Headers/intrin.h
@@ -408,7 +408,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
 
 /*----------------------------------------------------------------------------*\

diff  --git a/clang/lib/Sema/SemaARM.cpp b/clang/lib/Sema/SemaARM.cpp
index 281d5341520547..370db341e997ec 100644
--- a/clang/lib/Sema/SemaARM.cpp
+++ b/clang/lib/Sema/SemaARM.cpp
@@ -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;
 

diff  --git a/clang/test/CodeGen/arm64-microsoft-intrinsics.c b/clang/test/CodeGen/arm64-microsoft-intrinsics.c
index a354ed948ca5f1..7953618d2f9d13 100644
--- a/clang/test/CodeGen/arm64-microsoft-intrinsics.c
+++ b/clang/test/CodeGen/arm64-microsoft-intrinsics.c
@@ -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);

diff  --git a/clang/test/Sema/builtins-microsoft-arm64.c b/clang/test/Sema/builtins-microsoft-arm64.c
index 6d0dc09c9ed83f..322cf7542f43a6 100644
--- a/clang/test/Sema/builtins-microsoft-arm64.c
+++ b/clang/test/Sema/builtins-microsoft-arm64.c
@@ -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}}

diff  --git a/llvm/include/llvm/IR/IntrinsicsAArch64.td b/llvm/include/llvm/IR/IntrinsicsAArch64.td
index 6f3694cf952d47..65e3403fbf1524 100644
--- a/llvm/include/llvm/IR/IntrinsicsAArch64.td
+++ b/llvm/include/llvm/IR/IntrinsicsAArch64.td
@@ -57,6 +57,7 @@ def int_aarch64_frint64x
     : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], [ LLVMMatchType<0> ],
                             [ IntrNoMem ]>;
 
+
 //===----------------------------------------------------------------------===//
 // HINT
 
@@ -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],

diff  --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index 1e06d5fdc7562e..78c8bf1e323aba 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -3111,7 +3111,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">;

diff  --git a/llvm/test/CodeGen/AArch64/arm64-hlt.ll b/llvm/test/CodeGen/AArch64/arm64-hlt.ll
new file mode 100644
index 00000000000000..b16d9a0426f0d4
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/arm64-hlt.ll
@@ -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


        


More information about the cfe-commits mailing list