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
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
10 changes: 5 additions & 5 deletions clang/lib/Headers/hlsl/hlsl_detail.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,23 @@ namespace hlsl {

namespace __detail {

#define _HLSL_INLINE \
__attribute__((__always_inline__, __nodebug__)) static inline
Comment on lines -16 to -17
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.


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);
}

Expand Down
9 changes: 4 additions & 5 deletions clang/lib/Headers/hlsl/hlsl_intrinsics.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down Expand Up @@ -414,12 +414,11 @@ float4 asin(float4);
/// \brief Interprets the bit pattern of x as an unsigned integer.
/// \param Val The input value.

template <typename T, int N>
_HLSL_INLINE vector<uint, N> asuint(vector<T, N> V) {
template <typename T, int N> 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);
}

Expand Down
12 changes: 6 additions & 6 deletions clang/test/CodeGenHLSL/builtins/asuint.hlsl
Original file line number Diff line number Diff line change
@@ -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);
Expand Down
10 changes: 10 additions & 0 deletions clang/test/SemaHLSL/BuiltIns/asfloat-constexpr.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -verify

// expected-no-diagnostics

// Because asfloat 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");
}
10 changes: 10 additions & 0 deletions clang/test/SemaHLSL/BuiltIns/asuint-constexpr.hlsl
Original file line number Diff line number Diff line change
@@ -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");
}
Loading