[clang] [llvm] [HLSL] Implement ddx/ddy_coarse intrinsics (PR #164831)
Alexander Johnston via llvm-commits
llvm-commits at lists.llvm.org
Thu Oct 23 10:30:37 PDT 2025
https://github.com/Alexander-Johnston updated https://github.com/llvm/llvm-project/pull/164831
>From 120e88999b8f11971fc7848121eebef1b3c15fee Mon Sep 17 00:00:00 2001
From: Alexander Johnston <alexander.johnston at amd.com>
Date: Thu, 23 Oct 2025 15:12:23 +0100
Subject: [PATCH 1/4] [HLSL] Implement ddx/ddy_coarse intrinsics
---
clang/include/clang/Basic/Builtins.td | 12 +++
clang/include/clang/Basic/BuiltinsSPIRVVK.td | 2 +
clang/lib/CodeGen/CGHLSLBuiltins.cpp | 18 +++++
clang/lib/CodeGen/CGHLSLRuntime.h | 2 +
clang/lib/CodeGen/TargetBuiltins/SPIR.cpp | 12 +++
.../lib/Headers/hlsl/hlsl_intrinsic_helpers.h | 16 ++++
clang/lib/Headers/hlsl/hlsl_intrinsics.h | 76 +++++++++++++++++++
clang/lib/Sema/SemaHLSL.cpp | 4 +-
clang/lib/Sema/SemaSPIRV.cpp | 26 +++++++
.../builtins/ddx-coarse-builtin.hlsl | 17 +++++
.../test/CodeGenHLSL/builtins/ddx-coarse.hlsl | 61 +++++++++++++++
.../builtins/ddy-coarse-builtin.hlsl | 17 +++++
.../test/CodeGenHLSL/builtins/ddy-coarse.hlsl | 61 +++++++++++++++
.../SemaHLSL/BuiltIns/ddx-coarse-errors.hlsl | 23 ++++++
.../SemaHLSL/BuiltIns/ddy-coarse-errors.hlsl | 21 +++++
.../SemaSPIRV/BuiltIns/ddx-coarse-errors.c | 29 +++++++
.../SemaSPIRV/BuiltIns/ddy-coarse-errors.c | 29 +++++++
llvm/include/llvm/IR/IntrinsicsDirectX.td | 2 +
llvm/include/llvm/IR/IntrinsicsSPIRV.td | 2 +
llvm/lib/Target/DirectX/DXIL.td | 18 +++++
.../DirectX/DirectXTargetTransformInfo.cpp | 2 +
.../Target/SPIRV/SPIRVInstructionSelector.cpp | 14 ++++
.../test/CodeGen/DirectX/ddx_coarse-errors.ll | 15 ++++
llvm/test/CodeGen/DirectX/ddx_coarse.ll | 41 ++++++++++
.../test/CodeGen/DirectX/ddy_coarse-errors.ll | 15 ++++
llvm/test/CodeGen/DirectX/ddy_coarse.ll | 41 ++++++++++
.../SPIRV/hlsl-intrinsics/ddx_coarse.ll | 43 +++++++++++
.../SPIRV/hlsl-intrinsics/ddy_coarse.ll | 43 +++++++++++
28 files changed, 661 insertions(+), 1 deletion(-)
create mode 100644 clang/test/CodeGenHLSL/builtins/ddx-coarse-builtin.hlsl
create mode 100644 clang/test/CodeGenHLSL/builtins/ddx-coarse.hlsl
create mode 100644 clang/test/CodeGenHLSL/builtins/ddy-coarse-builtin.hlsl
create mode 100644 clang/test/CodeGenHLSL/builtins/ddy-coarse.hlsl
create mode 100644 clang/test/SemaHLSL/BuiltIns/ddx-coarse-errors.hlsl
create mode 100644 clang/test/SemaHLSL/BuiltIns/ddy-coarse-errors.hlsl
create mode 100644 clang/test/SemaSPIRV/BuiltIns/ddx-coarse-errors.c
create mode 100644 clang/test/SemaSPIRV/BuiltIns/ddy-coarse-errors.c
create mode 100644 llvm/test/CodeGen/DirectX/ddx_coarse-errors.ll
create mode 100644 llvm/test/CodeGen/DirectX/ddx_coarse.ll
create mode 100644 llvm/test/CodeGen/DirectX/ddy_coarse-errors.ll
create mode 100644 llvm/test/CodeGen/DirectX/ddy_coarse.ll
create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/ddx_coarse.ll
create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/ddy_coarse.ll
diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index a2c202158522f..31f0c29d4c8b7 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -5229,6 +5229,18 @@ def HLSLGetSpirvSpecConstant : LangBuiltin<"HLSL_LANG">, HLSLScalarTemplate {
let Prototype = "T(unsigned int, T)";
}
+def HLSLDdxCoarse : LangBuiltin<"HLSL_LANG"> {
+ let Spellings = ["__builtin_hlsl_elementwise_ddx_coarse"];
+ let Attributes = [NoThrow, Const, CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
+def HLSLDdyCoarse : LangBuiltin<"HLSL_LANG"> {
+ let Spellings = ["__builtin_hlsl_elementwise_ddy_coarse"];
+ let Attributes = [NoThrow, Const, CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
// Builtins for XRay.
def XRayCustomEvent : Builtin {
let Spellings = ["__xray_customevent"];
diff --git a/clang/include/clang/Basic/BuiltinsSPIRVVK.td b/clang/include/clang/Basic/BuiltinsSPIRVVK.td
index 5dc3c7588cd2a..96e7c7b11fdfd 100644
--- a/clang/include/clang/Basic/BuiltinsSPIRVVK.td
+++ b/clang/include/clang/Basic/BuiltinsSPIRVVK.td
@@ -12,3 +12,5 @@ include "clang/Basic/BuiltinsSPIRVBase.td"
def reflect : SPIRVBuiltin<"void(...)", [NoThrow, Const]>;
def faceforward : SPIRVBuiltin<"void(...)", [NoThrow, Const, CustomTypeChecking]>;
def refract : SPIRVBuiltin<"void(...)", [NoThrow, Const, CustomTypeChecking]>;
+def ddx_coarse : SPIRVBuiltin<"void(...)", [NoThrow, Const, CustomTypeChecking]>;
+def ddy_coarse : SPIRVBuiltin<"void(...)", [NoThrow, Const, CustomTypeChecking]>;
diff --git a/clang/lib/CodeGen/CGHLSLBuiltins.cpp b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
index 384bd59e7533a..8abc15b53d8c1 100644
--- a/clang/lib/CodeGen/CGHLSLBuiltins.cpp
+++ b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
@@ -840,6 +840,24 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
return EmitRuntimeCall(
Intrinsic::getOrInsertDeclaration(&CGM.getModule(), ID));
}
+ case Builtin::BI__builtin_hlsl_elementwise_ddx_coarse: {
+ Value *Op0 = EmitScalarExpr(E->getArg(0));
+ if (!E->getArg(0)->getType()->hasFloatingRepresentation())
+ llvm_unreachable("ddx_coarse operand must have a float representation");
+ Intrinsic::ID ID = CGM.getHLSLRuntime().getDdxCoarseIntrinsic();
+ return Builder.CreateIntrinsic(/*ReturnType=*/Op0->getType(), ID,
+ ArrayRef<Value *>{Op0}, nullptr,
+ "hlsl.ddx.coarse");
+ }
+ case Builtin::BI__builtin_hlsl_elementwise_ddy_coarse: {
+ Value *Op0 = EmitScalarExpr(E->getArg(0));
+ if (!E->getArg(0)->getType()->hasFloatingRepresentation())
+ llvm_unreachable("ddy_coarse operand must have a float representation");
+ Intrinsic::ID ID = CGM.getHLSLRuntime().getDdyCoarseIntrinsic();
+ return Builder.CreateIntrinsic(/*ReturnType=*/Op0->getType(), ID,
+ ArrayRef<Value *>{Op0}, nullptr,
+ "hlsl.ddy.coarse");
+ }
case Builtin::BI__builtin_get_spirv_spec_constant_bool:
case Builtin::BI__builtin_get_spirv_spec_constant_short:
case Builtin::BI__builtin_get_spirv_spec_constant_ushort:
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h
index d35df524fdc84..a13022cae9d37 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -136,6 +136,8 @@ class CGHLSLRuntime {
GENERATE_HLSL_INTRINSIC_FUNCTION(GroupMemoryBarrierWithGroupSync,
group_memory_barrier_with_group_sync)
GENERATE_HLSL_INTRINSIC_FUNCTION(GetDimensionsX, resource_getdimensions_x)
+ GENERATE_HLSL_INTRINSIC_FUNCTION(DdxCoarse, ddx_coarse)
+ GENERATE_HLSL_INTRINSIC_FUNCTION(DdyCoarse, ddy_coarse)
//===----------------------------------------------------------------------===//
// End of reserved area for HLSL intrinsic getters.
diff --git a/clang/lib/CodeGen/TargetBuiltins/SPIR.cpp b/clang/lib/CodeGen/TargetBuiltins/SPIR.cpp
index 243aad8bf7083..12937fe8c0d10 100644
--- a/clang/lib/CodeGen/TargetBuiltins/SPIR.cpp
+++ b/clang/lib/CodeGen/TargetBuiltins/SPIR.cpp
@@ -151,6 +151,18 @@ Value *CodeGenFunction::EmitSPIRVBuiltinExpr(unsigned BuiltinID,
Intrinsic::spv_global_offset,
ArrayRef<Value *>{EmitScalarExpr(E->getArg(0))}, nullptr,
"spv.global.offset");
+ case SPIRV::BI__builtin_spirv_ddx_coarse:
+ return Builder.CreateIntrinsic(
+ /*ReturnType=*/getTypes().ConvertType(E->getType()),
+ Intrinsic::spv_ddx_coarse,
+ ArrayRef<Value *>{EmitScalarExpr(E->getArg(0))}, nullptr,
+ "spv.ddx.coarse");
+ case SPIRV::BI__builtin_spirv_ddy_coarse:
+ return Builder.CreateIntrinsic(
+ /*ReturnType=*/getTypes().ConvertType(E->getType()),
+ Intrinsic::spv_ddy_coarse,
+ ArrayRef<Value *>{EmitScalarExpr(E->getArg(0))}, nullptr,
+ "spv.ddy.coarse");
}
return nullptr;
}
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h b/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h
index c877234479ad1..e3f5c5dbfa8d1 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h
@@ -148,6 +148,22 @@ template <typename T> constexpr T ldexp_impl(T X, T Exp) {
return exp2(Exp) * X;
}
+template <typename T> constexpr T ddx_coarse_impl(T value) {
+#if (__has_builtin(__builtin_spirv_ddx_coarse))
+ return __builtin_spirv_ddx_coarse(value);
+#else
+ return __builtin_hlsl_elementwise_ddx_coarse(value);
+#endif
+}
+
+template <typename T> constexpr T ddy_coarse_impl(T value) {
+#if (__has_builtin(__builtin_spirv_ddy_coarse))
+ return __builtin_spirv_ddy_coarse(value);
+#else
+ return __builtin_hlsl_elementwise_ddy_coarse(value);
+#endif
+}
+
} // namespace __detail
} // namespace hlsl
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
index 5ba5bfb9abde0..9fac001be1572 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
@@ -605,5 +605,81 @@ smoothstep(__detail::HLSL_FIXED_VECTOR<float, N> Min,
return __detail::smoothstep_vec_impl(Min, Max, X);
}
+//===----------------------------------------------------------------------===//
+// ddx_coarse builtin
+//===----------------------------------------------------------------------===//
+
+/// \fn T ddx_coarse(T value)
+/// \brief Computes a low precision partial derivative with respect to the
+/// screen-space x-coordinate.
+/// \param value The input value.
+///
+/// The return value is a floating point scalar or vector containing the low
+/// prevision partial derivative of the input value.
+
+template <typename T>
+const inline __detail::enable_if_t<
+ __detail::is_arithmetic<T>::Value && __detail::is_same<half, T>::value, T>
+ddx_coarse(T value) {
+ return __detail::ddx_coarse_impl(value);
+}
+
+template <typename T>
+const inline __detail::enable_if_t<
+ __detail::is_arithmetic<T>::Value && __detail::is_same<float, T>::value, T>
+ddx_coarse(T value) {
+ return __detail::ddx_coarse_impl(value);
+}
+
+template <int L>
+const inline __detail::HLSL_FIXED_VECTOR<half, L>
+ddx_coarse(__detail::HLSL_FIXED_VECTOR<half, L> value) {
+ return __detail::ddx_coarse_impl(value);
+}
+
+template <int L>
+const inline __detail::HLSL_FIXED_VECTOR<float, L>
+ddx_coarse(__detail::HLSL_FIXED_VECTOR<float, L> value) {
+ return __detail::ddx_coarse_impl(value);
+}
+
+//===----------------------------------------------------------------------===//
+// ddy_coarse builtin
+//===----------------------------------------------------------------------===//
+
+/// \fn T ddy_coarse(T value)
+/// \brief Computes a low precision partial derivative with respect to the
+/// screen-space y-coordinate.
+/// \param value The input value.
+///
+/// The return value is a floating point scalar or vector containing the low
+/// prevision partial derivative of the input value.
+
+template <typename T>
+const inline __detail::enable_if_t<
+ __detail::is_arithmetic<T>::Value && __detail::is_same<half, T>::value, T>
+ddy_coarse(T value) {
+ return __detail::ddy_coarse_impl(value);
+}
+
+template <typename T>
+const inline __detail::enable_if_t<
+ __detail::is_arithmetic<T>::Value && __detail::is_same<float, T>::value, T>
+ddy_coarse(T value) {
+ return __detail::ddy_coarse_impl(value);
+}
+
+template <int L>
+const inline __detail::HLSL_FIXED_VECTOR<half, L>
+ddy_coarse(__detail::HLSL_FIXED_VECTOR<half, L> value) {
+ return __detail::ddy_coarse_impl(value);
+}
+
+template <int L>
+const inline __detail::HLSL_FIXED_VECTOR<float, L>
+ddy_coarse(__detail::HLSL_FIXED_VECTOR<float, L> value) {
+ return __detail::ddy_coarse_impl(value);
+}
+
} // namespace hlsl
#endif //_HLSL_HLSL_INTRINSICS_H_
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 2a485da06908d..b717f6706068f 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -3202,7 +3202,9 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
case Builtin::BI__builtin_hlsl_elementwise_degrees:
case Builtin::BI__builtin_hlsl_elementwise_radians:
case Builtin::BI__builtin_hlsl_elementwise_rsqrt:
- case Builtin::BI__builtin_hlsl_elementwise_frac: {
+ case Builtin::BI__builtin_hlsl_elementwise_frac:
+ case Builtin::BI__builtin_hlsl_elementwise_ddx_coarse:
+ case Builtin::BI__builtin_hlsl_elementwise_ddy_coarse: {
if (SemaRef.checkArgCount(TheCall, 1))
return true;
if (CheckAllArgTypesAreCorrect(&SemaRef, TheCall,
diff --git a/clang/lib/Sema/SemaSPIRV.cpp b/clang/lib/Sema/SemaSPIRV.cpp
index c8ea0d09c4081..0e2bb1f3c1900 100644
--- a/clang/lib/Sema/SemaSPIRV.cpp
+++ b/clang/lib/Sema/SemaSPIRV.cpp
@@ -46,6 +46,19 @@ static bool CheckAllArgsHaveSameType(Sema *S, CallExpr *TheCall) {
return false;
}
+static bool CheckAllArgTypesAreCorrect(
+ Sema *S, CallExpr *TheCall,
+ llvm::function_ref<bool(Sema *S, SourceLocation Loc, int ArgOrdinal,
+ clang::QualType PassedType)>
+ Check) {
+ for (unsigned I = 0; I < TheCall->getNumArgs(); ++I) {
+ Expr *Arg = TheCall->getArg(I);
+ if (Check(S, Arg->getBeginLoc(), I + 1, Arg->getType()))
+ return true;
+ }
+ return false;
+}
+
static bool CheckAllArgTypesAreCorrect(
Sema *S, CallExpr *TheCall,
llvm::ArrayRef<
@@ -360,6 +373,19 @@ bool SemaSPIRV::CheckSPIRVBuiltinFunctionCall(const TargetInfo &TI,
case SPIRV::BI__builtin_spirv_generic_cast_to_ptr_explicit: {
return checkGenericCastToPtr(SemaRef, TheCall);
}
+ case SPIRV::BI__builtin_spirv_ddx_coarse:
+ case SPIRV::BI__builtin_spirv_ddy_coarse: {
+ if (SemaRef.checkArgCount(TheCall, 1))
+ return true;
+
+ if (CheckAllArgTypesAreCorrect(&SemaRef, TheCall,
+ CheckFloatOrHalfRepresentation))
+ return true;
+
+ QualType RetTy = TheCall->getArg(0)->getType();
+ TheCall->setType(RetTy);
+ break;
+ }
}
return false;
}
diff --git a/clang/test/CodeGenHLSL/builtins/ddx-coarse-builtin.hlsl b/clang/test/CodeGenHLSL/builtins/ddx-coarse-builtin.hlsl
new file mode 100644
index 0000000000000..36d9d5969a59b
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/ddx-coarse-builtin.hlsl
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
+// RUN: FileCheck %s --check-prefixes=CHECK
+
+// CHECK: define hidden noundef nofpclass(nan inf) half @
+// CHECK: %hlsl.ddx.coarse = call reassoc nnan ninf nsz arcp afn half @llvm.dx.ddx.coarse.f16(half %{{.*}})
+// CHECK: ret half %hlsl.ddx.coarse
+half test_f16_ddx_coarse(half val) {
+ return __builtin_hlsl_elementwise_ddx_coarse(val);
+}
+
+// CHECK: define hidden noundef nofpclass(nan inf) float @
+// CHECK: %hlsl.ddx.coarse = call reassoc nnan ninf nsz arcp afn float @llvm.dx.ddx.coarse.f32(float %{{.*}})
+// CHECK: ret float %hlsl.ddx.coarse
+float test_f32_ddx_coarse(float val) {
+ return __builtin_hlsl_elementwise_ddx_coarse(val);
+}
\ No newline at end of file
diff --git a/clang/test/CodeGenHLSL/builtins/ddx-coarse.hlsl b/clang/test/CodeGenHLSL/builtins/ddx-coarse.hlsl
new file mode 100644
index 0000000000000..aedcb9b6e08cd
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/ddx-coarse.hlsl
@@ -0,0 +1,61 @@
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
+// RUN: FileCheck %s --check-prefixes=CHECK
+
+using hlsl::ddx_coarse;
+
+// CHECK: define linkonce_odr hidden noundef nofpclass(nan inf) half @
+// CHECK: %hlsl.ddx.coarse = call reassoc nnan ninf nsz arcp afn half @llvm.dx.ddx.coarse.f16(half %{{.*}})
+// CHECK: ret half %hlsl.ddx.coarse
+half test_f16_ddx_coarse(half val) {
+ return ddx_coarse(val);
+}
+
+// CHECK: define linkonce_odr hidden noundef nofpclass(nan inf) <2 x half> @
+// CHECK: %hlsl.ddx.coarse = call reassoc nnan ninf nsz arcp afn <2 x half> @llvm.dx.ddx.coarse.v2f16(<2 x half> %{{.*}})
+// CHECK: ret <2 x half> %hlsl.ddx.coarse
+half2 test_f16_ddx_coarse2(half2 val) {
+ return ddx_coarse(val);
+}
+
+// CHECK: define linkonce_odr hidden noundef nofpclass(nan inf) <3 x half> @
+// CHECK: %hlsl.ddx.coarse = call reassoc nnan ninf nsz arcp afn <3 x half> @llvm.dx.ddx.coarse.v3f16(<3 x half> %{{.*}})
+// CHECK: ret <3 x half> %hlsl.ddx.coarse
+half3 test_f16_ddx_coarse3(half3 val) {
+ return ddx_coarse(val);
+}
+
+// CHECK: define linkonce_odr hidden noundef nofpclass(nan inf) <4 x half> @
+// CHECK: %hlsl.ddx.coarse = call reassoc nnan ninf nsz arcp afn <4 x half> @llvm.dx.ddx.coarse.v4f16(<4 x half> %{{.*}})
+// CHECK: ret <4 x half> %hlsl.ddx.coarse
+half4 test_f16_ddx_coarse4(half4 val) {
+ return ddx_coarse(val);
+}
+
+// CHECK: define linkonce_odr hidden noundef nofpclass(nan inf) float @
+// CHECK: %hlsl.ddx.coarse = call reassoc nnan ninf nsz arcp afn float @llvm.dx.ddx.coarse.f32(float %{{.*}})
+// CHECK: ret float %hlsl.ddx.coarse
+float test_f32_ddx_coarse(float val) {
+ return ddx_coarse(val);
+}
+
+// CHECK: define linkonce_odr hidden noundef nofpclass(nan inf) <2 x float> @
+// CHECK: %hlsl.ddx.coarse = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.dx.ddx.coarse.v2f32(<2 x float> %{{.*}})
+// CHECK: ret <2 x float> %hlsl.ddx.coarse
+float2 test_f32_ddx_coarse2(float2 val) {
+ return ddx_coarse(val);
+}
+
+// CHECK: define linkonce_odr hidden noundef nofpclass(nan inf) <3 x float> @
+// CHECK: %hlsl.ddx.coarse = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.dx.ddx.coarse.v3f32(<3 x float> %{{.*}})
+// CHECK: ret <3 x float> %hlsl.ddx.coarse
+float3 test_f32_ddx_coarse3(float3 val) {
+ return ddx_coarse(val);
+}
+
+// CHECK: define linkonce_odr hidden noundef nofpclass(nan inf) <4 x float> @
+// CHECK: %hlsl.ddx.coarse = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.dx.ddx.coarse.v4f32(<4 x float> %{{.*}})
+// CHECK: ret <4 x float> %hlsl.ddx.coarse
+float4 test_f32_ddx_coarse4(float4 val) {
+ return ddx_coarse(val);
+}
diff --git a/clang/test/CodeGenHLSL/builtins/ddy-coarse-builtin.hlsl b/clang/test/CodeGenHLSL/builtins/ddy-coarse-builtin.hlsl
new file mode 100644
index 0000000000000..5f69699ff7bd6
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/ddy-coarse-builtin.hlsl
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
+// RUN: FileCheck %s --check-prefixes=CHECK
+
+// CHECK: define hidden noundef nofpclass(nan inf) half @
+// CHECK: %hlsl.ddy.coarse = call reassoc nnan ninf nsz arcp afn half @llvm.dx.ddy.coarse.f16(half %{{.*}})
+// CHECK: ret half %hlsl.ddy.coarse
+half test_f16_ddy_coarse(half val) {
+ return __builtin_hlsl_elementwise_ddy_coarse(val);
+}
+
+// CHECK: define hidden noundef nofpclass(nan inf) float @
+// CHECK: %hlsl.ddy.coarse = call reassoc nnan ninf nsz arcp afn float @llvm.dx.ddy.coarse.f32(float %{{.*}})
+// CHECK: ret float %hlsl.ddy.coarse
+float test_f32_ddy_coarse(float val) {
+ return __builtin_hlsl_elementwise_ddy_coarse(val);
+}
\ No newline at end of file
diff --git a/clang/test/CodeGenHLSL/builtins/ddy-coarse.hlsl b/clang/test/CodeGenHLSL/builtins/ddy-coarse.hlsl
new file mode 100644
index 0000000000000..5428930d519ab
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/ddy-coarse.hlsl
@@ -0,0 +1,61 @@
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
+// RUN: FileCheck %s --check-prefixes=CHECK
+
+using hlsl::ddy_coarse;
+
+// CHECK: define linkonce_odr hidden noundef nofpclass(nan inf) half @
+// CHECK: %hlsl.ddy.coarse = call reassoc nnan ninf nsz arcp afn half @llvm.dx.ddy.coarse.f16(half %{{.*}})
+// CHECK: ret half %hlsl.ddy.coarse
+half test_f16_ddy_coarse(half val) {
+ return ddy_coarse(val);
+}
+
+// CHECK: define linkonce_odr hidden noundef nofpclass(nan inf) <2 x half> @
+// CHECK: %hlsl.ddy.coarse = call reassoc nnan ninf nsz arcp afn <2 x half> @llvm.dx.ddy.coarse.v2f16(<2 x half> %{{.*}})
+// CHECK: ret <2 x half> %hlsl.ddy.coarse
+half2 test_f16_ddy_coarse2(half2 val) {
+ return ddy_coarse(val);
+}
+
+// CHECK: define linkonce_odr hidden noundef nofpclass(nan inf) <3 x half> @
+// CHECK: %hlsl.ddy.coarse = call reassoc nnan ninf nsz arcp afn <3 x half> @llvm.dx.ddy.coarse.v3f16(<3 x half> %{{.*}})
+// CHECK: ret <3 x half> %hlsl.ddy.coarse
+half3 test_f16_ddy_coarse3(half3 val) {
+ return ddy_coarse(val);
+}
+
+// CHECK: define linkonce_odr hidden noundef nofpclass(nan inf) <4 x half> @
+// CHECK: %hlsl.ddy.coarse = call reassoc nnan ninf nsz arcp afn <4 x half> @llvm.dx.ddy.coarse.v4f16(<4 x half> %{{.*}})
+// CHECK: ret <4 x half> %hlsl.ddy.coarse
+half4 test_f16_ddy_coarse4(half4 val) {
+ return ddy_coarse(val);
+}
+
+// CHECK: define linkonce_odr hidden noundef nofpclass(nan inf) float @
+// CHECK: %hlsl.ddy.coarse = call reassoc nnan ninf nsz arcp afn float @llvm.dx.ddy.coarse.f32(float %{{.*}})
+// CHECK: ret float %hlsl.ddy.coarse
+float test_f32_ddy_coarse(float val) {
+ return ddy_coarse(val);
+}
+
+// CHECK: define linkonce_odr hidden noundef nofpclass(nan inf) <2 x float> @
+// CHECK: %hlsl.ddy.coarse = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.dx.ddy.coarse.v2f32(<2 x float> %{{.*}})
+// CHECK: ret <2 x float> %hlsl.ddy.coarse
+float2 test_f32_ddy_coarse2(float2 val) {
+ return ddy_coarse(val);
+}
+
+// CHECK: define linkonce_odr hidden noundef nofpclass(nan inf) <3 x float> @
+// CHECK: %hlsl.ddy.coarse = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.dx.ddy.coarse.v3f32(<3 x float> %{{.*}})
+// CHECK: ret <3 x float> %hlsl.ddy.coarse
+float3 test_f32_ddy_coarse3(float3 val) {
+ return ddy_coarse(val);
+}
+
+// CHECK: define linkonce_odr hidden noundef nofpclass(nan inf) <4 x float> @
+// CHECK: %hlsl.ddy.coarse = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.dx.ddy.coarse.v4f32(<4 x float> %{{.*}})
+// CHECK: ret <4 x float> %hlsl.ddy.coarse
+float4 test_f32_ddy_coarse4(float4 val) {
+ return ddy_coarse(val);
+}
diff --git a/clang/test/SemaHLSL/BuiltIns/ddx-coarse-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/ddx-coarse-errors.hlsl
new file mode 100644
index 0000000000000..48b717a4af11f
--- /dev/null
+++ b/clang/test/SemaHLSL/BuiltIns/ddx-coarse-errors.hlsl
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -verify
+
+typedef float float2 __attribute__((ext_vector_type(2)));
+
+float no_arg() {
+ return __builtin_hlsl_elementwise_ddx_coarse();
+ // expected-error at -1 {{too few arguments to function call, expected 1, have 0}}
+}
+
+float too_many_args(float val) {
+ return __builtin_hlsl_elementwise_ddx_coarse(val, val);
+ // expected-error at -1 {{too many arguments to function call, expected 1, have 2}}
+}
+
+float test_integer_scalar_input(int val) {
+ return __builtin_hlsl_elementwise_ddx_coarse(val);
+ // expected-error at -1 {{1st argument must be a scalar or vector of 16 or 32 bit floating-point types (was 'int')}}
+}
+
+double test_double_scalar_input(double val) {
+ return __builtin_hlsl_elementwise_ddx_coarse(val);
+ // expected-error at -1 {{1st argument must be a scalar or vector of 16 or 32 bit floating-point types (was 'double')}}
+}
\ No newline at end of file
diff --git a/clang/test/SemaHLSL/BuiltIns/ddy-coarse-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/ddy-coarse-errors.hlsl
new file mode 100644
index 0000000000000..c9e9d17757f25
--- /dev/null
+++ b/clang/test/SemaHLSL/BuiltIns/ddy-coarse-errors.hlsl
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -verify
+
+float no_arg() {
+ return __builtin_hlsl_elementwise_ddy_coarse();
+ // expected-error at -1 {{too few arguments to function call, expected 1, have 0}}
+}
+
+float too_many_args(float val) {
+ return __builtin_hlsl_elementwise_ddy_coarse(val, val);
+ // expected-error at -1 {{too many arguments to function call, expected 1, have 2}}
+}
+
+float test_integer_scalar_input(int val) {
+ return __builtin_hlsl_elementwise_ddy_coarse(val);
+ // expected-error at -1 {{1st argument must be a scalar or vector of 16 or 32 bit floating-point types (was 'int')}}
+}
+
+double test_double_scalar_input(double val) {
+ return __builtin_hlsl_elementwise_ddy_coarse(val);
+ // expected-error at -1 {{1st argument must be a scalar or vector of 16 or 32 bit floating-point types (was 'double')}}
+}
\ No newline at end of file
diff --git a/clang/test/SemaSPIRV/BuiltIns/ddx-coarse-errors.c b/clang/test/SemaSPIRV/BuiltIns/ddx-coarse-errors.c
new file mode 100644
index 0000000000000..d4f37100f6ce2
--- /dev/null
+++ b/clang/test/SemaSPIRV/BuiltIns/ddx-coarse-errors.c
@@ -0,0 +1,29 @@
+/// RUN: %clang_cc1 %s -triple spirv-pc-vulkan-compute -verify
+
+typedef _Float16 half;
+typedef float float2 __attribute__((ext_vector_type(2)));
+
+float no_arg() {
+ return __builtin_spirv_ddx_coarse();
+ // expected-error at -1 {{too few arguments to function call, expected 1, have 0}}
+}
+
+float too_many_args(float val) {
+ return __builtin_spirv_ddx_coarse(val, val);
+ // expected-error at -1 {{too many arguments to function call, expected 1, have 2}}
+}
+
+float mismatched_return(float2 val) {
+ return __builtin_spirv_ddx_coarse(val);
+ // expected-error at -1 {{returning 'float2' (vector of 2 'float' values) from a function with incompatible result type 'float'}}
+}
+
+float test_integer_scalar_input(int val) {
+ return __builtin_spirv_ddx_coarse(val);
+ // expected-error at -1 {{1st argument must be a scalar or vector of 16 or 32 bit floating-point types (was 'int')}}
+}
+
+double test_double_scalar_input(double val) {
+ return __builtin_spirv_ddx_coarse(val);
+ // expected-error at -1 {{1st argument must be a scalar or vector of 16 or 32 bit floating-point types (was 'double')}}
+}
\ No newline at end of file
diff --git a/clang/test/SemaSPIRV/BuiltIns/ddy-coarse-errors.c b/clang/test/SemaSPIRV/BuiltIns/ddy-coarse-errors.c
new file mode 100644
index 0000000000000..fc8c32f998ffd
--- /dev/null
+++ b/clang/test/SemaSPIRV/BuiltIns/ddy-coarse-errors.c
@@ -0,0 +1,29 @@
+/// RUN: %clang_cc1 %s -triple spirv-pc-vulkan-compute -verify
+
+typedef _Float16 half;
+typedef float float2 __attribute__((ext_vector_type(2)));
+
+float no_arg() {
+ return __builtin_spirv_ddy_coarse();
+ // expected-error at -1 {{too few arguments to function call, expected 1, have 0}}
+}
+
+float too_many_args(float val) {
+ return __builtin_spirv_ddy_coarse(val, val);
+ // expected-error at -1 {{too many arguments to function call, expected 1, have 2}}
+}
+
+float mismatched_return(float2 val) {
+ return __builtin_spirv_ddy_coarse(val);
+ // expected-error at -1 {{returning 'float2' (vector of 2 'float' values) from a function with incompatible result type 'float'}}
+}
+
+float test_integer_scalar_input(int val) {
+ return __builtin_spirv_ddy_coarse(val);
+ // expected-error at -1 {{1st argument must be a scalar or vector of 16 or 32 bit floating-point types (was 'int')}}
+}
+
+double test_double_scalar_input(double val) {
+ return __builtin_spirv_ddy_coarse(val);
+ // expected-error at -1 {{1st argument must be a scalar or vector of 16 or 32 bit floating-point types (was 'double')}}
+}
\ No newline at end of file
diff --git a/llvm/include/llvm/IR/IntrinsicsDirectX.td b/llvm/include/llvm/IR/IntrinsicsDirectX.td
index 3b7077c52db21..111f3e1754901 100644
--- a/llvm/include/llvm/IR/IntrinsicsDirectX.td
+++ b/llvm/include/llvm/IR/IntrinsicsDirectX.td
@@ -165,6 +165,8 @@ def int_dx_splitdouble : DefaultAttrsIntrinsic<[llvm_anyint_ty, LLVMMatchType<0>
[LLVMScalarOrSameVectorWidth<0, llvm_double_ty>], [IntrNoMem]>;
def int_dx_radians : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]>;
def int_dx_discard : DefaultAttrsIntrinsic<[], [llvm_i1_ty], []>;
+def int_dx_ddx_coarse : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]>;
+def int_dx_ddy_coarse : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]>;
def int_dx_firstbituhigh : DefaultAttrsIntrinsic<[LLVMScalarOrSameVectorWidth<0, llvm_i32_ty>], [llvm_anyint_ty], [IntrNoMem]>;
def int_dx_firstbitshigh : DefaultAttrsIntrinsic<[LLVMScalarOrSameVectorWidth<0, llvm_i32_ty>], [llvm_anyint_ty], [IntrNoMem]>;
def int_dx_firstbitlow : DefaultAttrsIntrinsic<[LLVMScalarOrSameVectorWidth<0, llvm_i32_ty>], [llvm_anyint_ty], [IntrNoMem]>;
diff --git a/llvm/include/llvm/IR/IntrinsicsSPIRV.td b/llvm/include/llvm/IR/IntrinsicsSPIRV.td
index 49a182be98acd..7865d473d2efc 100644
--- a/llvm/include/llvm/IR/IntrinsicsSPIRV.td
+++ b/llvm/include/llvm/IR/IntrinsicsSPIRV.td
@@ -132,6 +132,8 @@ def int_spv_rsqrt : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty]
def int_spv_group_memory_barrier_with_group_sync
: DefaultAttrsIntrinsic<[], [], [IntrConvergent]>;
def int_spv_discard : DefaultAttrsIntrinsic<[], [], []>;
+ def int_spv_ddx_coarse : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]>;
+ def int_spv_ddy_coarse : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]>;
def int_spv_uclamp : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>;
def int_spv_sclamp : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>;
def int_spv_nclamp : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>;
diff --git a/llvm/lib/Target/DirectX/DXIL.td b/llvm/lib/Target/DirectX/DXIL.td
index 44c48305f2832..95b9bc4078fbd 100644
--- a/llvm/lib/Target/DirectX/DXIL.td
+++ b/llvm/lib/Target/DirectX/DXIL.td
@@ -930,6 +930,24 @@ def Discard : DXILOp<82, discard> {
let stages = [Stages<DXIL1_0, [pixel]>];
}
+def DerivCoarseX : DXILOp<83, unary> {
+ let Doc = "computes the rate of change per stamp in x direction";
+ let intrinsics = [IntrinSelect<int_dx_ddx_coarse>];
+ let arguments = [OverloadTy];
+ let result = OverloadTy;
+ let overloads = [Overloads<DXIL1_0, [HalfTy, FloatTy]>];
+ let stages = [Stages<DXIL1_0, [library, pixel]>];
+}
+
+def DerivCoarseY : DXILOp<84, unary> {
+ let Doc = "computes the rate of change per stamp in y direction";
+ let intrinsics = [IntrinSelect<int_dx_ddy_coarse>];
+ let arguments = [OverloadTy];
+ let result = OverloadTy;
+ let overloads = [Overloads<DXIL1_0, [HalfTy, FloatTy]>];
+ let stages = [Stages<DXIL1_0, [library, pixel]>];
+}
+
def ThreadId : DXILOp<93, threadId> {
let Doc = "Reads the thread ID";
let intrinsics = [IntrinSelect<int_dx_thread_id>];
diff --git a/llvm/lib/Target/DirectX/DirectXTargetTransformInfo.cpp b/llvm/lib/Target/DirectX/DirectXTargetTransformInfo.cpp
index 68fd3e0bc74c7..7c5116abb7276 100644
--- a/llvm/lib/Target/DirectX/DirectXTargetTransformInfo.cpp
+++ b/llvm/lib/Target/DirectX/DirectXTargetTransformInfo.cpp
@@ -60,6 +60,8 @@ bool DirectXTTIImpl::isTargetIntrinsicTriviallyScalarizable(
case Intrinsic::dx_wave_reduce_usum:
case Intrinsic::dx_imad:
case Intrinsic::dx_umad:
+ case Intrinsic::dx_ddx_coarse:
+ case Intrinsic::dx_ddy_coarse:
return true;
default:
return false;
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index 021353ab716f7..fb96a66ebfff5 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -3472,6 +3472,20 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg,
case Intrinsic::spv_resource_nonuniformindex: {
return selectResourceNonUniformIndex(ResVReg, ResType, I);
}
+ case Intrinsic::spv_ddx_coarse: {
+ return BuildMI(*I.getParent(), I, I.getDebugLoc(),
+ TII.get(SPIRV::OpDPdxCoarse))
+ .addDef(ResVReg)
+ .addUse(GR.getSPIRVTypeID(ResType))
+ .addUse(I.getOperand(2).getReg());
+ }
+ case Intrinsic::spv_ddy_coarse: {
+ return BuildMI(*I.getParent(), I, I.getDebugLoc(),
+ TII.get(SPIRV::OpDPdyCoarse))
+ .addDef(ResVReg)
+ .addUse(GR.getSPIRVTypeID(ResType))
+ .addUse(I.getOperand(2).getReg());
+ }
default: {
std::string DiagMsg;
raw_string_ostream OS(DiagMsg);
diff --git a/llvm/test/CodeGen/DirectX/ddx_coarse-errors.ll b/llvm/test/CodeGen/DirectX/ddx_coarse-errors.ll
new file mode 100644
index 0000000000000..2cf0d1db27efe
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/ddx_coarse-errors.ll
@@ -0,0 +1,15 @@
+; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s 2>&1 | FileCheck %s
+
+; DXIL operation ddx.coarse does not support double overload type
+; CHECK: in function ddx.coarse
+; CHECK-SAME: Cannot create DerivCoarseX operation: Invalid overload type
+
+; Function Attrs: noinline nounwind optnone
+define noundef double @ddx.coarse_double(double noundef %a) #0 {
+entry:
+ %a.addr = alloca double, align 8
+ store double %a, ptr %a.addr, align 8
+ %0 = load double, ptr %a.addr, align 8
+ %dx.ddx.coarse = call double @llvm.dx.ddx.coarse.f64(double %0)
+ ret double %dx.ddx.coarse
+}
\ No newline at end of file
diff --git a/llvm/test/CodeGen/DirectX/ddx_coarse.ll b/llvm/test/CodeGen/DirectX/ddx_coarse.ll
new file mode 100644
index 0000000000000..bb4512a7a4341
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/ddx_coarse.ll
@@ -0,0 +1,41 @@
+; RUN: opt -S -scalarizer -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s
+
+; Make sure dxil operation function calls for fwidth are generated for half/float and matching vectors
+
+define noundef half @deriv_coarse_x_half(half noundef %a) {
+; CHECK: call half @dx.op.unary.f16(i32 83, half %{{.*}})
+entry:
+ %dx.ddx.coarse = call half @llvm.dx.ddx.coarse.f16(half %a)
+ ret half %dx.ddx.coarse
+}
+
+define noundef float @deriv_coarse_x_float(float noundef %a) {
+; CHECK: call float @dx.op.unary.f32(i32 83, float %{{.*}})
+entry:
+ %dx.ddx.coarse = call float @llvm.dx.ddx.coarse.f32(float %a)
+ ret float %dx.ddx.coarse
+}
+
+define noundef <4 x float> @deriv_coarse_x_float4(<4 x float> noundef %a) {
+; CHECK: [[ee0:%.*]] = extractelement <4 x float> %a, i64 0
+; CHECK: [[ie0:%.*]] = call float @dx.op.unary.f32(i32 83, float [[ee0]])
+; CHECK: [[ee1:%.*]] = extractelement <4 x float> %a, i64 1
+; CHECK: [[ie1:%.*]] = call float @dx.op.unary.f32(i32 83, float [[ee1]])
+; CHECK: [[ee2:%.*]] = extractelement <4 x float> %a, i64 2
+; CHECK: [[ie2:%.*]] = call float @dx.op.unary.f32(i32 83, float [[ee2]])
+; CHECK: [[ee3:%.*]] = extractelement <4 x float> %a, i64 3
+; CHECK: [[ie3:%.*]] = call float @dx.op.unary.f32(i32 83, float [[ee3]])
+; CHECK: insertelement <4 x float> poison, float [[ie0]], i64 0
+; CHECK: insertelement <4 x float> %{{.*}}, float [[ie1]], i64 1
+; CHECK: insertelement <4 x float> %{{.*}}, float [[ie2]], i64 2
+; CHECK: insertelement <4 x float> %{{.*}}, float [[ie3]], i64 3
+; CHECK: ret <4 x float> %{{.*}}
+entry:
+ %dx.ddx.coarse = call <4 x float> @llvm.dx.ddx.coarse.v4f32(<4 x float> %a)
+ ret <4 x float> %dx.ddx.coarse
+}
+
+declare half @llvm.dx.ddx.coarse.f16(half)
+declare float @llvm.dx.ddx.coarse.f32(float)
+declare <4 x float> @llvm.dx.ddx.coarse.v4f32(<4 x float>)
+
diff --git a/llvm/test/CodeGen/DirectX/ddy_coarse-errors.ll b/llvm/test/CodeGen/DirectX/ddy_coarse-errors.ll
new file mode 100644
index 0000000000000..400969f21713c
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/ddy_coarse-errors.ll
@@ -0,0 +1,15 @@
+; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s 2>&1 | FileCheck %s
+
+; DXIL operation ddy.coarse does not support double overload type
+; CHECK: in function ddy.coarse
+; CHECK-SAME: Cannot create DerivCoarseY operation: Invalid overload type
+
+; Function Attrs: noinline nounwind optnone
+define noundef double @ddy.coarse_double(double noundef %a) #0 {
+entry:
+ %a.addr = alloca double, align 8
+ store double %a, ptr %a.addr, align 8
+ %0 = load double, ptr %a.addr, align 8
+ %dx.ddy.coarse = call double @llvm.dx.ddy.coarse.f64(double %0)
+ ret double %dx.ddy.coarse
+}
\ No newline at end of file
diff --git a/llvm/test/CodeGen/DirectX/ddy_coarse.ll b/llvm/test/CodeGen/DirectX/ddy_coarse.ll
new file mode 100644
index 0000000000000..7321fc1a80975
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/ddy_coarse.ll
@@ -0,0 +1,41 @@
+; RUN: opt -S -scalarizer -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s
+
+; Make sure dxil operation function calls for fwidth are generated for half/float and matching vectors
+
+define noundef half @deriv_coarse_y_half(half noundef %a) {
+; CHECK: call half @dx.op.unary.f16(i32 84, half %{{.*}})
+entry:
+ %dx.ddy.coarse = call half @llvm.dx.ddy.coarse.f16(half %a)
+ ret half %dx.ddy.coarse
+}
+
+define noundef float @deriv_coarse_y_float(float noundef %a) {
+; CHECK: call float @dx.op.unary.f32(i32 84, float %{{.*}})
+entry:
+ %dx.ddy.coarse = call float @llvm.dx.ddy.coarse.f32(float %a)
+ ret float %dx.ddy.coarse
+}
+
+define noundef <4 x float> @deriv_coarse_y_float4(<4 x float> noundef %a) {
+; CHECK: [[ee0:%.*]] = extractelement <4 x float> %a, i64 0
+; CHECK: [[ie0:%.*]] = call float @dx.op.unary.f32(i32 84, float [[ee0]])
+; CHECK: [[ee1:%.*]] = extractelement <4 x float> %a, i64 1
+; CHECK: [[ie1:%.*]] = call float @dx.op.unary.f32(i32 84, float [[ee1]])
+; CHECK: [[ee2:%.*]] = extractelement <4 x float> %a, i64 2
+; CHECK: [[ie2:%.*]] = call float @dx.op.unary.f32(i32 84, float [[ee2]])
+; CHECK: [[ee3:%.*]] = extractelement <4 x float> %a, i64 3
+; CHECK: [[ie3:%.*]] = call float @dx.op.unary.f32(i32 84, float [[ee3]])
+; CHECK: insertelement <4 x float> poison, float [[ie0]], i64 0
+; CHECK: insertelement <4 x float> %{{.*}}, float [[ie1]], i64 1
+; CHECK: insertelement <4 x float> %{{.*}}, float [[ie2]], i64 2
+; CHECK: insertelement <4 x float> %{{.*}}, float [[ie3]], i64 3
+; CHECK: ret <4 x float> %{{.*}}
+entry:
+ %dx.ddy.coarse = call <4 x float> @llvm.dx.ddy.coarse.v4f32(<4 x float> %a)
+ ret <4 x float> %dx.ddy.coarse
+}
+
+declare half @llvm.dx.ddy.coarse.f16(half)
+declare float @llvm.dx.ddy.coarse.f32(float)
+declare <4 x float> @llvm.dx.ddy.coarse.v4f32(<4 x float>)
+
diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/ddx_coarse.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/ddx_coarse.ll
new file mode 100644
index 0000000000000..019c7b75ffe66
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/ddx_coarse.ll
@@ -0,0 +1,43 @@
+; RUN: llc -O0 -verify-machineinstrs -mtriple=spirv-unknown-vulkan %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-vulkan %s -o - -filetype=obj | spirv-val %}
+
+; CHECK-DAG: %[[#float_32:]] = OpTypeFloat 32
+; CHECK-DAG: %[[#float_16:]] = OpTypeFloat 16
+
+; CHECK-DAG: %[[#vec4_float_32:]] = OpTypeVector %[[#float_32]] 4
+; CHECK-DAG: %[[#vec4_float_16:]] = OpTypeVector %[[#float_16]] 4
+
+define noundef float @ddx_coarse_float(float noundef %a) {
+entry:
+; CHECK: %[[#float_32_arg:]] = OpFunctionParameter %[[#float_32]]
+; CHECK: %[[#]] = OpDPdxCoarse %[[#float_32]] %[[#float_32_arg]]
+ %elt.ddx.coarse = call float @llvm.spv.ddx.coarse.f32(float %a)
+ ret float %elt.ddx.coarse
+}
+
+define noundef half @ddx_coarse_half(half noundef %a) {
+entry:
+; CHECK: %[[#float_16_arg:]] = OpFunctionParameter %[[#float_16]]
+; CHECK: %[[#]] = OpDPdxCoarse %[[#float_16]] %[[#float_16_arg]]
+ %elt.ddx.coarse = call half @llvm.spv.ddx.coarse.f16(half %a)
+ ret half %elt.ddx.coarse
+}
+
+define noundef <4 x float> @ddx_coarse_float_vector(<4 x float> noundef %a) {
+entry:
+; CHECK: %[[#vec4_float_32_arg:]] = OpFunctionParameter %[[#vec4_float_32]]
+; CHECK: %[[#]] = OpDPdxCoarse %[[#vec4_float_32]] %[[#vec4_float_32_arg]]
+ %elt.ddx.coarse = call <4 x float> @llvm.spv.ddx.coarse.v4f32(<4 x float> %a)
+ ret <4 x float> %elt.ddx.coarse
+}
+
+define noundef <4 x half> @ddx_coarse_half_vector(<4 x half> noundef %a) {
+entry:
+; CHECK: %[[#vec4_float_16_arg:]] = OpFunctionParameter %[[#vec4_float_16]]
+; CHECK: %[[#]] = OpDPdxCoarse %[[#vec4_float_16]] %[[#vec4_float_16_arg]]
+ %elt.ddx.coarse = call <4 x half> @llvm.spv.ddx.coarse.v4f16(<4 x half> %a)
+ ret <4 x half> %elt.ddx.coarse
+}
+
+declare float @llvm.spv.ddx.coarse.f32(float)
+declare half @llvm.spv.ddx.coarse.f16(half)
\ No newline at end of file
diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/ddy_coarse.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/ddy_coarse.ll
new file mode 100644
index 0000000000000..87e03f55c260b
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/ddy_coarse.ll
@@ -0,0 +1,43 @@
+; RUN: llc -O0 -verify-machineinstrs -mtriple=spirv-unknown-vulkan %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-vulkan %s -o - -filetype=obj | spirv-val %}
+
+; CHECK-DAG: %[[#float_32:]] = OpTypeFloat 32
+; CHECK-DAG: %[[#float_16:]] = OpTypeFloat 16
+
+; CHECK-DAG: %[[#vec4_float_32:]] = OpTypeVector %[[#float_32]] 4
+; CHECK-DAG: %[[#vec4_float_16:]] = OpTypeVector %[[#float_16]] 4
+
+define noundef float @ddy_coarse_float(float noundef %a) {
+entry:
+; CHECK: %[[#float_32_arg:]] = OpFunctionParameter %[[#float_32]]
+; CHECK: %[[#]] = OpDPdyCoarse %[[#float_32]] %[[#float_32_arg]]
+ %elt.ddy.coarse = call float @llvm.spv.ddy.coarse.f32(float %a)
+ ret float %elt.ddy.coarse
+}
+
+define noundef half @ddy_coarse_half(half noundef %a) {
+entry:
+; CHECK: %[[#float_16_arg:]] = OpFunctionParameter %[[#float_16]]
+; CHECK: %[[#]] = OpDPdyCoarse %[[#float_16]] %[[#float_16_arg]]
+ %elt.ddy.coarse = call half @llvm.spv.ddy.coarse.f16(half %a)
+ ret half %elt.ddy.coarse
+}
+
+define noundef <4 x float> @ddy_coarse_float_vector(<4 x float> noundef %a) {
+entry:
+; CHECK: %[[#vec4_float_32_arg:]] = OpFunctionParameter %[[#vec4_float_32]]
+; CHECK: %[[#]] = OpDPdyCoarse %[[#vec4_float_32]] %[[#vec4_float_32_arg]]
+ %elt.ddy.coarse = call <4 x float> @llvm.spv.ddy.coarse.v4f32(<4 x float> %a)
+ ret <4 x float> %elt.ddy.coarse
+}
+
+define noundef <4 x half> @ddy_coarse_half_vector(<4 x half> noundef %a) {
+entry:
+; CHECK: %[[#vec4_float_16_arg:]] = OpFunctionParameter %[[#vec4_float_16]]
+; CHECK: %[[#]] = OpDPdyCoarse %[[#vec4_float_16]] %[[#vec4_float_16_arg]]
+ %elt.ddy.coarse = call <4 x half> @llvm.spv.ddy.coarse.v4f16(<4 x half> %a)
+ ret <4 x half> %elt.ddy.coarse
+}
+
+declare float @llvm.spv.ddy.coarse.f32(float)
+declare half @llvm.spv.ddy.coarse.f16(half)
\ No newline at end of file
>From 202b09cf2784d3ee6a1e97714a5290362383add8 Mon Sep 17 00:00:00 2001
From: Alexander Johnston <alexander.johnston at amd.com>
Date: Thu, 23 Oct 2025 16:49:28 +0100
Subject: [PATCH 2/4] Revert unneeded SPIR-V target changes
---
clang/include/clang/Basic/BuiltinsSPIRVVK.td | 2 --
clang/lib/CodeGen/TargetBuiltins/SPIR.cpp | 12 --------
clang/lib/Sema/SemaSPIRV.cpp | 26 -----------------
.../SemaSPIRV/BuiltIns/ddx-coarse-errors.c | 29 -------------------
.../SemaSPIRV/BuiltIns/ddy-coarse-errors.c | 29 -------------------
5 files changed, 98 deletions(-)
delete mode 100644 clang/test/SemaSPIRV/BuiltIns/ddx-coarse-errors.c
delete mode 100644 clang/test/SemaSPIRV/BuiltIns/ddy-coarse-errors.c
diff --git a/clang/include/clang/Basic/BuiltinsSPIRVVK.td b/clang/include/clang/Basic/BuiltinsSPIRVVK.td
index 96e7c7b11fdfd..5dc3c7588cd2a 100644
--- a/clang/include/clang/Basic/BuiltinsSPIRVVK.td
+++ b/clang/include/clang/Basic/BuiltinsSPIRVVK.td
@@ -12,5 +12,3 @@ include "clang/Basic/BuiltinsSPIRVBase.td"
def reflect : SPIRVBuiltin<"void(...)", [NoThrow, Const]>;
def faceforward : SPIRVBuiltin<"void(...)", [NoThrow, Const, CustomTypeChecking]>;
def refract : SPIRVBuiltin<"void(...)", [NoThrow, Const, CustomTypeChecking]>;
-def ddx_coarse : SPIRVBuiltin<"void(...)", [NoThrow, Const, CustomTypeChecking]>;
-def ddy_coarse : SPIRVBuiltin<"void(...)", [NoThrow, Const, CustomTypeChecking]>;
diff --git a/clang/lib/CodeGen/TargetBuiltins/SPIR.cpp b/clang/lib/CodeGen/TargetBuiltins/SPIR.cpp
index 12937fe8c0d10..243aad8bf7083 100644
--- a/clang/lib/CodeGen/TargetBuiltins/SPIR.cpp
+++ b/clang/lib/CodeGen/TargetBuiltins/SPIR.cpp
@@ -151,18 +151,6 @@ Value *CodeGenFunction::EmitSPIRVBuiltinExpr(unsigned BuiltinID,
Intrinsic::spv_global_offset,
ArrayRef<Value *>{EmitScalarExpr(E->getArg(0))}, nullptr,
"spv.global.offset");
- case SPIRV::BI__builtin_spirv_ddx_coarse:
- return Builder.CreateIntrinsic(
- /*ReturnType=*/getTypes().ConvertType(E->getType()),
- Intrinsic::spv_ddx_coarse,
- ArrayRef<Value *>{EmitScalarExpr(E->getArg(0))}, nullptr,
- "spv.ddx.coarse");
- case SPIRV::BI__builtin_spirv_ddy_coarse:
- return Builder.CreateIntrinsic(
- /*ReturnType=*/getTypes().ConvertType(E->getType()),
- Intrinsic::spv_ddy_coarse,
- ArrayRef<Value *>{EmitScalarExpr(E->getArg(0))}, nullptr,
- "spv.ddy.coarse");
}
return nullptr;
}
diff --git a/clang/lib/Sema/SemaSPIRV.cpp b/clang/lib/Sema/SemaSPIRV.cpp
index 0e2bb1f3c1900..c8ea0d09c4081 100644
--- a/clang/lib/Sema/SemaSPIRV.cpp
+++ b/clang/lib/Sema/SemaSPIRV.cpp
@@ -46,19 +46,6 @@ static bool CheckAllArgsHaveSameType(Sema *S, CallExpr *TheCall) {
return false;
}
-static bool CheckAllArgTypesAreCorrect(
- Sema *S, CallExpr *TheCall,
- llvm::function_ref<bool(Sema *S, SourceLocation Loc, int ArgOrdinal,
- clang::QualType PassedType)>
- Check) {
- for (unsigned I = 0; I < TheCall->getNumArgs(); ++I) {
- Expr *Arg = TheCall->getArg(I);
- if (Check(S, Arg->getBeginLoc(), I + 1, Arg->getType()))
- return true;
- }
- return false;
-}
-
static bool CheckAllArgTypesAreCorrect(
Sema *S, CallExpr *TheCall,
llvm::ArrayRef<
@@ -373,19 +360,6 @@ bool SemaSPIRV::CheckSPIRVBuiltinFunctionCall(const TargetInfo &TI,
case SPIRV::BI__builtin_spirv_generic_cast_to_ptr_explicit: {
return checkGenericCastToPtr(SemaRef, TheCall);
}
- case SPIRV::BI__builtin_spirv_ddx_coarse:
- case SPIRV::BI__builtin_spirv_ddy_coarse: {
- if (SemaRef.checkArgCount(TheCall, 1))
- return true;
-
- if (CheckAllArgTypesAreCorrect(&SemaRef, TheCall,
- CheckFloatOrHalfRepresentation))
- return true;
-
- QualType RetTy = TheCall->getArg(0)->getType();
- TheCall->setType(RetTy);
- break;
- }
}
return false;
}
diff --git a/clang/test/SemaSPIRV/BuiltIns/ddx-coarse-errors.c b/clang/test/SemaSPIRV/BuiltIns/ddx-coarse-errors.c
deleted file mode 100644
index d4f37100f6ce2..0000000000000
--- a/clang/test/SemaSPIRV/BuiltIns/ddx-coarse-errors.c
+++ /dev/null
@@ -1,29 +0,0 @@
-/// RUN: %clang_cc1 %s -triple spirv-pc-vulkan-compute -verify
-
-typedef _Float16 half;
-typedef float float2 __attribute__((ext_vector_type(2)));
-
-float no_arg() {
- return __builtin_spirv_ddx_coarse();
- // expected-error at -1 {{too few arguments to function call, expected 1, have 0}}
-}
-
-float too_many_args(float val) {
- return __builtin_spirv_ddx_coarse(val, val);
- // expected-error at -1 {{too many arguments to function call, expected 1, have 2}}
-}
-
-float mismatched_return(float2 val) {
- return __builtin_spirv_ddx_coarse(val);
- // expected-error at -1 {{returning 'float2' (vector of 2 'float' values) from a function with incompatible result type 'float'}}
-}
-
-float test_integer_scalar_input(int val) {
- return __builtin_spirv_ddx_coarse(val);
- // expected-error at -1 {{1st argument must be a scalar or vector of 16 or 32 bit floating-point types (was 'int')}}
-}
-
-double test_double_scalar_input(double val) {
- return __builtin_spirv_ddx_coarse(val);
- // expected-error at -1 {{1st argument must be a scalar or vector of 16 or 32 bit floating-point types (was 'double')}}
-}
\ No newline at end of file
diff --git a/clang/test/SemaSPIRV/BuiltIns/ddy-coarse-errors.c b/clang/test/SemaSPIRV/BuiltIns/ddy-coarse-errors.c
deleted file mode 100644
index fc8c32f998ffd..0000000000000
--- a/clang/test/SemaSPIRV/BuiltIns/ddy-coarse-errors.c
+++ /dev/null
@@ -1,29 +0,0 @@
-/// RUN: %clang_cc1 %s -triple spirv-pc-vulkan-compute -verify
-
-typedef _Float16 half;
-typedef float float2 __attribute__((ext_vector_type(2)));
-
-float no_arg() {
- return __builtin_spirv_ddy_coarse();
- // expected-error at -1 {{too few arguments to function call, expected 1, have 0}}
-}
-
-float too_many_args(float val) {
- return __builtin_spirv_ddy_coarse(val, val);
- // expected-error at -1 {{too many arguments to function call, expected 1, have 2}}
-}
-
-float mismatched_return(float2 val) {
- return __builtin_spirv_ddy_coarse(val);
- // expected-error at -1 {{returning 'float2' (vector of 2 'float' values) from a function with incompatible result type 'float'}}
-}
-
-float test_integer_scalar_input(int val) {
- return __builtin_spirv_ddy_coarse(val);
- // expected-error at -1 {{1st argument must be a scalar or vector of 16 or 32 bit floating-point types (was 'int')}}
-}
-
-double test_double_scalar_input(double val) {
- return __builtin_spirv_ddy_coarse(val);
- // expected-error at -1 {{1st argument must be a scalar or vector of 16 or 32 bit floating-point types (was 'double')}}
-}
\ No newline at end of file
>From a1938a7478e33685a69ed6fc3af8b214bc822874 Mon Sep 17 00:00:00 2001
From: Alexander Johnston <alexander.johnston at amd.com>
Date: Thu, 23 Oct 2025 17:59:54 +0100
Subject: [PATCH 3/4] Change hlsl ddx/y_coarse intrinsic to alias
---
.../lib/Headers/hlsl/hlsl_alias_intrinsics.h | 68 +++++++++++++++++
.../lib/Headers/hlsl/hlsl_intrinsic_helpers.h | 16 ----
clang/lib/Headers/hlsl/hlsl_intrinsics.h | 76 -------------------
3 files changed, 68 insertions(+), 92 deletions(-)
diff --git a/clang/lib/Headers/hlsl/hlsl_alias_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_alias_intrinsics.h
index d973371312701..cd54547a722d5 100644
--- a/clang/lib/Headers/hlsl/hlsl_alias_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_alias_intrinsics.h
@@ -2840,5 +2840,73 @@ float4 radians(float4);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_group_memory_barrier_with_group_sync)
__attribute__((convergent)) void GroupMemoryBarrierWithGroupSync(void);
+//===----------------------------------------------------------------------===//
+// ddx_coarse builtin
+//===----------------------------------------------------------------------===//
+
+/// \fn T ddx_coarse(T value)
+/// \brief Computes a low precision partial derivative with respect to the
+/// screen-space x-coordinate.
+/// \param value The input value.
+///
+/// The return value is a floating point scalar or vector containing the low
+/// prevision partial derivative of the input value.
+
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddx_coarse)
+half ddx_coarse(half);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddx_coarse)
+half2 ddx_coarse(half2);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddx_coarse)
+half3 ddx_coarse(half3);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddx_coarse)
+half4 ddx_coarse(half4);
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddx_coarse)
+float ddx_coarse(float);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddx_coarse)
+float2 ddx_coarse(float2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddx_coarse)
+float3 ddx_coarse(float3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddx_coarse)
+float4 ddx_coarse(float4);
+
+//===----------------------------------------------------------------------===//
+// ddy_coarse builtin
+//===----------------------------------------------------------------------===//
+
+/// \fn T ddy_coarse(T value)
+/// \brief Computes a low precision partial derivative with respect to the
+/// screen-space y-coordinate.
+/// \param value The input value.
+///
+/// The return value is a floating point scalar or vector containing the low
+/// prevision partial derivative of the input value.
+
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddy_coarse)
+half ddy_coarse(half);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddy_coarse)
+half2 ddy_coarse(half2);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddy_coarse)
+half3 ddy_coarse(half3);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddy_coarse)
+half4 ddy_coarse(half4);
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddy_coarse)
+float ddy_coarse(float);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddy_coarse)
+float2 ddy_coarse(float2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddy_coarse)
+float3 ddy_coarse(float3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddy_coarse)
+float4 ddy_coarse(float4);
+
} // namespace hlsl
#endif //_HLSL_HLSL_ALIAS_INTRINSICS_H_
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h b/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h
index e3f5c5dbfa8d1..c877234479ad1 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h
@@ -148,22 +148,6 @@ template <typename T> constexpr T ldexp_impl(T X, T Exp) {
return exp2(Exp) * X;
}
-template <typename T> constexpr T ddx_coarse_impl(T value) {
-#if (__has_builtin(__builtin_spirv_ddx_coarse))
- return __builtin_spirv_ddx_coarse(value);
-#else
- return __builtin_hlsl_elementwise_ddx_coarse(value);
-#endif
-}
-
-template <typename T> constexpr T ddy_coarse_impl(T value) {
-#if (__has_builtin(__builtin_spirv_ddy_coarse))
- return __builtin_spirv_ddy_coarse(value);
-#else
- return __builtin_hlsl_elementwise_ddy_coarse(value);
-#endif
-}
-
} // namespace __detail
} // namespace hlsl
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
index 9fac001be1572..5ba5bfb9abde0 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
@@ -605,81 +605,5 @@ smoothstep(__detail::HLSL_FIXED_VECTOR<float, N> Min,
return __detail::smoothstep_vec_impl(Min, Max, X);
}
-//===----------------------------------------------------------------------===//
-// ddx_coarse builtin
-//===----------------------------------------------------------------------===//
-
-/// \fn T ddx_coarse(T value)
-/// \brief Computes a low precision partial derivative with respect to the
-/// screen-space x-coordinate.
-/// \param value The input value.
-///
-/// The return value is a floating point scalar or vector containing the low
-/// prevision partial derivative of the input value.
-
-template <typename T>
-const inline __detail::enable_if_t<
- __detail::is_arithmetic<T>::Value && __detail::is_same<half, T>::value, T>
-ddx_coarse(T value) {
- return __detail::ddx_coarse_impl(value);
-}
-
-template <typename T>
-const inline __detail::enable_if_t<
- __detail::is_arithmetic<T>::Value && __detail::is_same<float, T>::value, T>
-ddx_coarse(T value) {
- return __detail::ddx_coarse_impl(value);
-}
-
-template <int L>
-const inline __detail::HLSL_FIXED_VECTOR<half, L>
-ddx_coarse(__detail::HLSL_FIXED_VECTOR<half, L> value) {
- return __detail::ddx_coarse_impl(value);
-}
-
-template <int L>
-const inline __detail::HLSL_FIXED_VECTOR<float, L>
-ddx_coarse(__detail::HLSL_FIXED_VECTOR<float, L> value) {
- return __detail::ddx_coarse_impl(value);
-}
-
-//===----------------------------------------------------------------------===//
-// ddy_coarse builtin
-//===----------------------------------------------------------------------===//
-
-/// \fn T ddy_coarse(T value)
-/// \brief Computes a low precision partial derivative with respect to the
-/// screen-space y-coordinate.
-/// \param value The input value.
-///
-/// The return value is a floating point scalar or vector containing the low
-/// prevision partial derivative of the input value.
-
-template <typename T>
-const inline __detail::enable_if_t<
- __detail::is_arithmetic<T>::Value && __detail::is_same<half, T>::value, T>
-ddy_coarse(T value) {
- return __detail::ddy_coarse_impl(value);
-}
-
-template <typename T>
-const inline __detail::enable_if_t<
- __detail::is_arithmetic<T>::Value && __detail::is_same<float, T>::value, T>
-ddy_coarse(T value) {
- return __detail::ddy_coarse_impl(value);
-}
-
-template <int L>
-const inline __detail::HLSL_FIXED_VECTOR<half, L>
-ddy_coarse(__detail::HLSL_FIXED_VECTOR<half, L> value) {
- return __detail::ddy_coarse_impl(value);
-}
-
-template <int L>
-const inline __detail::HLSL_FIXED_VECTOR<float, L>
-ddy_coarse(__detail::HLSL_FIXED_VECTOR<float, L> value) {
- return __detail::ddy_coarse_impl(value);
-}
-
} // namespace hlsl
#endif //_HLSL_HLSL_INTRINSICS_H_
>From c1703009ee462f5ef6848c7ac269b4fc3f99eb65 Mon Sep 17 00:00:00 2001
From: Alexander Johnston <alexander.johnston at amd.com>
Date: Thu, 23 Oct 2025 18:00:34 +0100
Subject: [PATCH 4/4] Update ddx/y_coarse tests
---
.../builtins/ddx-coarse-builtin.hlsl | 19 ++++--
.../test/CodeGenHLSL/builtins/ddx-coarse.hlsl | 61 +++++++++++++------
.../builtins/ddy-coarse-builtin.hlsl | 19 ++++--
.../test/CodeGenHLSL/builtins/ddy-coarse.hlsl | 61 +++++++++++++------
.../SemaHLSL/BuiltIns/ddx-coarse-errors.hlsl | 2 +-
.../SemaHLSL/BuiltIns/ddy-coarse-errors.hlsl | 2 +-
llvm/test/CodeGen/DirectX/ddx_coarse.ll | 2 +-
llvm/test/CodeGen/DirectX/ddy_coarse.ll | 2 +-
8 files changed, 118 insertions(+), 50 deletions(-)
diff --git a/clang/test/CodeGenHLSL/builtins/ddx-coarse-builtin.hlsl b/clang/test/CodeGenHLSL/builtins/ddx-coarse-builtin.hlsl
index 36d9d5969a59b..01216eefadba2 100644
--- a/clang/test/CodeGenHLSL/builtins/ddx-coarse-builtin.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/ddx-coarse-builtin.hlsl
@@ -1,17 +1,26 @@
// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s \
// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
// RUN: FileCheck %s --check-prefixes=CHECK
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple spirv-pc-vulkan-compute %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
+// RUN: FileCheck %s --check-prefixes=CHECK-SPIRV
-// CHECK: define hidden noundef nofpclass(nan inf) half @
-// CHECK: %hlsl.ddx.coarse = call reassoc nnan ninf nsz arcp afn half @llvm.dx.ddx.coarse.f16(half %{{.*}})
+// CHECK-LABEL: half @_Z19test_f16_ddx_coarseDh
+// CHECK: %hlsl.ddx.coarse = call {{.*}} half @llvm.dx.ddx.coarse.f16(half %{{.*}})
// CHECK: ret half %hlsl.ddx.coarse
+// CHECK-LABEL-SPIRV: half @_Z19test_f16_ddx_coarseDh
+// CHECK-SPIRV: %hlsl.ddx.coarse = call {{.*}} half @llvm.spv.ddx.coarse.f16(half %{{.*}})
+// CHECK-SPIRV: ret half %hlsl.ddx.coarse
half test_f16_ddx_coarse(half val) {
return __builtin_hlsl_elementwise_ddx_coarse(val);
}
-// CHECK: define hidden noundef nofpclass(nan inf) float @
-// CHECK: %hlsl.ddx.coarse = call reassoc nnan ninf nsz arcp afn float @llvm.dx.ddx.coarse.f32(float %{{.*}})
+// CHECK-LABEL: float @_Z19test_f32_ddx_coarsef
+// CHECK: %hlsl.ddx.coarse = call {{.*}} float @llvm.dx.ddx.coarse.f32(float %{{.*}})
// CHECK: ret float %hlsl.ddx.coarse
+// CHECK-LABEL-SPIRV: float @_Z19test_f32_ddx_coarsef
+// CHECK-SPIRV: %hlsl.ddx.coarse = call {{.*}} float @llvm.spv.ddx.coarse.f32(float %{{.*}})
+// CHECK-SPIRV: ret float %hlsl.ddx.coarse
float test_f32_ddx_coarse(float val) {
return __builtin_hlsl_elementwise_ddx_coarse(val);
-}
\ No newline at end of file
+}
diff --git a/clang/test/CodeGenHLSL/builtins/ddx-coarse.hlsl b/clang/test/CodeGenHLSL/builtins/ddx-coarse.hlsl
index aedcb9b6e08cd..c200d4715629e 100644
--- a/clang/test/CodeGenHLSL/builtins/ddx-coarse.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/ddx-coarse.hlsl
@@ -1,61 +1,86 @@
// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s \
// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
// RUN: FileCheck %s --check-prefixes=CHECK
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple spirv-pc-vulkan-compute %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
+// RUN: FileCheck %s --check-prefixes=CHECK-SPIRV
-using hlsl::ddx_coarse;
-
-// CHECK: define linkonce_odr hidden noundef nofpclass(nan inf) half @
-// CHECK: %hlsl.ddx.coarse = call reassoc nnan ninf nsz arcp afn half @llvm.dx.ddx.coarse.f16(half %{{.*}})
+// CHECK-LABEL: half @_Z19test_f16_ddx_coarseDh
+// CHECK: %hlsl.ddx.coarse = call {{.*}} half @llvm.dx.ddx.coarse.f16(half %{{.*}})
// CHECK: ret half %hlsl.ddx.coarse
+// CHECK-LABEL-SPIRV: half @_Z19test_f16_ddx_coarseDh
+// CHECK-SPIRV: %hlsl.ddx.coarse = call {{.*}} half @llvm.spv.ddx.coarse.f16(half %{{.*}})
+// CHECK-SPIRV: ret half %hlsl.ddx.coarse
half test_f16_ddx_coarse(half val) {
return ddx_coarse(val);
}
-// CHECK: define linkonce_odr hidden noundef nofpclass(nan inf) <2 x half> @
-// CHECK: %hlsl.ddx.coarse = call reassoc nnan ninf nsz arcp afn <2 x half> @llvm.dx.ddx.coarse.v2f16(<2 x half> %{{.*}})
+// CHECK-LABEL: <2 x half> @_Z20test_f16_ddx_coarse2Dv2_Dh
+// CHECK: %hlsl.ddx.coarse = call {{.*}} <2 x half> @llvm.dx.ddx.coarse.v2f16(<2 x half> %{{.*}})
// CHECK: ret <2 x half> %hlsl.ddx.coarse
+// CHECK-LABEL-SPIRV: <2 x half> @_Z20test_f16_ddx_coarse2Dv2_Dh
+// CHECK-SPIRV: %hlsl.ddx.coarse = call {{.*}} <2 x half> @llvm.spv.ddx.coarse.v2f16(<2 x half> %{{.*}})
+// CHECK-SPIRV: ret <2 x half> %hlsl.ddx.coarse
half2 test_f16_ddx_coarse2(half2 val) {
return ddx_coarse(val);
}
-// CHECK: define linkonce_odr hidden noundef nofpclass(nan inf) <3 x half> @
-// CHECK: %hlsl.ddx.coarse = call reassoc nnan ninf nsz arcp afn <3 x half> @llvm.dx.ddx.coarse.v3f16(<3 x half> %{{.*}})
+// CHECK-LABEL: <3 x half> @_Z20test_f16_ddx_coarse3Dv3_Dh
+// CHECK: %hlsl.ddx.coarse = call {{.*}} <3 x half> @llvm.dx.ddx.coarse.v3f16(<3 x half> %{{.*}})
// CHECK: ret <3 x half> %hlsl.ddx.coarse
+// CHECK-LABEL-SPIRV: <3 x half> @_Z20test_f16_ddx_coarse3Dv3_Dh
+// CHECK-SPIRV: %hlsl.ddx.coarse = call {{.*}} <3 x half> @llvm.spv.ddx.coarse.v3f16(<3 x half> %{{.*}})
+// CHECK-SPIRV: ret <3 x half> %hlsl.ddx.coarse
half3 test_f16_ddx_coarse3(half3 val) {
return ddx_coarse(val);
}
-// CHECK: define linkonce_odr hidden noundef nofpclass(nan inf) <4 x half> @
-// CHECK: %hlsl.ddx.coarse = call reassoc nnan ninf nsz arcp afn <4 x half> @llvm.dx.ddx.coarse.v4f16(<4 x half> %{{.*}})
+// CHECK-LABEL: <4 x half> @_Z20test_f16_ddx_coarse4Dv4_Dh
+// CHECK: %hlsl.ddx.coarse = call {{.*}} <4 x half> @llvm.dx.ddx.coarse.v4f16(<4 x half> %{{.*}})
// CHECK: ret <4 x half> %hlsl.ddx.coarse
+// CHECK-LABEL-SPIRV: <4 x half> @_Z20test_f16_ddx_coarse4Dv4_Dh
+// CHECK-SPIRV: %hlsl.ddx.coarse = call {{.*}} <4 x half> @llvm.spv.ddx.coarse.v4f16(<4 x half> %{{.*}})
+// CHECK-SPIRV: ret <4 x half> %hlsl.ddx.coarse
half4 test_f16_ddx_coarse4(half4 val) {
return ddx_coarse(val);
}
-// CHECK: define linkonce_odr hidden noundef nofpclass(nan inf) float @
-// CHECK: %hlsl.ddx.coarse = call reassoc nnan ninf nsz arcp afn float @llvm.dx.ddx.coarse.f32(float %{{.*}})
+// CHECK-LABEL: float @_Z19test_f32_ddx_coarsef
+// CHECK: %hlsl.ddx.coarse = call {{.*}} float @llvm.dx.ddx.coarse.f32(float %{{.*}})
// CHECK: ret float %hlsl.ddx.coarse
+// CHECK-LABEL-SPIRV: float @_Z19test_f32_ddx_coarsef
+// CHECK-SPIRV: %hlsl.ddx.coarse = call {{.*}} float @llvm.spv.ddx.coarse.f32(float %{{.*}})
+// CHECK-SPIRV: ret float %hlsl.ddx.coarse
float test_f32_ddx_coarse(float val) {
return ddx_coarse(val);
}
-// CHECK: define linkonce_odr hidden noundef nofpclass(nan inf) <2 x float> @
-// CHECK: %hlsl.ddx.coarse = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.dx.ddx.coarse.v2f32(<2 x float> %{{.*}})
+// CHECK-LABEL: <2 x float> @_Z20test_f32_ddx_coarse2Dv2_f
+// CHECK: %hlsl.ddx.coarse = call {{.*}} <2 x float> @llvm.dx.ddx.coarse.v2f32(<2 x float> %{{.*}})
// CHECK: ret <2 x float> %hlsl.ddx.coarse
+// CHECK-LABEL-SPIRV: <2 x float> @_Z20test_f32_ddx_coarse2Dv2_f
+// CHECK-SPIRV: %hlsl.ddx.coarse = call {{.*}} <2 x float> @llvm.spv.ddx.coarse.v2f32(<2 x float> %{{.*}})
+// CHECK-SPIRV: ret <2 x float> %hlsl.ddx.coarse
float2 test_f32_ddx_coarse2(float2 val) {
return ddx_coarse(val);
}
-// CHECK: define linkonce_odr hidden noundef nofpclass(nan inf) <3 x float> @
-// CHECK: %hlsl.ddx.coarse = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.dx.ddx.coarse.v3f32(<3 x float> %{{.*}})
+// CHECK-LABEL: <3 x float> @_Z20test_f32_ddx_coarse3Dv3_f
+// CHECK: %hlsl.ddx.coarse = call {{.*}} <3 x float> @llvm.dx.ddx.coarse.v3f32(<3 x float> %{{.*}})
// CHECK: ret <3 x float> %hlsl.ddx.coarse
+// CHECK-LABEL-SPIRV: <3 x float> @_Z20test_f32_ddx_coarse3Dv3_f
+// CHECK-SPIRV: %hlsl.ddx.coarse = call {{.*}} <3 x float> @llvm.spv.ddx.coarse.v3f32(<3 x float> %{{.*}})
+// CHECK-SPIRV: ret <3 x float> %hlsl.ddx.coarse
float3 test_f32_ddx_coarse3(float3 val) {
return ddx_coarse(val);
}
-// CHECK: define linkonce_odr hidden noundef nofpclass(nan inf) <4 x float> @
-// CHECK: %hlsl.ddx.coarse = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.dx.ddx.coarse.v4f32(<4 x float> %{{.*}})
+// CHECK-LABEL: <4 x float> @_Z20test_f32_ddx_coarse4Dv4_f
+// CHECK: %hlsl.ddx.coarse = call {{.*}} <4 x float> @llvm.dx.ddx.coarse.v4f32(<4 x float> %{{.*}})
// CHECK: ret <4 x float> %hlsl.ddx.coarse
+// CHECK-LABEL-SPIRV: <4 x float> @_Z20test_f32_ddx_coarse4Dv4_f
+// CHECK-SPIRV: %hlsl.ddx.coarse = call {{.*}} <4 x float> @llvm.spv.ddx.coarse.v4f32(<4 x float> %{{.*}})
+// CHECK-SPIRV: ret <4 x float> %hlsl.ddx.coarse
float4 test_f32_ddx_coarse4(float4 val) {
return ddx_coarse(val);
}
diff --git a/clang/test/CodeGenHLSL/builtins/ddy-coarse-builtin.hlsl b/clang/test/CodeGenHLSL/builtins/ddy-coarse-builtin.hlsl
index 5f69699ff7bd6..2967deb75031f 100644
--- a/clang/test/CodeGenHLSL/builtins/ddy-coarse-builtin.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/ddy-coarse-builtin.hlsl
@@ -1,17 +1,26 @@
// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s \
// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
// RUN: FileCheck %s --check-prefixes=CHECK
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple spirv-pc-vulkan-compute %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
+// RUN: FileCheck %s --check-prefixes=CHECK-SPIRV
-// CHECK: define hidden noundef nofpclass(nan inf) half @
-// CHECK: %hlsl.ddy.coarse = call reassoc nnan ninf nsz arcp afn half @llvm.dx.ddy.coarse.f16(half %{{.*}})
+// CHECK-LABEL: half @_Z19test_f16_ddy_coarseDh
+// CHECK: %hlsl.ddy.coarse = call {{.*}} half @llvm.dx.ddy.coarse.f16(half %{{.*}})
// CHECK: ret half %hlsl.ddy.coarse
+// CHECK-LABEL-SPIRV: half @_Z19test_f16_ddy_coarseDh
+// CHECK-SPIRV: %hlsl.ddy.coarse = call {{.*}} half @llvm.spv.ddy.coarse.f16(half %{{.*}})
+// CHECK-SPIRV: ret half %hlsl.ddy.coarse
half test_f16_ddy_coarse(half val) {
return __builtin_hlsl_elementwise_ddy_coarse(val);
}
-// CHECK: define hidden noundef nofpclass(nan inf) float @
-// CHECK: %hlsl.ddy.coarse = call reassoc nnan ninf nsz arcp afn float @llvm.dx.ddy.coarse.f32(float %{{.*}})
+// CHECK-LABEL: float @_Z19test_f32_ddy_coarsef
+// CHECK: %hlsl.ddy.coarse = call {{.*}} float @llvm.dx.ddy.coarse.f32(float %{{.*}})
// CHECK: ret float %hlsl.ddy.coarse
+// CHECK-LABEL-SPIRV: float @_Z19test_f32_ddy_coarsef
+// CHECK-SPIRV: %hlsl.ddy.coarse = call {{.*}} float @llvm.spv.ddy.coarse.f32(float %{{.*}})
+// CHECK-SPIRV: ret float %hlsl.ddy.coarse
float test_f32_ddy_coarse(float val) {
return __builtin_hlsl_elementwise_ddy_coarse(val);
-}
\ No newline at end of file
+}
diff --git a/clang/test/CodeGenHLSL/builtins/ddy-coarse.hlsl b/clang/test/CodeGenHLSL/builtins/ddy-coarse.hlsl
index 5428930d519ab..faa972a1be326 100644
--- a/clang/test/CodeGenHLSL/builtins/ddy-coarse.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/ddy-coarse.hlsl
@@ -1,61 +1,86 @@
// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s \
// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
// RUN: FileCheck %s --check-prefixes=CHECK
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple spirv-pc-vulkan-compute %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
+// RUN: FileCheck %s --check-prefixes=CHECK-SPIRV
-using hlsl::ddy_coarse;
-
-// CHECK: define linkonce_odr hidden noundef nofpclass(nan inf) half @
-// CHECK: %hlsl.ddy.coarse = call reassoc nnan ninf nsz arcp afn half @llvm.dx.ddy.coarse.f16(half %{{.*}})
+// CHECK-LABEL: half @_Z19test_f16_ddy_coarseDh
+// CHECK: %hlsl.ddy.coarse = call {{.*}} half @llvm.dx.ddy.coarse.f16(half %{{.*}})
// CHECK: ret half %hlsl.ddy.coarse
+// CHECK-LABEL-SPIRV: half @_Z19test_f16_ddy_coarseDh
+// CHECK-SPIRV: %hlsl.ddy.coarse = call {{.*}} half @llvm.spv.ddy.coarse.f16(half %{{.*}})
+// CHECK-SPIRV: ret half %hlsl.ddy.coarse
half test_f16_ddy_coarse(half val) {
return ddy_coarse(val);
}
-// CHECK: define linkonce_odr hidden noundef nofpclass(nan inf) <2 x half> @
-// CHECK: %hlsl.ddy.coarse = call reassoc nnan ninf nsz arcp afn <2 x half> @llvm.dx.ddy.coarse.v2f16(<2 x half> %{{.*}})
+// CHECK-LABEL: <2 x half> @_Z20test_f16_ddy_coarse2Dv2_Dh
+// CHECK: %hlsl.ddy.coarse = call {{.*}} <2 x half> @llvm.dx.ddy.coarse.v2f16(<2 x half> %{{.*}})
// CHECK: ret <2 x half> %hlsl.ddy.coarse
+// CHECK-LABEL-SPIRV: <2 x half> @_Z20test_f16_ddy_coarse2Dv2_Dh
+// CHECK-SPIRV: %hlsl.ddy.coarse = call {{.*}} <2 x half> @llvm.spv.ddy.coarse.v2f16(<2 x half> %{{.*}})
+// CHECK-SPIRV: ret <2 x half> %hlsl.ddy.coarse
half2 test_f16_ddy_coarse2(half2 val) {
return ddy_coarse(val);
}
-// CHECK: define linkonce_odr hidden noundef nofpclass(nan inf) <3 x half> @
-// CHECK: %hlsl.ddy.coarse = call reassoc nnan ninf nsz arcp afn <3 x half> @llvm.dx.ddy.coarse.v3f16(<3 x half> %{{.*}})
+// CHECK-LABEL: <3 x half> @_Z20test_f16_ddy_coarse3Dv3_Dh
+// CHECK: %hlsl.ddy.coarse = call {{.*}} <3 x half> @llvm.dx.ddy.coarse.v3f16(<3 x half> %{{.*}})
// CHECK: ret <3 x half> %hlsl.ddy.coarse
+// CHECK-LABEL-SPIRV: <3 x half> @_Z20test_f16_ddy_coarse3Dv3_Dh
+// CHECK-SPIRV: %hlsl.ddy.coarse = call {{.*}} <3 x half> @llvm.spv.ddy.coarse.v3f16(<3 x half> %{{.*}})
+// CHECK-SPIRV: ret <3 x half> %hlsl.ddy.coarse
half3 test_f16_ddy_coarse3(half3 val) {
return ddy_coarse(val);
}
-// CHECK: define linkonce_odr hidden noundef nofpclass(nan inf) <4 x half> @
-// CHECK: %hlsl.ddy.coarse = call reassoc nnan ninf nsz arcp afn <4 x half> @llvm.dx.ddy.coarse.v4f16(<4 x half> %{{.*}})
+// CHECK-LABEL: <4 x half> @_Z20test_f16_ddy_coarse4Dv4_Dh
+// CHECK: %hlsl.ddy.coarse = call {{.*}} <4 x half> @llvm.dx.ddy.coarse.v4f16(<4 x half> %{{.*}})
// CHECK: ret <4 x half> %hlsl.ddy.coarse
+// CHECK-LABEL-SPIRV: <4 x half> @_Z20test_f16_ddy_coarse4Dv4_Dh
+// CHECK-SPIRV: %hlsl.ddy.coarse = call {{.*}} <4 x half> @llvm.spv.ddy.coarse.v4f16(<4 x half> %{{.*}})
+// CHECK-SPIRV: ret <4 x half> %hlsl.ddy.coarse
half4 test_f16_ddy_coarse4(half4 val) {
return ddy_coarse(val);
}
-// CHECK: define linkonce_odr hidden noundef nofpclass(nan inf) float @
-// CHECK: %hlsl.ddy.coarse = call reassoc nnan ninf nsz arcp afn float @llvm.dx.ddy.coarse.f32(float %{{.*}})
+// CHECK-LABEL: float @_Z19test_f32_ddy_coarsef
+// CHECK: %hlsl.ddy.coarse = call {{.*}} float @llvm.dx.ddy.coarse.f32(float %{{.*}})
// CHECK: ret float %hlsl.ddy.coarse
+// CHECK-LABEL-SPIRV: float @_Z19test_f32_ddy_coarsef
+// CHECK-SPIRV: %hlsl.ddy.coarse = call {{.*}} float @llvm.spv.ddy.coarse.f32(float %{{.*}})
+// CHECK-SPIRV: ret float %hlsl.ddy.coarse
float test_f32_ddy_coarse(float val) {
return ddy_coarse(val);
}
-// CHECK: define linkonce_odr hidden noundef nofpclass(nan inf) <2 x float> @
-// CHECK: %hlsl.ddy.coarse = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.dx.ddy.coarse.v2f32(<2 x float> %{{.*}})
+// CHECK-LABEL: <2 x float> @_Z20test_f32_ddy_coarse2Dv2_f
+// CHECK: %hlsl.ddy.coarse = call {{.*}} <2 x float> @llvm.dx.ddy.coarse.v2f32(<2 x float> %{{.*}})
// CHECK: ret <2 x float> %hlsl.ddy.coarse
+// CHECK-LABEL-SPIRV: <2 x float> @_Z20test_f32_ddy_coarse2Dv2_f
+// CHECK-SPIRV: %hlsl.ddy.coarse = call {{.*}} <2 x float> @llvm.spv.ddy.coarse.v2f32(<2 x float> %{{.*}})
+// CHECK-SPIRV: ret <2 x float> %hlsl.ddy.coarse
float2 test_f32_ddy_coarse2(float2 val) {
return ddy_coarse(val);
}
-// CHECK: define linkonce_odr hidden noundef nofpclass(nan inf) <3 x float> @
-// CHECK: %hlsl.ddy.coarse = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.dx.ddy.coarse.v3f32(<3 x float> %{{.*}})
+// CHECK-LABEL: <3 x float> @_Z20test_f32_ddy_coarse3Dv3_f
+// CHECK: %hlsl.ddy.coarse = call {{.*}} <3 x float> @llvm.dx.ddy.coarse.v3f32(<3 x float> %{{.*}})
// CHECK: ret <3 x float> %hlsl.ddy.coarse
+// CHECK-LABEL-SPIRV: <3 x float> @_Z20test_f32_ddy_coarse3Dv3_f
+// CHECK-SPIRV: %hlsl.ddy.coarse = call {{.*}} <3 x float> @llvm.spv.ddy.coarse.v3f32(<3 x float> %{{.*}})
+// CHECK-SPIRV: ret <3 x float> %hlsl.ddy.coarse
float3 test_f32_ddy_coarse3(float3 val) {
return ddy_coarse(val);
}
-// CHECK: define linkonce_odr hidden noundef nofpclass(nan inf) <4 x float> @
-// CHECK: %hlsl.ddy.coarse = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.dx.ddy.coarse.v4f32(<4 x float> %{{.*}})
+// CHECK-LABEL: <4 x float> @_Z20test_f32_ddy_coarse4Dv4_f
+// CHECK: %hlsl.ddy.coarse = call {{.*}} <4 x float> @llvm.dx.ddy.coarse.v4f32(<4 x float> %{{.*}})
// CHECK: ret <4 x float> %hlsl.ddy.coarse
+// CHECK-LABEL-SPIRV: <4 x float> @_Z20test_f32_ddy_coarse4Dv4_f
+// CHECK-SPIRV: %hlsl.ddy.coarse = call {{.*}} <4 x float> @llvm.spv.ddy.coarse.v4f32(<4 x float> %{{.*}})
+// CHECK-SPIRV: ret <4 x float> %hlsl.ddy.coarse
float4 test_f32_ddy_coarse4(float4 val) {
return ddy_coarse(val);
}
diff --git a/clang/test/SemaHLSL/BuiltIns/ddx-coarse-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/ddx-coarse-errors.hlsl
index 48b717a4af11f..6bb7d5c0f9a2c 100644
--- a/clang/test/SemaHLSL/BuiltIns/ddx-coarse-errors.hlsl
+++ b/clang/test/SemaHLSL/BuiltIns/ddx-coarse-errors.hlsl
@@ -20,4 +20,4 @@ float test_integer_scalar_input(int val) {
double test_double_scalar_input(double val) {
return __builtin_hlsl_elementwise_ddx_coarse(val);
// expected-error at -1 {{1st argument must be a scalar or vector of 16 or 32 bit floating-point types (was 'double')}}
-}
\ No newline at end of file
+}
diff --git a/clang/test/SemaHLSL/BuiltIns/ddy-coarse-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/ddy-coarse-errors.hlsl
index c9e9d17757f25..fe01ec0f4c4b0 100644
--- a/clang/test/SemaHLSL/BuiltIns/ddy-coarse-errors.hlsl
+++ b/clang/test/SemaHLSL/BuiltIns/ddy-coarse-errors.hlsl
@@ -18,4 +18,4 @@ float test_integer_scalar_input(int val) {
double test_double_scalar_input(double val) {
return __builtin_hlsl_elementwise_ddy_coarse(val);
// expected-error at -1 {{1st argument must be a scalar or vector of 16 or 32 bit floating-point types (was 'double')}}
-}
\ No newline at end of file
+}
diff --git a/llvm/test/CodeGen/DirectX/ddx_coarse.ll b/llvm/test/CodeGen/DirectX/ddx_coarse.ll
index bb4512a7a4341..986f7a57fd5ea 100644
--- a/llvm/test/CodeGen/DirectX/ddx_coarse.ll
+++ b/llvm/test/CodeGen/DirectX/ddx_coarse.ll
@@ -1,6 +1,6 @@
; RUN: opt -S -scalarizer -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s
-; Make sure dxil operation function calls for fwidth are generated for half/float and matching vectors
+; Make sure dxil operation function calls for ddx_coarse are generated for half/float and matching vectors
define noundef half @deriv_coarse_x_half(half noundef %a) {
; CHECK: call half @dx.op.unary.f16(i32 83, half %{{.*}})
diff --git a/llvm/test/CodeGen/DirectX/ddy_coarse.ll b/llvm/test/CodeGen/DirectX/ddy_coarse.ll
index 7321fc1a80975..24c6d6c9d745a 100644
--- a/llvm/test/CodeGen/DirectX/ddy_coarse.ll
+++ b/llvm/test/CodeGen/DirectX/ddy_coarse.ll
@@ -1,6 +1,6 @@
; RUN: opt -S -scalarizer -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s
-; Make sure dxil operation function calls for fwidth are generated for half/float and matching vectors
+; Make sure dxil operation function calls for ddy_coarse are generated for half/float and matching vectors
define noundef half @deriv_coarse_y_half(half noundef %a) {
; CHECK: call half @dx.op.unary.f16(i32 84, half %{{.*}})
More information about the llvm-commits
mailing list