diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index 103709f3baa4e..2a9cf554b7420 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -46,6 +46,35 @@ template constexpr int asint(T F) { return __detail::bit_cast(F); } +//===----------------------------------------------------------------------===// +// asint16 builtins +//===----------------------------------------------------------------------===// + +/// \fn int16_t asint16(T X) +/// \brief Interprets the bit pattern of \a X as an 16-bit integer. +/// \param X The input value. + +#ifdef __HLSL_ENABLE_16_BIT + +template +_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2) +constexpr __detail::enable_if_t<__detail::is_same::value || + __detail::is_same::value || + __detail::is_same::value, + vector> asint16(vector V) { + return __detail::bit_cast(V); +} + +template +_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2) +constexpr __detail::enable_if_t<__detail::is_same::value || + __detail::is_same::value || + __detail::is_same::value, + int16_t> asint16(T F) { + return __detail::bit_cast(F); +} +#endif + //===----------------------------------------------------------------------===// // asuint builtins //===----------------------------------------------------------------------===// @@ -87,6 +116,7 @@ void asuint(double4, out uint4, out uint4); /// \fn uint16_t asuint16(T X) /// \brief Interprets the bit pattern of \a X as an 16-bit unsigned integer. /// \param X The input value. + #ifdef __HLSL_ENABLE_16_BIT template diff --git a/clang/test/CodeGenHLSL/builtins/asint16.hlsl b/clang/test/CodeGenHLSL/builtins/asint16.hlsl new file mode 100644 index 0000000000000..1d35125bfb8cc --- /dev/null +++ b/clang/test/CodeGenHLSL/builtins/asint16.hlsl @@ -0,0 +1,60 @@ +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.2-library %s -fnative-half-type -emit-llvm -O1 -o - | FileCheck %s + +//CHECK-LABEL: define {{.*}}test_ints +//CHECK-SAME: {{.*}}(i16 {{.*}} [[VAL:%.*]]){{.*}} +//CHECK-NOT: bitcast +//CHECK: entry: +//CHECK-NEXT: ret i16 [[VAL]] +int16_t test_int(int16_t p0) +{ + return asint16(p0); +} + +//CHECK-LABEL: define {{.*}}test_uint +//CHECK-SAME: {{.*}}(i16 {{.*}} [[VAL:%.*]]){{.*}} +//CHECK-NOT:bitcast +//CHECK: entry: +//CHECK-NEXT: ret i16 [[VAL]] +int16_t test_uint(uint16_t p0) +{ + return asint16(p0); +} + +//CHECK-LABEL: define {{.*}}test_half +//CHECK-SAME: {{.*}}(half {{.*}} [[VAL:%.*]]){{.*}} +//CHECK: [[RES:%.*]] = bitcast half [[VAL]] to i16 +//CHECK-NEXT : ret i16 [[RES]] +int16_t test_half(half p0) +{ + return asint16(p0); +} + +//CHECK-LABEL: define {{.*}}test_vector_int +//CHECK-SAME: {{.*}}(<4 x i16> {{.*}} [[VAL:%.*]]){{.*}} +//CHECK-NOT: bitcast +//CHECK: entry: +//CHECK-NEXT: ret <4 x i16> [[VAL]] +int16_t4 test_vector_int(int16_t4 p0) +{ + return asint16(p0); +} + +//CHECK-LABEL: define {{.*}}test_vector_uint +//CHECK-SAME: {{.*}}(<4 x i16> {{.*}} [[VAL:%.*]]){{.*}} +//CHECK-NOT: bitcast +//CHECK-NEXT: entry: +//CHECK-NEXT: ret <4 x i16> [[VAL]] +int16_t4 test_vector_uint(uint16_t4 p0) +{ + return asint16(p0); +} + +//CHECK-LABEL: define {{.*}}fn +//CHECK-SAME: {{.*}}(<4 x half> {{.*}} [[VAL:%.*]]){{.*}} +//CHECK: [[RES:%.*]] = bitcast <4 x half> [[VAL]] to <4 x i16> +//CHECK-NEXT: ret <4 x i16> [[RES]] +int16_t4 fn(half4 p1) +{ + return asint16(p1); +} + diff --git a/clang/test/SemaHLSL/BuiltIns/asint16-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/asint16-errors.hlsl new file mode 100644 index 0000000000000..e78560cf09083 --- /dev/null +++ b/clang/test/SemaHLSL/BuiltIns/asint16-errors.hlsl @@ -0,0 +1,43 @@ +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.2-library %s -fnative-half-type -verify + + +int16_t4 test_asint16_too_many_arg(uint16_t p0, uint16_t p1) +{ + return asint16(p0, p1); + // expected-error@-1 {{no matching function for call to 'asint16'}} + // 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}} +} + +int16_t test_asint16_int(int p1) +{ + return asint16(p1); + // expected-error@-1 {{no matching function for call to 'asint16'}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored: could not match 'vector' against 'int'}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with T = int]: no type named 'Type'}} +} + +int16_t test_asint16_float(float p1) +{ + return asint16(p1); + // expected-error@-1 {{no matching function for call to 'asint16'}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored: could not match 'vector' against 'float'}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with T = float]: no type named 'Type'}} +} + +int16_t4 test_asint16_vector_int(int4 p1) +{ + return asint16(p1); + // expected-error@-1 {{no matching function for call to 'asint16'}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with T = int, N = 4]: no type named 'Type'}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with T = int4]: no type named 'Type'}} +} + +int16_t4 test_asint16_vector_float(float4 p1) +{ + return asint16(p1); + // expected-error@-1 {{no matching function for call to 'asint16'}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with T = float, N = 4]: no type named 'Type'}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with T = float4]: no type named 'Type'}} +} + diff --git a/llvm/test/CodeGen/SPIRV/bitcast.ll b/llvm/test/CodeGen/SPIRV/bitcast.ll index d6c985dbadcc4..2688bdfe562a8 100644 --- a/llvm/test/CodeGen/SPIRV/bitcast.ll +++ b/llvm/test/CodeGen/SPIRV/bitcast.ll @@ -4,6 +4,7 @@ ; CHECK-SPIRV-DAG: %[[#TyInt32:]] = OpTypeInt 32 0 ; CHECK-SPIRV-DAG: %[[#TyInt16:]] = OpTypeInt 16 0 ; CHECK-SPIRV-DAG: %[[#TyHalf:]] = OpTypeFloat 16 +; CHECK-SPIRV-DAG: %[[#vec4_float_16:]] = OpTypeVector %[[#TyHalf]] 4 ; CHECK-SPIRV-DAG: %[[#Arg32:]] = OpFunctionParameter %[[#TyInt32]] ; CHECK-SPIRV-DAG: %[[#Arg16:]] = OpUConvert %[[#TyInt16]] %[[#Arg32]] ; CHECK-SPIRV-DAG: %[[#ValHalf:]] = OpBitcast %[[#TyHalf]] %[[#Arg16:]] @@ -19,3 +20,12 @@ entry: %res = bitcast half %val2 to i16 ret i16 %res } + +define <4 x i16> @test_vector_half4(<4 x half> nofpclass(nan inf) %p1) { +entry: + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec4_float_16]] + ; CHECK: %[[#Res1:]] = OpBitcast %[[#vec4_int_16]] %[[#arg0]] + %0 = bitcast <4 x half> %p1 to <4 x i16> + ; CHECK: OpReturnValue %[[#Res1]] + ret <4 x i16> %0 +}