llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-llvm-ir Author: Kaitlin Peng (kmpeng) <details> <summary>Changes</summary> Closes #<!-- -->99156. Tasks completed: - Implement `smoothstep` using HLSL source in `hlsl_intrinsics.h` - Implement the `smoothstep` SPIR-V target built-in in `clang/include/clang/Basic/BuiltinsSPIRV.td` - Add sema checks for `smoothstep` to `CheckSPIRVBuiltinFunctionCall` in `clang/lib/Sema/SemaSPIRV.cpp` - Add codegen for spv `smoothstep` to `EmitSPIRVBuiltinExpr` in `CGBuiltin.cpp` - Add codegen tests to `clang/test/CodeGenHLSL/builtins/smoothstep.hlsl` - Add spv codegen test to `clang/test/CodeGenSPIRV/Builtins/smoothstep.c` - Add sema tests to `clang/test/SemaHLSL/BuiltIns/smoothstep-errors.hlsl` - Add spv sema tests to `clang/test/SemaSPIRV/BuiltIns/smoothstep-errors.c` - Create the `int_spv_smoothstep` intrinsic in `IntrinsicsSPIRV.td` - In SPIRVInstructionSelector.cpp create the `smoothstep` lowering and map it to `int_spv_smoothstep` in `SPIRVInstructionSelector::selectIntrinsic` - Create SPIR-V backend test case in `llvm/test/CodeGen/SPIRV/hlsl-intrinsics/smoothstep.ll` - Create SPIR-V backend test case in `llvm/test/CodeGen/SPIRV/opencl/smoothstep.ll` --- Patch is 41.67 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/132288.diff 13 Files Affected: - (modified) clang/include/clang/Basic/BuiltinsSPIRV.td (+6) - (modified) clang/lib/CodeGen/CGBuiltin.cpp (+19) - (modified) clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h (+20) - (modified) clang/lib/Headers/hlsl/hlsl_intrinsics.h (+48) - (modified) clang/lib/Sema/SemaSPIRV.cpp (+38) - (added) clang/test/CodeGenHLSL/builtins/smoothstep.hlsl (+183) - (added) clang/test/CodeGenSPIRV/Builtins/smoothstep.c (+44) - (added) clang/test/SemaHLSL/BuiltIns/smoothstep-errors.hlsl (+66) - (added) clang/test/SemaSPIRV/BuiltIns/smoothstep-errors.c (+18) - (modified) llvm/include/llvm/IR/IntrinsicsSPIRV.td (+1) - (modified) llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp (+2) - (added) llvm/test/CodeGen/SPIRV/hlsl-intrinsics/smoothstep.ll (+60) - (added) llvm/test/CodeGen/SPIRV/opencl/smoothstep.ll (+61) ``````````diff diff --git a/clang/include/clang/Basic/BuiltinsSPIRV.td b/clang/include/clang/Basic/BuiltinsSPIRV.td index 34933e889ba31..2eb4c733b0a42 100644 --- a/clang/include/clang/Basic/BuiltinsSPIRV.td +++ b/clang/include/clang/Basic/BuiltinsSPIRV.td @@ -25,3 +25,9 @@ def SPIRVReflect : Builtin { let Attributes = [NoThrow, Const]; let Prototype = "void(...)"; } + +def SPIRVSmoothStep : Builtin { + let Spellings = ["__builtin_spirv_smoothstep"]; + let Attributes = [NoThrow, Const]; + let Prototype = "void(...)"; +} diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index c126f88b9e3a5..ac92f89415724 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -20955,6 +20955,25 @@ Value *CodeGenFunction::EmitSPIRVBuiltinExpr(unsigned BuiltinID, /*ReturnType=*/I->getType(), Intrinsic::spv_reflect, ArrayRef<Value *>{I, N}, nullptr, "spv.reflect"); } + case SPIRV::BI__builtin_spirv_smoothstep: { + Value *Min = EmitScalarExpr(E->getArg(0)); + Value *Max = EmitScalarExpr(E->getArg(1)); + Value *X = EmitScalarExpr(E->getArg(2)); + assert(E->getArg(0)->getType()->hasFloatingRepresentation() && + E->getArg(1)->getType()->hasFloatingRepresentation() && + E->getArg(2)->getType()->hasFloatingRepresentation() && + "SmoothStep operands must have a float representation"); + assert((E->getArg(0)->getType()->isScalarType() || + E->getArg(0)->getType()->isVectorType()) && + (E->getArg(1)->getType()->isScalarType() || + E->getArg(1)->getType()->isVectorType()) && + (E->getArg(2)->getType()->isScalarType() || + E->getArg(2)->getType()->isVectorType()) && + "SmoothStep operands must be a scalar or vector"); + return Builder.CreateIntrinsic( + /*ReturnType=*/Min->getType(), Intrinsic::spv_smoothstep, + ArrayRef<Value *>{Min, Max, X}, nullptr, "spv.smoothstep"); + } } return nullptr; } diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h b/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h index 89ab664e90ba9..8cdd63d7e07bb 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h @@ -81,6 +81,26 @@ constexpr vector<T, N> fmod_vec_impl(vector<T, N> X, vector<T, N> Y) { #endif } +template <typename T> constexpr T smoothstep_impl(T Min, T Max, T X) { +#if (__has_builtin(__builtin_spirv_smoothstep)) + return __builtin_spirv_smoothstep(Min, Max, X); +#else + T S = saturate((X - Min) / (Max - Min)); + return (3 - 2 * S) * S * S; +#endif +} + +template <typename T, int N> +constexpr vector<T, N> smoothstep_vec_impl(vector<T, N> Min, vector<T, N> Max, + vector<T, N> X) { +#if (__has_builtin(__builtin_spirv_smoothstep)) + return __builtin_spirv_smoothstep(Min, Max, X); +#else + vector<T, N> S = saturate((X - Min) / (Max - Min)); + return (3 - 2 * S) * S * S; +#endif +} + } // namespace __detail } // namespace hlsl diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index a48a8e998a015..3803a87d32afc 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -264,5 +264,53 @@ reflect(__detail::HLSL_FIXED_VECTOR<float, L> I, __detail::HLSL_FIXED_VECTOR<float, L> N) { return __detail::reflect_vec_impl(I, N); } + +//===----------------------------------------------------------------------===// +// smoothstep builtin +//===----------------------------------------------------------------------===// + +/// \fn T smoothstep(T Min, T Max, T X) +/// \brief Returns a smooth Hermite interpolation between 0 and 1, if \a X is in +/// the range [\a Min, \a Max]. +/// \param Min The minimum range of the x parameter. +/// \param Max The maximum range of the x parameter. +/// \param X The specified value to be interpolated. +/// +/// 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, the function performs smooth Hermite interpolation +/// between 0 and 1. + +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> smoothstep(T Min, T Max, T X) { + return __detail::smoothstep_impl(Min, Max, X); +} + +template <typename T> +const inline __detail::enable_if_t< + __detail::is_arithmetic<T>::Value && __detail::is_same<float, T>::value, T> +smoothstep(T Min, T Max, T X) { + return __detail::smoothstep_impl(Min, Max, X); +} + +template <int N> +_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2) +const inline __detail::HLSL_FIXED_VECTOR<half, N> smoothstep( + __detail::HLSL_FIXED_VECTOR<half, N> Min, + __detail::HLSL_FIXED_VECTOR<half, N> Max, + __detail::HLSL_FIXED_VECTOR<half, N> X) { + return __detail::smoothstep_vec_impl(Min, Max, X); +} + +template <int N> +const inline __detail::HLSL_FIXED_VECTOR<float, N> +smoothstep(__detail::HLSL_FIXED_VECTOR<float, N> Min, + __detail::HLSL_FIXED_VECTOR<float, N> Max, + __detail::HLSL_FIXED_VECTOR<float, N> X) { + return __detail::smoothstep_vec_impl(Min, Max, X); +} + } // namespace hlsl #endif //_HLSL_HLSL_INTRINSICS_H_ diff --git a/clang/lib/Sema/SemaSPIRV.cpp b/clang/lib/Sema/SemaSPIRV.cpp index 94534485e07c3..2cbb57a739a1a 100644 --- a/clang/lib/Sema/SemaSPIRV.cpp +++ b/clang/lib/Sema/SemaSPIRV.cpp @@ -101,6 +101,44 @@ bool SemaSPIRV::CheckSPIRVBuiltinFunctionCall(unsigned BuiltinID, TheCall->setType(RetTy); break; } + case SPIRV::BI__builtin_spirv_smoothstep: { + if (SemaRef.checkArgCount(TheCall, 3)) + return true; + + ExprResult A = TheCall->getArg(0); + QualType ArgTyA = A.get()->getType(); + auto *VTyA = ArgTyA->getAs<VectorType>(); + if (!(ArgTyA->isScalarType() || VTyA)) { + SemaRef.Diag(A.get()->getBeginLoc(), + diag::err_typecheck_expect_any_scalar_or_vector) + << ArgTyA << 1; + return true; + } + + ExprResult B = TheCall->getArg(1); + QualType ArgTyB = B.get()->getType(); + auto *VTyB = ArgTyB->getAs<VectorType>(); + if (!(ArgTyB->isScalarType() || VTyB)) { + SemaRef.Diag(A.get()->getBeginLoc(), + diag::err_typecheck_expect_any_scalar_or_vector) + << ArgTyB << 1; + return true; + } + + ExprResult C = TheCall->getArg(2); + QualType ArgTyC = C.get()->getType(); + auto *VTyC = ArgTyC->getAs<VectorType>(); + if (!(ArgTyC->isScalarType() || VTyC)) { + SemaRef.Diag(A.get()->getBeginLoc(), + diag::err_typecheck_expect_any_scalar_or_vector) + << ArgTyC << 1; + return true; + } + + QualType RetTy = ArgTyA; + TheCall->setType(RetTy); + break; + } } return false; } diff --git a/clang/test/CodeGenHLSL/builtins/smoothstep.hlsl b/clang/test/CodeGenHLSL/builtins/smoothstep.hlsl new file mode 100644 index 0000000000000..bbb19692f1225 --- /dev/null +++ b/clang/test/CodeGenHLSL/builtins/smoothstep.hlsl @@ -0,0 +1,183 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5 +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ +// RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \ +// RUN: -emit-llvm -O1 -o - | FileCheck %s +// RUN: %clang_cc1 -finclude-default-header -triple \ +// RUN: spirv-unknown-vulkan-compute %s -fnative-half-type \ +// RUN: -emit-llvm -O1 -o - | FileCheck %s --check-prefix=SPVCHECK + +// CHECK-LABEL: define noundef nofpclass(nan inf) half @_Z20test_smoothstep_halfDhDhDh( +// CHECK-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]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[SUB_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn half [[X]], [[MIN]] +// CHECK-NEXT: [[SUB1_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn half [[MAX]], [[MIN]] +// CHECK-NEXT: [[DIV_I:%.*]] = fdiv reassoc nnan ninf nsz arcp afn half [[SUB_I]], [[SUB1_I]] +// CHECK-NEXT: [[HLSL_SATURATE_I:%.*]] = tail call reassoc nnan ninf nsz arcp afn half @llvm.dx.saturate.f16(half [[DIV_I]]) +// CHECK-NEXT: [[MUL_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[HLSL_SATURATE_I]], 0xH4000 +// CHECK-NEXT: [[SUB2_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn half 0xH4200, [[MUL_I]] +// CHECK-NEXT: [[TMP0:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[HLSL_SATURATE_I]], [[HLSL_SATURATE_I]] +// CHECK-NEXT: [[MUL4_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[TMP0]], [[SUB2_I]] +// CHECK-NEXT: ret half [[MUL4_I]] +// +// SPVCHECK-LABEL: define spir_func noundef nofpclass(nan inf) half @_Z20test_smoothstep_halfDhDhDh( +// 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]+]] { +// SPVCHECK-NEXT: [[ENTRY:.*:]] +// SPVCHECK-NEXT: [[CONV_I:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[MIN]] to double +// SPVCHECK-NEXT: [[CONV1_I:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[MAX]] to double +// SPVCHECK-NEXT: [[CONV2_I:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[X]] to double +// 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]]) +// SPVCHECK-NEXT: [[CONV3_I:%.*]] = fptrunc reassoc nnan ninf nsz arcp afn double [[SPV_SMOOTHSTEP_I]] to half +// SPVCHECK-NEXT: ret half [[CONV3_I]] +// +half test_smoothstep_half(half Min, half Max, half X) { return smoothstep(Min, Max, X); } + +// CHECK-LABEL: define noundef nofpclass(nan inf) <2 x half> @_Z21test_smoothstep_half2Dv2_DhS_S_( +// CHECK-SAME: <2 x half> noundef nofpclass(nan inf) [[MIN:%.*]], <2 x half> noundef nofpclass(nan inf) [[MAX:%.*]], <2 x half> noundef nofpclass(nan inf) [[X:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[SUB_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn <2 x half> [[X]], [[MIN]] +// CHECK-NEXT: [[SUB1_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn <2 x half> [[MAX]], [[MIN]] +// CHECK-NEXT: [[DIV_I:%.*]] = fdiv reassoc nnan ninf nsz arcp afn <2 x half> [[SUB_I]], [[SUB1_I]] +// CHECK-NEXT: [[HLSL_SATURATE_I:%.*]] = tail call reassoc nnan ninf nsz arcp afn <2 x half> @llvm.dx.saturate.v2f16(<2 x half> [[DIV_I]]) +// CHECK-NEXT: [[MUL_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn <2 x half> [[HLSL_SATURATE_I]], splat (half 0xH4000) +// CHECK-NEXT: [[SUB2_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn <2 x half> splat (half 0xH4200), [[MUL_I]] +// CHECK-NEXT: [[TMP0:%.*]] = fmul reassoc nnan ninf nsz arcp afn <2 x half> [[HLSL_SATURATE_I]], [[HLSL_SATURATE_I]] +// CHECK-NEXT: [[MUL4_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn <2 x half> [[TMP0]], [[SUB2_I]] +// CHECK-NEXT: ret <2 x half> [[MUL4_I]] +// +// SPVCHECK-LABEL: define spir_func noundef nofpclass(nan inf) <2 x half> @_Z21test_smoothstep_half2Dv2_DhS_S_( +// SPVCHECK-SAME: <2 x half> noundef nofpclass(nan inf) [[MIN:%.*]], <2 x half> noundef nofpclass(nan inf) [[MAX:%.*]], <2 x half> noundef nofpclass(nan inf) [[X:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SPVCHECK-NEXT: [[ENTRY:.*:]] +// SPVCHECK-NEXT: [[SPV_SMOOTHSTEP_I:%.*]] = tail call reassoc nnan ninf nsz arcp afn noundef <2 x half> @llvm.spv.smoothstep.v2f16(<2 x half> [[MIN]], <2 x half> [[MAX]], <2 x half> [[X]]) +// SPVCHECK-NEXT: ret <2 x half> [[SPV_SMOOTHSTEP_I]] +// +half2 test_smoothstep_half2(half2 Min, half2 Max, half2 X) { return smoothstep(Min, Max, X); } + +// CHECK-LABEL: define noundef nofpclass(nan inf) <3 x half> @_Z21test_smoothstep_half3Dv3_DhS_S_( +// CHECK-SAME: <3 x half> noundef nofpclass(nan inf) [[MIN:%.*]], <3 x half> noundef nofpclass(nan inf) [[MAX:%.*]], <3 x half> noundef nofpclass(nan inf) [[X:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[SUB_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn <3 x half> [[X]], [[MIN]] +// CHECK-NEXT: [[SUB1_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn <3 x half> [[MAX]], [[MIN]] +// CHECK-NEXT: [[DIV_I:%.*]] = fdiv reassoc nnan ninf nsz arcp afn <3 x half> [[SUB_I]], [[SUB1_I]] +// CHECK-NEXT: [[HLSL_SATURATE_I:%.*]] = tail call reassoc nnan ninf nsz arcp afn <3 x half> @llvm.dx.saturate.v3f16(<3 x half> [[DIV_I]]) +// CHECK-NEXT: [[MUL_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn <3 x half> [[HLSL_SATURATE_I]], splat (half 0xH4000) +// CHECK-NEXT: [[SUB2_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn <3 x half> splat (half 0xH4200), [[MUL_I]] +// CHECK-NEXT: [[TMP0:%.*]] = fmul reassoc nnan ninf nsz arcp afn <3 x half> [[HLSL_SATURATE_I]], [[HLSL_SATURATE_I]] +// CHECK-NEXT: [[MUL4_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn <3 x half> [[TMP0]], [[SUB2_I]] +// CHECK-NEXT: ret <3 x half> [[MUL4_I]] +// +// SPVCHECK-LABEL: define spir_func noundef nofpclass(nan inf) <3 x half> @_Z21test_smoothstep_half3Dv3_DhS_S_( +// SPVCHECK-SAME: <3 x half> noundef nofpclass(nan inf) [[MIN:%.*]], <3 x half> noundef nofpclass(nan inf) [[MAX:%.*]], <3 x half> noundef nofpclass(nan inf) [[X:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SPVCHECK-NEXT: [[ENTRY:.*:]] +// SPVCHECK-NEXT: [[SPV_SMOOTHSTEP_I:%.*]] = tail call reassoc nnan ninf nsz arcp afn noundef <3 x half> @llvm.spv.smoothstep.v3f16(<3 x half> [[MIN]], <3 x half> [[MAX]], <3 x half> [[X]]) +// SPVCHECK-NEXT: ret <3 x half> [[SPV_SMOOTHSTEP_I]] +// +half3 test_smoothstep_half3(half3 Min, half3 Max, half3 X) { return smoothstep(Min, Max, X); } + +// CHECK-LABEL: define noundef nofpclass(nan inf) <4 x half> @_Z21test_smoothstep_half4Dv4_DhS_S_( +// CHECK-SAME: <4 x half> noundef nofpclass(nan inf) [[MIN:%.*]], <4 x half> noundef nofpclass(nan inf) [[MAX:%.*]], <4 x half> noundef nofpclass(nan inf) [[X:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[SUB_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn <4 x half> [[X]], [[MIN]] +// CHECK-NEXT: [[SUB1_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn <4 x half> [[MAX]], [[MIN]] +// CHECK-NEXT: [[DIV_I:%.*]] = fdiv reassoc nnan ninf nsz arcp afn <4 x half> [[SUB_I]], [[SUB1_I]] +// CHECK-NEXT: [[HLSL_SATURATE_I:%.*]] = tail call reassoc nnan ninf nsz arcp afn <4 x half> @llvm.dx.saturate.v4f16(<4 x half> [[DIV_I]]) +// CHECK-NEXT: [[MUL_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn <4 x half> [[HLSL_SATURATE_I]], splat (half 0xH4000) +// CHECK-NEXT: [[SUB2_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn <4 x half> splat (half 0xH4200), [[MUL_I]] +// CHECK-NEXT: [[TMP0:%.*]] = fmul reassoc nnan ninf nsz arcp afn <4 x half> [[HLSL_SATURATE_I]], [[HLSL_SATURATE_I]] +// CHECK-NEXT: [[MUL4_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn <4 x half> [[TMP0]], [[SUB2_I]] +// CHECK-NEXT: ret <4 x half> [[MUL4_I]] +// +// SPVCHECK-LABEL: define spir_func noundef nofpclass(nan inf) <4 x half> @_Z21test_smoothstep_half4Dv4_DhS_S_( +// SPVCHECK-SAME: <4 x half> noundef nofpclass(nan inf) [[MIN:%.*]], <4 x half> noundef nofpclass(nan inf) [[MAX:%.*]], <4 x half> noundef nofpclass(nan inf) [[X:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SPVCHECK-NEXT: [[ENTRY:.*:]] +// SPVCHECK-NEXT: [[SPV_SMOOTHSTEP_I:%.*]] = tail call reassoc nnan ninf nsz arcp afn noundef <4 x half> @llvm.spv.smoothstep.v4f16(<4 x half> [[MIN]], <4 x half> [[MAX]], <4 x half> [[X]]) +// SPVCHECK-NEXT: ret <4 x half> [[SPV_SMOOTHSTEP_I]] +// +half4 test_smoothstep_half4(half4 Min, half4 Max, half4 X) { return smoothstep(Min, Max, X); } + +// CHECK-LABEL: define noundef nofpclass(nan inf) float @_Z21test_smoothstep_floatfff( +// CHECK-SAME: float noundef nofpclass(nan inf) [[MIN:%.*]], float noundef nofpclass(nan inf) [[MAX:%.*]], float noundef nofpclass(nan inf) [[X:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[SUB_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn float [[X]], [[MIN]] +// CHECK-NEXT: [[SUB1_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn float [[MAX]], [[MIN]] +// CHECK-NEXT: [[DIV_I:%.*]] = fdiv reassoc nnan ninf nsz arcp afn float [[SUB_I]], [[SUB1_I]] +// CHECK-NEXT: [[HLSL_SATURATE_I:%.*]] = tail call reassoc nnan ninf nsz arcp afn float @llvm.dx.saturate.f32(float [[DIV_I]]) +// CHECK-NEXT: [[MUL_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[HLSL_SATURATE_I]], 2.000000e+00 +// CHECK-NEXT: [[SUB2_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn float 3.000000e+00, [[MUL_I]] +// CHECK-NEXT: [[TMP0:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[HLSL_SATURATE_I]], [[HLSL_SATURATE_I]] +// CHECK-NEXT: [[MUL4_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[TMP0]], [[SUB2_I]] +// CHECK-NEXT: ret float [[MUL4_I]] +// +// SPVCHECK-LABEL: define spir_func noundef nofpclass(nan inf) float @_Z21test_smoothstep_floatfff( +// SPVCHECK-SAME: float noundef nofpclass(nan inf) [[MIN:%.*]], float noundef nofpclass(nan inf) [[MAX:%.*]], float noundef nofpclass(nan inf) [[X:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SPVCHECK-NEXT: [[ENTRY:.*:]] +// SPVCHECK-NEXT: [[CONV_I:%.*]] = fpext reassoc nnan ninf nsz arcp afn float [[MIN]] to double +// SPVCHECK-NEXT: [[CONV1_I:%.*]] = fpext reassoc nnan ninf nsz arcp afn float [[MAX]] to double +// SPVCHECK-NEXT: [[CONV2_I:%.*]] = fpext reassoc nnan ninf nsz arcp afn float [[X]] to double +// 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]]) +// SPVCHECK-NEXT: [[CONV3_I:%.*]] = fptrunc reassoc nnan ninf nsz arcp afn double [[SPV_SMOOTHSTEP_I]] to float +// SPVCHECK-NEXT: ret float [[CONV3_I]] +// +float test_smoothstep_float(float Min, float Max, float X) { return smoothstep(Min, Max, X); } + +// CHECK-LABEL: define noundef nofpclass(nan inf) <2 x float> @_Z22test_smoothstep_float2Dv2_fS_S_( +// CHECK-SAME: <2 x float> noundef nofpclass(nan inf) [[MIN:%.*]], <2 x float> noundef nofpclass(nan inf) [[MAX:%.*]], <2 x float> noundef nofpclass(nan inf) [[X:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[SUB_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn <2 x float> [[X]], [[MIN]] +// CHECK-NEXT: [[SUB1_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn <2 x float> [[MAX]], [[MIN]] +// CHECK-NEXT: [[DIV_I:%.*]] = fdiv reassoc nnan ninf nsz arcp afn <2 x float> [[SUB_I]], [[SUB1_I]] +// CHECK-NEXT: [[HLSL_SATURATE_I:%.*]] = tail call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.dx.saturate.v2f32(<2 x float> [[DIV_I]]) +// CHECK-NEXT: [[MUL_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn <2 x float> [[HLSL_SATURATE_I]], splat (float 2.000000e+00) +// CHECK-NEXT: [[SUB2_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn <2 x float> splat (float 3.000000e+00), [[MUL_I]] +// CHECK-NEXT: [[TMP0:%.*]] = fmul reassoc nnan ninf nsz arcp afn <2 x float> [[HLSL_SATURATE_I]], [[HLSL_SATURATE_I]] +// CHECK-NEXT: [[MUL4_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn <2 x float> [[TMP0]], [[SUB2_I]] +// CHECK-NEXT: ret <2 x float> [[MUL4_I]] +// +// SPVCHECK-LABEL: define spir_func noundef nofpclass(nan inf) <2 x float> @_Z22test_smoothstep_float2Dv2_fS_S_( +// SPVCHECK-SAME: <2 x float> noundef nofpclass(nan inf) [[MIN:%.*]], <2 x float> noundef nofpclass(nan inf) [[MAX:%.*]], <2 x float> noundef nofpclass(nan inf) [[X:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SPVCHECK-NEXT: [[ENTRY:.*:]] +// SPVCHECK-NEXT: [[SPV_SMOOTHSTEP_I:%.*]] = tail call reassoc nnan ninf nsz arcp afn noundef <2 x float> @llvm.spv.smoothstep.v2f32(<2 x float> [[MIN]], <2 x float> [[MAX]], <2 x float> [[X]]) +// SPVCHECK-NEXT: ret <2 x float> [[SPV_SMOOTHSTEP_I]] +// +float2 test_smoothstep_float2(float2 Min, float2 Max, float2 X) { return smoothstep(Min, Max, X); } + +// CHECK-LABEL: define noundef nofpclass(nan inf) <3 x float> @_Z22test_smoothstep_float3Dv3_fS_S_( +// CHECK-SAME: <3 x float> noundef nofpclass(nan inf) [[MIN:%.*]], <3 x float> noundef nofpclass(nan inf) [[MAX:%.*]], <3 x float> noundef nofpclass(nan inf) [[X:%.*]]) local_unnamed_addr ... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/132288 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits