llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-backend-x86 Author: Kaitlin Peng (kmpeng) <details> <summary>Changes</summary> Closes #<!-- -->99133. Implemented `ldexp` entirely in `hlsl_intrinsics.h` and `hlsl_intrinsic_helpers.h`, added coresponding tests in `clang/test/CodeGenHLSL/builtins/ldexp.hlsl` and `clang/test/SemaHLSL/BuiltIns/ldexp-errors.hlsl`. --- Full diff: https://github.com/llvm/llvm-project/pull/138182.diff 4 Files Affected: - (modified) clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h (+4) - (modified) clang/lib/Headers/hlsl/hlsl_intrinsics.h (+41) - (added) clang/test/CodeGenHLSL/builtins/ldexp.hlsl (+49) - (added) clang/test/SemaHLSL/BuiltIns/ldexp-errors.hlsl (+39) ``````````diff diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h b/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h index 3180492b7de36..4eb7b8f45c85a 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h @@ -134,6 +134,10 @@ template <typename T> constexpr T faceforward_impl(T N, T I, T Ng) { #endif } +template <typename T> constexpr T ldexp_impl(T X, T Exp) { + return exp2(Exp) * X; +} + } // namespace __detail } // namespace hlsl diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index 193e7e6e99498..ffeb09bb49bef 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -303,6 +303,47 @@ fmod(__detail::HLSL_FIXED_VECTOR<float, N> X, return __detail::fmod_vec_impl(X, Y); } +//===----------------------------------------------------------------------===// +// ldexp builtins +//===----------------------------------------------------------------------===// + +/// \fn T ldexp(T X, T Exp) +/// \brief Returns the result of multiplying \a X by two, raised to the power of \a Exp. +/// \param X [in] The specified value. +/// \param Exp [in] The specified exponent. +/// +/// This function uses the following formula: X * 2^Exp + +template <typename T> +_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2) +const inline __detail::enable_if_t<__detail::is_arithmetic<T>::Value && + __detail::is_same<half, T>::value, + T> ldexp(T X, T Exp) { + return __detail::ldexp_impl(X, Exp); +} + +template <typename T> +const inline __detail::enable_if_t< + __detail::is_arithmetic<T>::Value && __detail::is_same<float, T>::value, T> +ldexp(T X, T Exp) { + return __detail::ldexp_impl(X, Exp); +} + +template <int N> +_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2) +const inline __detail::HLSL_FIXED_VECTOR<half, N> ldexp( + __detail::HLSL_FIXED_VECTOR<half, N> X, + __detail::HLSL_FIXED_VECTOR<half, N> Exp) { + return __detail::ldexp_impl(X, Exp); +} + +template <int N> +const inline __detail::HLSL_FIXED_VECTOR<float, N> +ldexp(__detail::HLSL_FIXED_VECTOR<float, N> X, + __detail::HLSL_FIXED_VECTOR<float, N> Exp) { + return __detail::ldexp_impl(X, Exp); +} + //===----------------------------------------------------------------------===// // length builtins //===----------------------------------------------------------------------===// diff --git a/clang/test/CodeGenHLSL/builtins/ldexp.hlsl b/clang/test/CodeGenHLSL/builtins/ldexp.hlsl new file mode 100644 index 0000000000000..6a6c04318f805 --- /dev/null +++ b/clang/test/CodeGenHLSL/builtins/ldexp.hlsl @@ -0,0 +1,49 @@ +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s -fnative-half-type -emit-llvm -o - | FileCheck %s + +// CHECK-LABEL: test_ldexp_half +// CHECK: %elt.exp2.i = call reassoc nnan ninf nsz arcp afn half @llvm.exp2.f16(half %{{.*}}) +// CHECK: %mul.i = fmul reassoc nnan ninf nsz arcp afn half %elt.exp2.i, %{{.*}} +// CHECK: ret half %mul.i +half test_ldexp_half(half X, half Exp) { return ldexp(X, Exp); } + +// CHECK-LABEL: test_ldexp_half2 +// CHECK: %elt.exp2.i = call reassoc nnan ninf nsz arcp afn <2 x half> @llvm.exp2.v2f16(<2 x half> %{{.*}}) +// CHECK: %mul.i = fmul reassoc nnan ninf nsz arcp afn <2 x half> %elt.exp2.i, %{{.*}} +// CHECK: ret <2 x half> %mul.i +half2 test_ldexp_half2(half2 X, half2 Exp) { return ldexp(X, Exp); } + +// CHECK-LABEL: test_ldexp_half3 +// CHECK: %elt.exp2.i = call reassoc nnan ninf nsz arcp afn <3 x half> @llvm.exp2.v3f16(<3 x half> %{{.*}}) +// CHECK: %mul.i = fmul reassoc nnan ninf nsz arcp afn <3 x half> %elt.exp2.i, %{{.*}} +// CHECK: ret <3 x half> %mul.i +half3 test_ldexp_half3(half3 X, half3 Exp) { return ldexp(X, Exp); } + +// CHECK-LABEL: test_ldexp_half4 +// CHECK: %elt.exp2.i = call reassoc nnan ninf nsz arcp afn <4 x half> @llvm.exp2.v4f16(<4 x half> %{{.*}}) +// CHECK: %mul.i = fmul reassoc nnan ninf nsz arcp afn <4 x half> %elt.exp2.i, %{{.*}} +// CHECK: ret <4 x half> %mul.i +half4 test_ldexp_half4(half4 X, half4 Exp) { return ldexp(X, Exp); } + +// CHECK-LABEL: test_ldexp_float +// CHECK: %elt.exp2.i = call reassoc nnan ninf nsz arcp afn float @llvm.exp2.f32(float %{{.*}}) +// CHECK: %mul.i = fmul reassoc nnan ninf nsz arcp afn float %elt.exp2.i, %{{.*}} +// CHECK: ret float %mul.i +float test_ldexp_float(float X, float Exp) { return ldexp(X, Exp); } + +// CHECK-LABEL: test_ldexp_float2 +// CHECK: %elt.exp2.i = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.exp2.v2f32(<2 x float> %{{.*}}) +// CHECK: %mul.i = fmul reassoc nnan ninf nsz arcp afn <2 x float> %elt.exp2.i, %{{.*}} +// CHECK: ret <2 x float> %mul.i +float2 test_ldexp_float2(float2 X, float2 Exp) { return ldexp(X, Exp); } + +// CHECK-LABEL: test_ldexp_float3 +// CHECK: %elt.exp2.i = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.exp2.v3f32(<3 x float> %{{.*}}) +// CHECK: %mul.i = fmul reassoc nnan ninf nsz arcp afn <3 x float> %elt.exp2.i, %{{.*}} +// CHECK: ret <3 x float> %mul.i +float3 test_ldexp_float3(float3 X, float3 Exp) { return ldexp(X, Exp); } + +// CHECK-LABEL: test_ldexp_float4 +// CHECK: %elt.exp2.i = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.exp2.v4f32(<4 x float> %{{.*}}) +// CHECK: %mul.i = fmul reassoc nnan ninf nsz arcp afn <4 x float> %elt.exp2.i, %{{.*}} +// CHECK: ret <4 x float> %mul.i +float4 test_ldexp_float4(float4 X, float4 Exp) { return ldexp(X, Exp); } diff --git a/clang/test/SemaHLSL/BuiltIns/ldexp-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/ldexp-errors.hlsl new file mode 100644 index 0000000000000..0bc7f7e40f5d3 --- /dev/null +++ b/clang/test/SemaHLSL/BuiltIns/ldexp-errors.hlsl @@ -0,0 +1,39 @@ +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify + +float test_double_inputs(double p0, double p1) { + return ldexp(p0, p1); + // expected-error@-1 {{no matching function for call to 'ldexp'}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored}} +} + +float test_int_inputs(int p0, int p1, int p2) { + return ldexp(p0, p1); + // expected-error@-1 {{no matching function for call to 'ldexp'}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored}} +} + +float1 test_vec1_inputs(float1 p0, float1 p1) { + return ldexp(p0, p1); + // expected-error@-1 {{no matching function for call to 'ldexp'}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with T = float1]: no type named 'Type' in 'hlsl::__detail::enable_if<false, vector<float, 1>>'}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with T = float1]: no type named 'Type' in 'hlsl::__detail::enable_if<false, vector<float, 1>>'}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with N = 1]: no type named 'Type' in 'hlsl::__detail::enable_if<false, half>'}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with N = 1]: no type named 'Type' in 'hlsl::__detail::enable_if<false, float>'}} +} + +typedef float float5 __attribute__((ext_vector_type(5))); + +float5 test_vec5_inputs(float5 p0, float5 p1) { + return ldexp(p0, p1); + // expected-error@-1 {{no matching function for call to 'ldexp'}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with T = float5]: no type named 'Type' in 'hlsl::__detail::enable_if<false, vector<float, 5>>'}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with T = float5]: no type named 'Type' in 'hlsl::__detail::enable_if<false, vector<float, 5>>'}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with N = 5]: no type named 'Type' in 'hlsl::__detail::enable_if<false, half>'}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with N = 5]: no type named 'Type' in 'hlsl::__detail::enable_if<false, float>'}} +} `````````` </details> https://github.com/llvm/llvm-project/pull/138182 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits