diff --git a/clang/lib/Headers/CMakeLists.txt b/clang/lib/Headers/CMakeLists.txt index e928b5b142827..f85fbb49c4fad 100644 --- a/clang/lib/Headers/CMakeLists.txt +++ b/clang/lib/Headers/CMakeLists.txt @@ -87,6 +87,7 @@ set(hlsl_h set(hlsl_subdir_files hlsl/hlsl_basic_types.h hlsl/hlsl_intrinsics.h + hlsl/hlsl_detail.h ) set(hlsl_files ${hlsl_h} diff --git a/clang/lib/Headers/hlsl/hlsl_detail.h b/clang/lib/Headers/hlsl/hlsl_detail.h new file mode 100644 index 0000000000000..9801d86208159 --- /dev/null +++ b/clang/lib/Headers/hlsl/hlsl_detail.h @@ -0,0 +1,38 @@ +//===----- detail.h - HLSL definitions for intrinsics ----------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _HLSL_HLSL_DETAILS_H_ +#define _HLSL_HLSL_DETAILS_H_ + +namespace hlsl { + +namespace __detail { + +#define _HLSL_INLINE \ + __attribute__((__always_inline__, __nodebug__)) static inline + +template struct enable_if {}; + +template struct enable_if { + using Type = T; +}; + +template +_HLSL_INLINE typename enable_if >::Type +bit_cast(vector V) { + return __builtin_bit_cast(vector, V); +} + +template +_HLSL_INLINE typename enable_if::Type bit_cast(T F) { + return __builtin_bit_cast(U, F); +} + +} // namespace __detail +} // namespace hlsl +#endif //_HLSL_HLSL_DETAILS_H_ diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index 7a1edd93984de..7a09fb957fbea 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -9,6 +9,8 @@ #ifndef _HLSL_HLSL_INTRINSICS_H_ #define _HLSL_HLSL_INTRINSICS_H_ +#include "hlsl_detail.h" + namespace hlsl { // Note: Functions in this file are sorted alphabetically, then grouped by base @@ -387,6 +389,23 @@ float3 asin(float3); _HLSL_BUILTIN_ALIAS(__builtin_elementwise_asin) float4 asin(float4); +//===----------------------------------------------------------------------===// +// asuint builtins +//===----------------------------------------------------------------------===// + +/// \fn uint asuint(T Val) +/// \brief Interprets the bit pattern of x as an unsigned integer. +/// \param Val The input value. + +template +_HLSL_INLINE vector asuint(vector V) { + return __detail::bit_cast(V); +} + +template _HLSL_INLINE uint asuint(T F) { + return __detail::bit_cast(F); +} + //===----------------------------------------------------------------------===// // atan builtins //===----------------------------------------------------------------------===// diff --git a/clang/test/CodeGenHLSL/builtins/asuint.hlsl b/clang/test/CodeGenHLSL/builtins/asuint.hlsl new file mode 100644 index 0000000000000..ac3dae26d6cae --- /dev/null +++ b/clang/test/CodeGenHLSL/builtins/asuint.hlsl @@ -0,0 +1,41 @@ +// 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-NOT: bitcast +// CHECK: ret i32 [[VAL]] +uint test_uint(uint p0) { + return asuint(p0); +} + +// 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: bitcast float [[VAL]] to i32 +uint test_float(float p0) { + return asuint(p0); +} + +// 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-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: 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/asuint-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/asuint-errors.hlsl new file mode 100644 index 0000000000000..8c56fdddb1c24 --- /dev/null +++ b/clang/test/SemaHLSL/BuiltIns/asuint-errors.hlsl @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -verify + + +uint4 test_asuint_too_many_arg(float p0, float p1) { + return asuint(p0, p1); + // expected-error@-1 {{no matching function for call to 'asuint'}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires single argument 'V', but 2 arguments were provided}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires single argument 'F', but 2 arguments were provided}} +} + +uint test_asuint_double(double p1) { + return asuint(p1); + // expected-error@hlsl/hlsl_intrinsics.h:* {{no matching function for call to 'bit_cast'}} + // expected-note@-2 {{in instantiation of function template specialization 'hlsl::asuint'}} + // expected-note@hlsl/hlsl_detail.h:* {{candidate template ignored: could not match 'vector' against 'double'}} + // expected-note@hlsl/hlsl_detail.h:* {{candidate template ignored: substitution failure [with U = uint, T = double]: no type named 'Type'}} +} + +uint test_asuint_half(half p1) { + return asuint(p1); + // expected-error@hlsl/hlsl_intrinsics.h:* {{no matching function for call to 'bit_cast'}} + // expected-note@-2 {{in instantiation of function template specialization 'hlsl::asuint'}} + // expected-note@hlsl/hlsl_detail.h:* {{candidate template ignored: could not match 'vector' against 'half'}} + // expected-note@hlsl/hlsl_detail.h:* {{candidate template ignored: substitution failure [with U = uint, T = half]: no type named 'Type'}} +}