[clang] [llvm] Add __hlt intrinsic for Windows ARM. (PR #96578)

Amy Huang via cfe-commits cfe-commits at lists.llvm.org
Wed Jun 26 11:27:28 PDT 2024


https://github.com/amykhuang updated https://github.com/llvm/llvm-project/pull/96578

>From 1b436900146e1a91efac95416077485571722517 Mon Sep 17 00:00:00 2001
From: Amy Huang <akhuang at google.com>
Date: Mon, 24 Jun 2024 16:55:08 -0700
Subject: [PATCH 1/2] Add __hlt intrinsic for Windows ARM.

---
 clang/include/clang/Basic/BuiltinsAArch64.def   |  1 +
 clang/lib/CodeGen/CGBuiltin.cpp                 |  5 +++++
 clang/lib/Headers/intrin.h                      |  3 +++
 clang/test/CodeGen/arm64-microsoft-intrinsics.c |  7 +++++++
 llvm/include/llvm/IR/IntrinsicsAArch64.td       |  3 +++
 llvm/lib/Target/AArch64/AArch64InstrInfo.td     |  3 ++-
 llvm/test/CodeGen/AArch64/arm64-hlt.ll          | 10 ++++++++++
 7 files changed, 31 insertions(+), 1 deletion(-)
 create mode 100644 llvm/test/CodeGen/AArch64/arm64-hlt.ll

diff --git a/clang/include/clang/Basic/BuiltinsAArch64.def b/clang/include/clang/Basic/BuiltinsAArch64.def
index 5f53c98167dfb..668c4296208de 100644
--- a/clang/include/clang/Basic/BuiltinsAArch64.def
+++ b/clang/include/clang/Basic/BuiltinsAArch64.def
@@ -291,6 +291,7 @@ TARGET_HEADER_BUILTIN(_CountOneBits, "UiUNi", "nh", INTRIN_H, ALL_MS_LANGUAGES,
 TARGET_HEADER_BUILTIN(_CountOneBits64, "UiULLi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
 
 TARGET_HEADER_BUILTIN(__prefetch, "vvC*", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(__hlt, "iUi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
 
 #undef BUILTIN
 #undef LANGBUILTIN
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 08a89bd123d03..c646614333499 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -11475,6 +11475,11 @@ 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);
+    return Builder.CreateCall(F, {EmitScalarExpr(E->getArg(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 1227f45d5432b..a8a3463a78494 100644
--- a/clang/lib/Headers/intrin.h
+++ b/clang/lib/Headers/intrin.h
@@ -397,7 +397,10 @@ unsigned int _CountLeadingSigns64(__int64);
 unsigned int _CountOneBits(unsigned long);
 unsigned int _CountOneBits64(unsigned __int64);
 
+int __hlt(unsigned int);
+
 void __cdecl __prefetch(const void *);
+
 #endif
 
 /*----------------------------------------------------------------------------*\
diff --git a/clang/test/CodeGen/arm64-microsoft-intrinsics.c b/clang/test/CodeGen/arm64-microsoft-intrinsics.c
index a354ed948ca5f..5d17cc1ca6162 100644
--- a/clang/test/CodeGen/arm64-microsoft-intrinsics.c
+++ b/clang/test/CodeGen/arm64-microsoft-intrinsics.c
@@ -127,6 +127,13 @@ 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);
+}
+
+// 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/llvm/include/llvm/IR/IntrinsicsAArch64.td b/llvm/include/llvm/IR/IntrinsicsAArch64.td
index 9a71aaa9f4434..d7c3189280de7 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 91e5bc3caa102..f4434525afecc 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -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">;
diff --git a/llvm/test/CodeGen/AArch64/arm64-hlt.ll b/llvm/test/CodeGen/AArch64/arm64-hlt.ll
new file mode 100644
index 0000000000000..b16d9a0426f0d
--- /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

>From f5ae6094aa9e67b36dde86fbb0b462fab0c76772 Mon Sep 17 00:00:00 2001
From: Amy Huang <akhuang at google.com>
Date: Wed, 26 Jun 2024 11:26:48 -0700
Subject: [PATCH 2/2] Updates

---
 clang/include/clang/Basic/BuiltinsAArch64.def | 3 ++-
 clang/lib/CodeGen/CGBuiltin.cpp               | 6 +++++-
 clang/lib/Headers/intrin.h                    | 2 +-
 3 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/clang/include/clang/Basic/BuiltinsAArch64.def b/clang/include/clang/Basic/BuiltinsAArch64.def
index 668c4296208de..f7453847d049f 100644
--- a/clang/include/clang/Basic/BuiltinsAArch64.def
+++ b/clang/include/clang/Basic/BuiltinsAArch64.def
@@ -291,7 +291,8 @@ TARGET_HEADER_BUILTIN(_CountOneBits, "UiUNi", "nh", INTRIN_H, ALL_MS_LANGUAGES,
 TARGET_HEADER_BUILTIN(_CountOneBits64, "UiULLi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
 
 TARGET_HEADER_BUILTIN(__prefetch, "vvC*", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
-TARGET_HEADER_BUILTIN(__hlt, "iUi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
+
+TARGET_HEADER_BUILTIN(__hlt, "UiUi.", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
 
 #undef BUILTIN
 #undef LANGBUILTIN
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index c646614333499..22038489153cb 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -11477,7 +11477,11 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
 
   if (BuiltinID == AArch64::BI__hlt) {
     Function *F = CGM.getIntrinsic(Intrinsic::aarch64_hlt);
-    return Builder.CreateCall(F, {EmitScalarExpr(E->getArg(0))});
+    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
diff --git a/clang/lib/Headers/intrin.h b/clang/lib/Headers/intrin.h
index a8a3463a78494..dcc7c55b18770 100644
--- a/clang/lib/Headers/intrin.h
+++ b/clang/lib/Headers/intrin.h
@@ -397,7 +397,7 @@ unsigned int _CountLeadingSigns64(__int64);
 unsigned int _CountOneBits(unsigned long);
 unsigned int _CountOneBits64(unsigned __int64);
 
-int __hlt(unsigned int);
+unsigned int __hlt(unsigned int, ...);
 
 void __cdecl __prefetch(const void *);
 



More information about the cfe-commits mailing list