Skip to content

Commit d5187a9

Browse files
committed
ldexp implementation and tests
1 parent 1f56afa commit d5187a9

File tree

4 files changed

+133
-0
lines changed

4 files changed

+133
-0
lines changed

clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,10 @@ template <typename T> constexpr T faceforward_impl(T N, T I, T Ng) {
134134
#endif
135135
}
136136

137+
template <typename T> constexpr T ldexp_impl(T X, T Exp) {
138+
return exp2(Exp) * X;
139+
}
140+
137141
} // namespace __detail
138142
} // namespace hlsl
139143

clang/lib/Headers/hlsl/hlsl_intrinsics.h

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,47 @@ fmod(__detail::HLSL_FIXED_VECTOR<float, N> X,
303303
return __detail::fmod_vec_impl(X, Y);
304304
}
305305

306+
//===----------------------------------------------------------------------===//
307+
// ldexp builtins
308+
//===----------------------------------------------------------------------===//
309+
310+
/// \fn T ldexp(T X, T Exp)
311+
/// \brief Returns the result of multiplying \a X by two, raised to the power of \a Exp.
312+
/// \param X [in] The specified value.
313+
/// \param Exp [in] The specified exponent.
314+
///
315+
/// This function uses the following formula: X * 2^Exp
316+
317+
template <typename T>
318+
_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
319+
const inline __detail::enable_if_t<__detail::is_arithmetic<T>::Value &&
320+
__detail::is_same<half, T>::value,
321+
T> ldexp(T X, T Exp) {
322+
return __detail::ldexp_impl(X, Exp);
323+
}
324+
325+
template <typename T>
326+
const inline __detail::enable_if_t<
327+
__detail::is_arithmetic<T>::Value && __detail::is_same<float, T>::value, T>
328+
ldexp(T X, T Exp) {
329+
return __detail::ldexp_impl(X, Exp);
330+
}
331+
332+
template <int N>
333+
_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
334+
const inline __detail::HLSL_FIXED_VECTOR<half, N> ldexp(
335+
__detail::HLSL_FIXED_VECTOR<half, N> X,
336+
__detail::HLSL_FIXED_VECTOR<half, N> Exp) {
337+
return __detail::ldexp_impl(X, Exp);
338+
}
339+
340+
template <int N>
341+
const inline __detail::HLSL_FIXED_VECTOR<float, N>
342+
ldexp(__detail::HLSL_FIXED_VECTOR<float, N> X,
343+
__detail::HLSL_FIXED_VECTOR<float, N> Exp) {
344+
return __detail::ldexp_impl(X, Exp);
345+
}
346+
306347
//===----------------------------------------------------------------------===//
307348
// length builtins
308349
//===----------------------------------------------------------------------===//
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s -fnative-half-type -emit-llvm -o - | FileCheck %s
2+
3+
// CHECK-LABEL: test_ldexp_half
4+
// CHECK: %elt.exp2.i = call reassoc nnan ninf nsz arcp afn half @llvm.exp2.f16(half %{{.*}})
5+
// CHECK: %mul.i = fmul reassoc nnan ninf nsz arcp afn half %elt.exp2.i, %{{.*}}
6+
// CHECK: ret half %mul.i
7+
half test_ldexp_half(half X, half Exp) { return ldexp(X, Exp); }
8+
9+
// CHECK-LABEL: test_ldexp_half2
10+
// CHECK: %elt.exp2.i = call reassoc nnan ninf nsz arcp afn <2 x half> @llvm.exp2.v2f16(<2 x half> %{{.*}})
11+
// CHECK: %mul.i = fmul reassoc nnan ninf nsz arcp afn <2 x half> %elt.exp2.i, %{{.*}}
12+
// CHECK: ret <2 x half> %mul.i
13+
half2 test_ldexp_half2(half2 X, half2 Exp) { return ldexp(X, Exp); }
14+
15+
// CHECK-LABEL: test_ldexp_half3
16+
// CHECK: %elt.exp2.i = call reassoc nnan ninf nsz arcp afn <3 x half> @llvm.exp2.v3f16(<3 x half> %{{.*}})
17+
// CHECK: %mul.i = fmul reassoc nnan ninf nsz arcp afn <3 x half> %elt.exp2.i, %{{.*}}
18+
// CHECK: ret <3 x half> %mul.i
19+
half3 test_ldexp_half3(half3 X, half3 Exp) { return ldexp(X, Exp); }
20+
21+
// CHECK-LABEL: test_ldexp_half4
22+
// CHECK: %elt.exp2.i = call reassoc nnan ninf nsz arcp afn <4 x half> @llvm.exp2.v4f16(<4 x half> %{{.*}})
23+
// CHECK: %mul.i = fmul reassoc nnan ninf nsz arcp afn <4 x half> %elt.exp2.i, %{{.*}}
24+
// CHECK: ret <4 x half> %mul.i
25+
half4 test_ldexp_half4(half4 X, half4 Exp) { return ldexp(X, Exp); }
26+
27+
// CHECK-LABEL: test_ldexp_float
28+
// CHECK: %elt.exp2.i = call reassoc nnan ninf nsz arcp afn float @llvm.exp2.f32(float %{{.*}})
29+
// CHECK: %mul.i = fmul reassoc nnan ninf nsz arcp afn float %elt.exp2.i, %{{.*}}
30+
// CHECK: ret float %mul.i
31+
float test_ldexp_float(float X, float Exp) { return ldexp(X, Exp); }
32+
33+
// CHECK-LABEL: test_ldexp_float2
34+
// CHECK: %elt.exp2.i = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.exp2.v2f32(<2 x float> %{{.*}})
35+
// CHECK: %mul.i = fmul reassoc nnan ninf nsz arcp afn <2 x float> %elt.exp2.i, %{{.*}}
36+
// CHECK: ret <2 x float> %mul.i
37+
float2 test_ldexp_float2(float2 X, float2 Exp) { return ldexp(X, Exp); }
38+
39+
// CHECK-LABEL: test_ldexp_float3
40+
// CHECK: %elt.exp2.i = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.exp2.v3f32(<3 x float> %{{.*}})
41+
// CHECK: %mul.i = fmul reassoc nnan ninf nsz arcp afn <3 x float> %elt.exp2.i, %{{.*}}
42+
// CHECK: ret <3 x float> %mul.i
43+
float3 test_ldexp_float3(float3 X, float3 Exp) { return ldexp(X, Exp); }
44+
45+
// CHECK-LABEL: test_ldexp_float4
46+
// CHECK: %elt.exp2.i = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.exp2.v4f32(<4 x float> %{{.*}})
47+
// CHECK: %mul.i = fmul reassoc nnan ninf nsz arcp afn <4 x float> %elt.exp2.i, %{{.*}}
48+
// CHECK: ret <4 x float> %mul.i
49+
float4 test_ldexp_float4(float4 X, float4 Exp) { return ldexp(X, Exp); }
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify
2+
3+
float test_double_inputs(double p0, double p1) {
4+
return ldexp(p0, p1);
5+
// expected-error@-1 {{no matching function for call to 'ldexp'}}
6+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored}}
7+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored}}
8+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored}}
9+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored}}
10+
}
11+
12+
float test_int_inputs(int p0, int p1, int p2) {
13+
return ldexp(p0, p1);
14+
// expected-error@-1 {{no matching function for call to 'ldexp'}}
15+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored}}
16+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored}}
17+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored}}
18+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored}}
19+
}
20+
21+
float1 test_vec1_inputs(float1 p0, float1 p1) {
22+
return ldexp(p0, p1);
23+
// expected-error@-1 {{no matching function for call to 'ldexp'}}
24+
// 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>>'}}
25+
// 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>>'}}
26+
// 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>'}}
27+
// 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>'}}
28+
}
29+
30+
typedef float float5 __attribute__((ext_vector_type(5)));
31+
32+
float5 test_vec5_inputs(float5 p0, float5 p1) {
33+
return ldexp(p0, p1);
34+
// expected-error@-1 {{no matching function for call to 'ldexp'}}
35+
// 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>>'}}
36+
// 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>>'}}
37+
// 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>'}}
38+
// 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>'}}
39+
}

0 commit comments

Comments
 (0)