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

Reply via email to