Skip to content

[HLSL] Make casting functions constexpr #108902

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
Sep 20, 2024

Conversation

llvm-beanz
Copy link
Collaborator

This marks the bit_cast helper as constexpr and allows the casts implemented with it to also be constexpr. This is largely not a functional change, but it enables using the casts in expressions that need to be resolved at compile time as demonstrated with the static asserts in the new tests.

This marks the `bit_cast` helper as `constexpr` and allows the casts
implemented with it to also be `constexpr`. This is largely not a
functional change, but it enables using the casts in expressions that
need to be resolved at compile time as demonstrated with the static
asserts in the new tests.
@llvmbot llvmbot added clang Clang issues not falling into any other category backend:X86 clang:headers Headers provided by Clang, e.g. for intrinsics HLSL HLSL Language Support labels Sep 17, 2024
@llvmbot
Copy link
Member

llvmbot commented Sep 17, 2024

@llvm/pr-subscribers-hlsl

@llvm/pr-subscribers-backend-x86

Author: Chris B (llvm-beanz)

Changes

This marks the bit_cast helper as constexpr and allows the casts implemented with it to also be constexpr. This is largely not a functional change, but it enables using the casts in expressions that need to be resolved at compile time as demonstrated with the static asserts in the new tests.


Full diff: https://github.com/llvm/llvm-project/pull/108902.diff

5 Files Affected:

  • (modified) clang/lib/Headers/hlsl/hlsl_detail.h (+5-5)
  • (modified) clang/lib/Headers/hlsl/hlsl_intrinsics.h (+4-4)
  • (modified) clang/test/CodeGenHLSL/builtins/asuint.hlsl (+6-6)
  • (added) clang/test/SemaHLSL/BuiltIns/asfloat-constexpr.hlsl (+10)
  • (added) clang/test/SemaHLSL/BuiltIns/asuint-constexpr.hlsl (+10)
diff --git a/clang/lib/Headers/hlsl/hlsl_detail.h b/clang/lib/Headers/hlsl/hlsl_detail.h
index 9801d86208159f..40849dcdf187e4 100644
--- a/clang/lib/Headers/hlsl/hlsl_detail.h
+++ b/clang/lib/Headers/hlsl/hlsl_detail.h
@@ -13,23 +13,23 @@ namespace hlsl {
 
 namespace __detail {
 
-#define _HLSL_INLINE                                                           \
-  __attribute__((__always_inline__, __nodebug__)) static inline
-
 template <bool B, typename T> struct enable_if {};
 
 template <typename T> struct enable_if<true, T> {
   using Type = T;
 };
 
+template <bool B, class T = void>
+using enable_if_t = typename enable_if<B, T>::Type;
+
 template <typename U, typename T, int N>
-_HLSL_INLINE typename enable_if<sizeof(U) == sizeof(T), vector<U, N> >::Type
+constexpr enable_if_t<sizeof(U) == sizeof(T), vector<U, N> >
 bit_cast(vector<T, N> V) {
   return __builtin_bit_cast(vector<U, N>, V);
 }
 
 template <typename U, typename T>
-_HLSL_INLINE typename enable_if<sizeof(U) == sizeof(T), U>::Type bit_cast(T F) {
+constexpr enable_if_t<sizeof(U) == sizeof(T), U> bit_cast(T F) {
   return __builtin_bit_cast(U, F);
 }
 
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
index 6a50d50ebd3479..12f58ef0718695 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
@@ -370,11 +370,11 @@ bool any(double4);
 /// \param Val The input value.
 
 template <typename T, int N>
-_HLSL_INLINE vector<float, N> asfloat(vector<T, N> V) {
+constexpr vector<float, N> asfloat(vector<T, N> V) {
   return __detail::bit_cast<float, T, N>(V);
 }
 
-template <typename T> _HLSL_INLINE float asfloat(T F) {
+template <typename T> constexpr float asfloat(T F) {
   return __detail::bit_cast<float, T>(F);
 }
 
@@ -415,11 +415,11 @@ float4 asin(float4);
 /// \param Val The input value.
 
 template <typename T, int N>
-_HLSL_INLINE vector<uint, N> asuint(vector<T, N> V) {
+constexpr vector<uint, N> asuint(vector<T, N> V) {
   return __detail::bit_cast<uint, T, N>(V);
 }
 
-template <typename T> _HLSL_INLINE uint asuint(T F) {
+template <typename T> constexpr uint asuint(T F) {
   return __detail::bit_cast<uint, T>(F);
 }
 
diff --git a/clang/test/CodeGenHLSL/builtins/asuint.hlsl b/clang/test/CodeGenHLSL/builtins/asuint.hlsl
index ac3dae26d6caed..252a434ccce0dc 100644
--- a/clang/test/CodeGenHLSL/builtins/asuint.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/asuint.hlsl
@@ -1,40 +1,40 @@
 // RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s -fnative-half-type -emit-llvm -O1 -o - | FileCheck %s
 
-// CHECK: define {{.*}}test_uint{{.*}}(i32 {{.*}} [[VAL:%.*]]){{.*}} 
+// CHECK: define {{.*}}test_uint{{.*}}(i32 {{.*}} [[VAL:%.*]]){{.*}}
 // CHECK-NOT: bitcast
 // CHECK: ret i32 [[VAL]]
 uint test_uint(uint p0) {
   return asuint(p0);
 }
 
-// CHECK: define {{.*}}test_int{{.*}}(i32 {{.*}} [[VAL:%.*]]){{.*}} 
+// CHECK: define {{.*}}test_int{{.*}}(i32 {{.*}} [[VAL:%.*]]){{.*}}
 // CHECK-NOT: bitcast
 // CHECK: ret i32 [[VAL]]
 uint test_int(int p0) {
   return asuint(p0);
 }
 
-// CHECK: define {{.*}}test_float{{.*}}(float {{.*}} [[VAL:%.*]]){{.*}} 
+// CHECK: define {{.*}}test_float{{.*}}(float {{.*}} [[VAL:%.*]]){{.*}}
 // CHECK: bitcast float [[VAL]] to i32
 uint test_float(float p0) {
   return asuint(p0);
 }
 
-// CHECK: define {{.*}}test_vector_uint{{.*}}(<4 x i32> {{.*}} [[VAL:%.*]]){{.*}} 
+// CHECK: define {{.*}}test_vector_uint{{.*}}(<4 x i32> {{.*}} [[VAL:%.*]]){{.*}}
 // CHECK-NOT: bitcast
 // CHECK: ret <4 x i32> [[VAL]]
 uint4 test_vector_uint(uint4 p0) {
   return asuint(p0);
 }
 
-// CHECK: define {{.*}}test_vector_int{{.*}}(<4 x i32> {{.*}} [[VAL:%.*]]){{.*}} 
+// CHECK: define {{.*}}test_vector_int{{.*}}(<4 x i32> {{.*}} [[VAL:%.*]]){{.*}}
 // CHECK-NOT: bitcast
 // CHECK: ret <4 x i32> [[VAL]]
 uint4 test_vector_int(int4 p0) {
   return asuint(p0);
 }
 
-// CHECK: define {{.*}}test_vector_float{{.*}}(<4 x float> {{.*}} [[VAL:%.*]]){{.*}} 
+// CHECK: define {{.*}}test_vector_float{{.*}}(<4 x float> {{.*}} [[VAL:%.*]]){{.*}}
 // CHECK: bitcast <4 x float> [[VAL]] to <4 x i32>
 uint4 test_vector_float(float4 p0) {
   return asuint(p0);
diff --git a/clang/test/SemaHLSL/BuiltIns/asfloat-constexpr.hlsl b/clang/test/SemaHLSL/BuiltIns/asfloat-constexpr.hlsl
new file mode 100644
index 00000000000000..b2a54d23173e57
--- /dev/null
+++ b/clang/test/SemaHLSL/BuiltIns/asfloat-constexpr.hlsl
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -verify
+
+// expected-no-diagnostics
+
+// Because asuint should be constant evaluated, all the static asserts below
+// should work!
+void ConstExprTest() {
+  static_assert(asfloat(0x3f800000) == 1.0f, "One");
+  static_assert(asfloat(0x40000000.xxx).y == 2.0f, "Two");
+}
diff --git a/clang/test/SemaHLSL/BuiltIns/asuint-constexpr.hlsl b/clang/test/SemaHLSL/BuiltIns/asuint-constexpr.hlsl
new file mode 100644
index 00000000000000..be6afda3be6636
--- /dev/null
+++ b/clang/test/SemaHLSL/BuiltIns/asuint-constexpr.hlsl
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -verify
+
+// expected-no-diagnostics
+
+// Because asuint should be constant evaluated, all the static asserts below
+// should work!
+void ConstExprTest() {
+  static_assert(asuint(1) == 1u, "One");
+  static_assert(asuint(2.xxx).y == 2u, "Two");
+}

Copy link

github-actions bot commented Sep 17, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

Comment on lines -16 to -17
#define _HLSL_INLINE \
__attribute__((__always_inline__, __nodebug__)) static inline
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that while constexpr implies inline and since it also implies const dropping static here is fine too, we are dropping the two attributes here. always_inlineshouldn't matter, but droppingnodebugpresumably does have an effect. I don't fully understand whatnodebug` is gaining us though, and if we really want to use it we should probably do that more systematically in this header anyway, so this all seems fine.

@llvm-beanz llvm-beanz merged commit 4b4ea6d into llvm:main Sep 20, 2024
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:X86 clang:headers Headers provided by Clang, e.g. for intrinsics clang Clang issues not falling into any other category HLSL HLSL Language Support
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

4 participants