Skip to content

Commit c106024

Browse files
committed
added spirv scalar implementation, updated codegen and sema tests
1 parent b865be4 commit c106024

File tree

6 files changed

+56
-47
lines changed

6 files changed

+56
-47
lines changed

clang/lib/CodeGen/CGBuiltin.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20352,10 +20352,10 @@ Value *CodeGenFunction::EmitSPIRVBuiltinExpr(unsigned BuiltinID,
2035220352
E->getArg(1)->getType()->hasFloatingRepresentation() &&
2035320353
E->getArg(2)->getType()->hasFloatingRepresentation() &&
2035420354
"SmoothStep operands must have a float representation");
20355-
assert(E->getArg(0)->getType()->isVectorType() &&
20356-
E->getArg(1)->getType()->isVectorType() &&
20357-
E->getArg(2)->getType()->hasFloatingRepresentation() &&
20358-
"SmoothStep operands must be a vector");
20355+
assert((E->getArg(0)->getType()->isScalarType() || E->getArg(0)->getType()->isVectorType()) &&
20356+
(E->getArg(1)->getType()->isScalarType() || E->getArg(1)->getType()->isVectorType()) &&
20357+
(E->getArg(2)->getType()->isScalarType() || E->getArg(2)->getType()->isVectorType()) &&
20358+
"SmoothStep operands must be a scalar or vector");
2035920359
return Builder.CreateIntrinsic(
2036020360
/*ReturnType=*/Min->getType(), Intrinsic::spv_smoothstep,
2036120361
ArrayRef<Value *>{Min, Max, X}, nullptr, "spv.smoothstep");

clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -82,18 +82,22 @@ constexpr vector<T, N> fmod_vec_impl(vector<T, N> X, vector<T, N> Y) {
8282
}
8383

8484
template <typename T> constexpr T smoothstep_impl(T Min, T Max, T X) {
85-
T t = saturate((X - Min) / (Max - Min));
86-
return (3 - 2 * t) * t * t;
85+
#if (__has_builtin(__builtin_spirv_smoothstep))
86+
return __builtin_spirv_smoothstep(Min, Max, X);
87+
#else
88+
T S = saturate((X - Min) / (Max - Min));
89+
return (3 - 2 * S) * S * S;
90+
#endif
8791
}
8892

8993
template <typename T, int N>
90-
constexpr vector<T, N> smoothstep_vec_impl(vector<T, N> Min, vector<T, N> Max, vector<T, N> X) {
94+
constexpr vector<T, N> smoothstep_vec_impl(vector<T, N> Min, vector<T, N> Max,
95+
vector<T, N> X) {
9196
#if (__has_builtin(__builtin_spirv_smoothstep))
9297
return __builtin_spirv_smoothstep(Min, Max, X);
9398
#else
94-
// undefined?
95-
vector<T, N> t = saturate((X - Min) / (Max - Min));
96-
return (3 - 2 * t) * t * t;
99+
vector<T, N> S = saturate((X - Min) / (Max - Min));
100+
return (3 - 2 * S) * S * S;
97101
#endif
98102
}
99103

clang/lib/Headers/hlsl/hlsl_intrinsics.h

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -328,13 +328,15 @@ reflect(__detail::HLSL_FIXED_VECTOR<float, L> I,
328328
//===----------------------------------------------------------------------===//
329329

330330
/// \fn T smoothstep(T Min, T Max, T X)
331-
/// \brief Returns a smooth Hermite interpolation between 0 and 1, if \a X is in the range [\a Min, \a Max].
331+
/// \brief Returns a smooth Hermite interpolation between 0 and 1, if \a X is in
332+
/// the range [\a Min, \a Max].
332333
/// \param Min The minimum range of the x parameter.
333334
/// \param Max The maximum range of the x parameter.
334335
/// \param X The specified value to be interpolated.
335336
///
336-
/// The return value is 0.0 if \a X ≤ \a Min and 1.0 if \a X ≥ \a Max. When \a Min < \a X < \a Max,
337-
/// the function performs smooth Hermite interpolation between 0 and 1. Result is undefined if Min ≥ Max.
337+
/// The return value is 0.0 if \a X ≤ \a Min and 1.0 if \a X ≥ \a Max. When \a
338+
/// Min < \a X < \a Max, the function performs smooth Hermite interpolation
339+
/// between 0 and 1.
338340

339341
template <typename T>
340342
_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
@@ -363,8 +365,8 @@ const inline __detail::HLSL_FIXED_VECTOR<half, N> smoothstep(
363365
template <int N>
364366
const inline __detail::HLSL_FIXED_VECTOR<float, N>
365367
smoothstep(__detail::HLSL_FIXED_VECTOR<float, N> Min,
366-
__detail::HLSL_FIXED_VECTOR<float, N> Max,
367-
__detail::HLSL_FIXED_VECTOR<float, N> X) {
368+
__detail::HLSL_FIXED_VECTOR<float, N> Max,
369+
__detail::HLSL_FIXED_VECTOR<float, N> X) {
368370
return __detail::smoothstep_vec_impl(Min, Max, X);
369371
}
370372

clang/lib/Sema/SemaSPIRV.cpp

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -108,36 +108,33 @@ bool SemaSPIRV::CheckSPIRVBuiltinFunctionCall(unsigned BuiltinID,
108108
ExprResult A = TheCall->getArg(0);
109109
QualType ArgTyA = A.get()->getType();
110110
auto *VTyA = ArgTyA->getAs<VectorType>();
111-
if (VTyA == nullptr) {
111+
if (!(ArgTyA->isScalarType() || VTyA)) {
112112
SemaRef.Diag(A.get()->getBeginLoc(),
113-
diag::err_typecheck_convert_incompatible)
113+
diag::err_typecheck_expect_any_scalar_or_vector)
114114
<< ArgTyA
115-
<< SemaRef.Context.getVectorType(ArgTyA, 2, VectorKind::Generic) << 1
116-
<< 0 << 0;
115+
<< 1;
117116
return true;
118117
}
119118

120119
ExprResult B = TheCall->getArg(1);
121120
QualType ArgTyB = B.get()->getType();
122121
auto *VTyB = ArgTyB->getAs<VectorType>();
123-
if (VTyB == nullptr) {
122+
if (!(ArgTyB->isScalarType() || VTyB)) {
124123
SemaRef.Diag(A.get()->getBeginLoc(),
125-
diag::err_typecheck_convert_incompatible)
124+
diag::err_typecheck_expect_any_scalar_or_vector)
126125
<< ArgTyB
127-
<< SemaRef.Context.getVectorType(ArgTyB, 2, VectorKind::Generic) << 1
128-
<< 0 << 0;
126+
<< 1;
129127
return true;
130128
}
131129

132130
ExprResult C = TheCall->getArg(2);
133131
QualType ArgTyC = C.get()->getType();
134132
auto *VTyC = ArgTyC->getAs<VectorType>();
135-
if (VTyC == nullptr) {
133+
if (!(ArgTyC->isScalarType() || VTyC)) {
136134
SemaRef.Diag(A.get()->getBeginLoc(),
137-
diag::err_typecheck_convert_incompatible)
138-
<< ArgTyB
139-
<< SemaRef.Context.getVectorType(ArgTyC, 2, VectorKind::Generic) << 1
140-
<< 0 << 0;
135+
diag::err_typecheck_expect_any_scalar_or_vector)
136+
<< ArgTyC
137+
<< 1;
141138
return true;
142139
}
143140

clang/test/CodeGenHLSL/builtins/smoothstep.hlsl

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,12 @@
2222
// SPVCHECK-LABEL: define spir_func noundef nofpclass(nan inf) half @_Z20test_smoothstep_halfDhDhDh(
2323
// SPVCHECK-SAME: half noundef nofpclass(nan inf) [[MIN:%.*]], half noundef nofpclass(nan inf) [[MAX:%.*]], half noundef nofpclass(nan inf) [[X:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
2424
// SPVCHECK-NEXT: [[ENTRY:.*:]]
25-
// SPVCHECK-NEXT: [[SUB_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn half [[X]], [[MIN]]
26-
// SPVCHECK-NEXT: [[SUB1_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn half [[MAX]], [[MIN]]
27-
// SPVCHECK-NEXT: [[DIV_I:%.*]] = fdiv reassoc nnan ninf nsz arcp afn half [[SUB_I]], [[SUB1_I]]
28-
// SPVCHECK-NEXT: [[HLSL_SATURATE_I:%.*]] = tail call reassoc nnan ninf nsz arcp afn half @llvm.spv.saturate.f16(half [[DIV_I]])
29-
// SPVCHECK-NEXT: [[MUL_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[HLSL_SATURATE_I]], 0xH4000
30-
// SPVCHECK-NEXT: [[SUB2_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn half 0xH4200, [[MUL_I]]
31-
// SPVCHECK-NEXT: [[TMP0:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[HLSL_SATURATE_I]], [[HLSL_SATURATE_I]]
32-
// SPVCHECK-NEXT: [[MUL4_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[TMP0]], [[SUB2_I]]
33-
// SPVCHECK-NEXT: ret half [[MUL4_I]]
25+
// SPVCHECK-NEXT: [[CONV_I:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[MIN]] to double
26+
// SPVCHECK-NEXT: [[CONV1_I:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[MAX]] to double
27+
// SPVCHECK-NEXT: [[CONV2_I:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[X]] to double
28+
// SPVCHECK-NEXT: [[SPV_SMOOTHSTEP_I:%.*]] = tail call reassoc nnan ninf nsz arcp afn double @llvm.spv.smoothstep.f64(double [[CONV_I]], double [[CONV1_I]], double [[CONV2_I]])
29+
// SPVCHECK-NEXT: [[CONV3_I:%.*]] = fptrunc reassoc nnan ninf nsz arcp afn double [[SPV_SMOOTHSTEP_I]] to half
30+
// SPVCHECK-NEXT: ret half [[CONV3_I]]
3431
//
3532
half test_smoothstep_half(half Min, half Max, half X) { return smoothstep(Min, Max, X); }
3633

@@ -113,15 +110,12 @@ half4 test_smoothstep_half4(half4 Min, half4 Max, half4 X) { return smoothstep(M
113110
// SPVCHECK-LABEL: define spir_func noundef nofpclass(nan inf) float @_Z21test_smoothstep_floatfff(
114111
// SPVCHECK-SAME: float noundef nofpclass(nan inf) [[MIN:%.*]], float noundef nofpclass(nan inf) [[MAX:%.*]], float noundef nofpclass(nan inf) [[X:%.*]]) local_unnamed_addr #[[ATTR0]] {
115112
// SPVCHECK-NEXT: [[ENTRY:.*:]]
116-
// SPVCHECK-NEXT: [[SUB_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn float [[X]], [[MIN]]
117-
// SPVCHECK-NEXT: [[SUB1_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn float [[MAX]], [[MIN]]
118-
// SPVCHECK-NEXT: [[DIV_I:%.*]] = fdiv reassoc nnan ninf nsz arcp afn float [[SUB_I]], [[SUB1_I]]
119-
// SPVCHECK-NEXT: [[HLSL_SATURATE_I:%.*]] = tail call reassoc nnan ninf nsz arcp afn float @llvm.spv.saturate.f32(float [[DIV_I]])
120-
// SPVCHECK-NEXT: [[MUL_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[HLSL_SATURATE_I]], 2.000000e+00
121-
// SPVCHECK-NEXT: [[SUB2_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn float 3.000000e+00, [[MUL_I]]
122-
// SPVCHECK-NEXT: [[TMP0:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[HLSL_SATURATE_I]], [[HLSL_SATURATE_I]]
123-
// SPVCHECK-NEXT: [[MUL4_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[TMP0]], [[SUB2_I]]
124-
// SPVCHECK-NEXT: ret float [[MUL4_I]]
113+
// SPVCHECK-NEXT: [[CONV_I:%.*]] = fpext reassoc nnan ninf nsz arcp afn float [[MIN]] to double
114+
// SPVCHECK-NEXT: [[CONV1_I:%.*]] = fpext reassoc nnan ninf nsz arcp afn float [[MAX]] to double
115+
// SPVCHECK-NEXT: [[CONV2_I:%.*]] = fpext reassoc nnan ninf nsz arcp afn float [[X]] to double
116+
// SPVCHECK-NEXT: [[SPV_SMOOTHSTEP_I:%.*]] = tail call reassoc nnan ninf nsz arcp afn double @llvm.spv.smoothstep.f64(double [[CONV_I]], double [[CONV1_I]], double [[CONV2_I]])
117+
// SPVCHECK-NEXT: [[CONV3_I:%.*]] = fptrunc reassoc nnan ninf nsz arcp afn double [[SPV_SMOOTHSTEP_I]] to float
118+
// SPVCHECK-NEXT: ret float [[CONV3_I]]
125119
//
126120
float test_smoothstep_float(float Min, float Max, float X) { return smoothstep(Min, Max, X); }
127121

clang/test/CodeGenSPIRV/Builtins/smoothstep.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,20 @@ typedef float float2 __attribute__((ext_vector_type(2)));
66
typedef float float3 __attribute__((ext_vector_type(3)));
77
typedef float float4 __attribute__((ext_vector_type(4)));
88

9+
// CHECK-LABEL: define spir_func float @test_smoothstep_float(
10+
// CHECK-SAME: float noundef [[MIN:%.*]], float noundef [[MAX:%.*]], float noundef [[X:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
11+
// CHECK-NEXT: [[ENTRY:.*:]]
12+
// CHECK-NEXT: [[CONV:%.*]] = fpext float [[MIN]] to double
13+
// CHECK-NEXT: [[CONV1:%.*]] = fpext float [[MAX]] to double
14+
// CHECK-NEXT: [[CONV2:%.*]] = fpext float [[X]] to double
15+
// CHECK-NEXT: [[SPV_SMOOTHSTEP:%.*]] = tail call double @llvm.spv.smoothstep.f64(double [[CONV]], double [[CONV1]], double [[CONV2]])
16+
// CHECK-NEXT: [[CONV3:%.*]] = fptrunc double [[SPV_SMOOTHSTEP]] to float
17+
// CHECK-NEXT: ret float [[CONV3]]
18+
//
19+
float test_smoothstep_float(float Min, float Max, float X) { return __builtin_spirv_smoothstep(Min, Max, X); }
20+
921
// CHECK-LABEL: define spir_func <2 x float> @test_smoothstep_float2(
10-
// CHECK-SAME: <2 x float> noundef [[MIN:%.*]], <2 x float> noundef [[MAX:%.*]], <2 x float> noundef [[X:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
22+
// CHECK-SAME: <2 x float> noundef [[MIN:%.*]], <2 x float> noundef [[MAX:%.*]], <2 x float> noundef [[X:%.*]]) local_unnamed_addr #[[ATTR0]] {
1123
// CHECK-NEXT: [[ENTRY:.*:]]
1224
// CHECK-NEXT: [[SPV_SMOOTHSTEP:%.*]] = tail call <2 x float> @llvm.spv.smoothstep.v2f32(<2 x float> [[MIN]], <2 x float> [[MAX]], <2 x float> [[X]])
1325
// CHECK-NEXT: ret <2 x float> [[SPV_SMOOTHSTEP]]

0 commit comments

Comments
 (0)