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 <[email protected]>
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@-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@-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@-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@-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@-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@-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@-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@-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@-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@-1 {{too many arguments to function call, expected 1, have 
2}}
+}
+
+float mismatched_return(float2 val) {
+  return __builtin_spirv_ddx_coarse(val);
+  // expected-error@-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@-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@-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@-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@-1 {{too many arguments to function call, expected 1, have 
2}}
+}
+
+float mismatched_return(float2 val) {
+  return __builtin_spirv_ddy_coarse(val);
+  // expected-error@-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@-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@-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 <[email protected]>
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@-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@-1 {{too many arguments to function call, expected 1, have 
2}}
-}
-
-float mismatched_return(float2 val) {
-  return __builtin_spirv_ddx_coarse(val);
-  // expected-error@-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@-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@-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@-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@-1 {{too many arguments to function call, expected 1, have 
2}}
-}
-
-float mismatched_return(float2 val) {
-  return __builtin_spirv_ddy_coarse(val);
-  // expected-error@-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@-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@-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 <[email protected]>
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 <[email protected]>
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@-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@-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 %{{.*}})

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to