Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions clang/include/clang/Basic/BuiltinsSPIRVVK.td
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,6 @@ 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 : SPIRVBuiltin<"void(...)", [NoThrow, Const, CustomTypeChecking]>;
def ddy : SPIRVBuiltin<"void(...)", [NoThrow, Const, CustomTypeChecking]>;
def fwidth : SPIRVBuiltin<"void(...)", [NoThrow, Const, CustomTypeChecking]>;
8 changes: 8 additions & 0 deletions clang/lib/CodeGen/TargetBuiltins/SPIR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,14 @@ 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:
return Builder.CreateIntrinsic(
/*ReturnType=*/getTypes().ConvertType(E->getType()), Intrinsic::spv_ddx,
ArrayRef<Value *>{EmitScalarExpr(E->getArg(0))}, nullptr, "spv.ddx");
case SPIRV::BI__builtin_spirv_ddy:
return Builder.CreateIntrinsic(
/*ReturnType=*/getTypes().ConvertType(E->getType()), Intrinsic::spv_ddy,
ArrayRef<Value *>{EmitScalarExpr(E->getArg(0))}, nullptr, "spv.ddy");
case SPIRV::BI__builtin_spirv_fwidth:
return Builder.CreateIntrinsic(
/*ReturnType=*/getTypes().ConvertType(E->getType()),
Expand Down
16 changes: 16 additions & 0 deletions clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,22 @@ constexpr K firstbithigh_impl(T X) {
return FBH;
}

template <typename T> constexpr T ddx_impl(T input) {
#if (__has_builtin(__builtin_spirv_ddx))
return __builtin_spirv_ddx(input);
#else
return __builtin_hlsl_elementwise_ddx_coarse(input);
#endif
}

template <typename T> constexpr T ddy_impl(T input) {
#if (__has_builtin(__builtin_spirv_ddy))
return __builtin_spirv_ddy(input);
#else
return __builtin_hlsl_elementwise_ddy_coarse(input);
#endif
}

template <typename T> constexpr T fwidth_impl(T input) {
#if (__has_builtin(__builtin_spirv_fwidth))
return __builtin_spirv_fwidth(input);
Expand Down
80 changes: 80 additions & 0 deletions clang/lib/Headers/hlsl/hlsl_intrinsics.h
Original file line number Diff line number Diff line change
Expand Up @@ -666,6 +666,86 @@ smoothstep(__detail::HLSL_FIXED_VECTOR<float, N> Min,
return __detail::smoothstep_vec_impl(Min, Max, X);
}

//===----------------------------------------------------------------------===//
// ddx builtin
//===----------------------------------------------------------------------===//

/// \fn T ddx(T x)
/// \brief Computes the sum of the absolute values of the partial derivatives
/// with regard to the x screen space coordinate.
/// \param x [in] The floating-point scalar or vector to process.
///
/// The return value is a floating-point scalar or vector where each element
/// holds the computation of the matching element in the input.

template <typename T>
_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
const inline __detail::enable_if_t<__detail::is_arithmetic<T>::Value &&
__detail::is_same<half, T>::value,
T> ddx(T input) {
return __detail::ddx_impl(input);
}

template <typename T>
const inline __detail::enable_if_t<
__detail::is_arithmetic<T>::Value && __detail::is_same<float, T>::value, T>
ddx(T input) {
return __detail::ddx_impl(input);
}

template <int N>
_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
const inline __detail::HLSL_FIXED_VECTOR<half, N> ddx(
__detail::HLSL_FIXED_VECTOR<half, N> input) {
return __detail::ddx_impl(input);
}

template <int N>
const inline __detail::HLSL_FIXED_VECTOR<float, N>
ddx(__detail::HLSL_FIXED_VECTOR<float, N> input) {
return __detail::ddx_impl(input);
}

//===----------------------------------------------------------------------===//
// ddy builtin
//===----------------------------------------------------------------------===//

/// \fn T ddy(T x)
/// \brief Computes the sum of the absolute values of the partial derivatives
/// with regard to the y screen space coordinate.
/// \param x [in] The floating-point scalar or vector to process.
///
/// The return value is a floating-point scalar or vector where each element
/// holds the computation of the matching element in the input.

template <typename T>
_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
const inline __detail::enable_if_t<__detail::is_arithmetic<T>::Value &&
__detail::is_same<half, T>::value,
T> ddy(T input) {
return __detail::ddy_impl(input);
}

template <typename T>
const inline __detail::enable_if_t<
__detail::is_arithmetic<T>::Value && __detail::is_same<float, T>::value, T>
ddy(T input) {
return __detail::ddy_impl(input);
}

template <int N>
_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
const inline __detail::HLSL_FIXED_VECTOR<half, N> ddy(
__detail::HLSL_FIXED_VECTOR<half, N> input) {
return __detail::ddy_impl(input);
}

template <int N>
const inline __detail::HLSL_FIXED_VECTOR<float, N>
ddy(__detail::HLSL_FIXED_VECTOR<float, N> input) {
return __detail::ddy_impl(input);
}

//===----------------------------------------------------------------------===//
// fwidth builtin
//===----------------------------------------------------------------------===//
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/Sema/SemaSPIRV.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,8 @@ 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:
case SPIRV::BI__builtin_spirv_ddy:
case SPIRV::BI__builtin_spirv_fwidth: {
if (SemaRef.checkArgCount(TheCall, 1))
return true;
Expand Down
86 changes: 86 additions & 0 deletions clang/test/CodeGenHLSL/builtins/ddx.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +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-pixel %s \
// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
// RUN: FileCheck %s --check-prefixes=CHECK-SPIRV

// CHECK-LABEL: define {{.*}} half @_ZN4hlsl8__detail8ddx_implIDhEET_S2_
// CHECK: %hlsl.ddx.coarse = call {{.*}} half @llvm.dx.ddx.coarse.f16(half %{{.*}})
// CHECK: ret half %hlsl.ddx.coarse
// CHECK-LABEL-SPIRV: half @_ZN4hlsl8__detail8ddx_implIDhEET_S2_
// CHECK-SPIRV: %spv.ddx = call {{.*}} half @llvm.spv.ddx.f16(half %{{.*}})
// CHECK-SPIRV: ret half %spv.ddx
half test_f16_ddx(half val) {
return ddx(val);
}

// CHECK-LABEL: define {{.*}} <2 x half> @_ZN4hlsl8__detail8ddx_implIDv2_DhEET_S3_
// 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> @_ZN4hlsl8__detail8ddx_implIDv2_DhEET_S3_
// CHECK-SPIRV: %spv.ddx = call {{.*}} <2 x half> @llvm.spv.ddx.v2f16(<2 x half> %{{.*}})
// CHECK-SPIRV: ret <2 x half> %spv.ddx
half2 test_f16_ddx2(half2 val) {
return ddx(val);
}

// CHECK-LABEL: define {{.*}} <3 x half> @_ZN4hlsl8__detail8ddx_implIDv3_DhEET_S3_
// 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> @_ZN4hlsl8__detail8ddx_implIDv3_DhEET_S3_
// CHECK-SPIRV: %spv.ddx = call {{.*}} <3 x half> @llvm.spv.ddx.v3f16(<3 x half> %{{.*}})
// CHECK-SPIRV: ret <3 x half> %spv.ddx
half3 test_f16_ddx3(half3 val) {
return ddx(val);
}

// CHECK-LABEL: define {{.*}} <4 x half> @_ZN4hlsl8__detail8ddx_implIDv4_DhEET_S3_
// 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> @_ZN4hlsl8__detail8ddx_implIDv4_DhEET_S3_
// CHECK-SPIRV: %spv.ddx = call {{.*}} <4 x half> @llvm.spv.ddx.v4f16(<4 x half> %{{.*}})
// CHECK-SPIRV: ret <4 x half> %spv.ddx
half4 test_f16_ddx4(half4 val) {
return ddx(val);
}

// CHECK-LABEL: define {{.*}} float @_ZN4hlsl8__detail8ddx_implIfEET_S2_
// CHECK: %hlsl.ddx.coarse = call {{.*}} float @llvm.dx.ddx.coarse.f32(float %{{.*}})
// CHECK: ret float %hlsl.ddx.coarse
// CHECK-LABEL-SPIRV: float @_ZN4hlsl8__detail8ddx_implIfEET_S2_
// CHECK-SPIRV: %spv.ddx = call {{.*}} float @llvm.spv.ddx.f32(float %{{.*}})
// CHECK-SPIRV: ret float %spv.ddx
float test_f32_ddx(float val) {
return ddx(val);
}

// CHECK-LABEL: define {{.*}} <2 x float> @_ZN4hlsl8__detail8ddx_implIDv2_fEET_S3_
// 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> @_ZN4hlsl8__detail8ddx_implIDv2_fEET_S3_
// CHECK-SPIRV: %spv.ddx = call {{.*}} <2 x float> @llvm.spv.ddx.v2f32(<2 x float> %{{.*}})
// CHECK-SPIRV: ret <2 x float> %spv.ddx
float2 test_f32_ddx2(float2 val) {
return ddx(val);
}

// CHECK-LABEL: define {{.*}} <3 x float> @_ZN4hlsl8__detail8ddx_implIDv3_fEET_S3_
// 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> @_ZN4hlsl8__detail8ddx_implIDv3_fEET_S3_
// CHECK-SPIRV: %spv.ddx = call {{.*}} <3 x float> @llvm.spv.ddx.v3f32(<3 x float> %{{.*}})
// CHECK-SPIRV: ret <3 x float> %spv.ddx
float3 test_f32_ddx3(float3 val) {
return ddx(val);
}

// CHECK-LABEL: define {{.*}} <4 x float> @_ZN4hlsl8__detail8ddx_implIDv4_fEET_S3_
// 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> @_ZN4hlsl8__detail8ddx_implIDv4_fEET_S3_
// CHECK-SPIRV: %spv.ddx = call {{.*}} <4 x float> @llvm.spv.ddx.v4f32(<4 x float> %{{.*}})
// CHECK-SPIRV: ret <4 x float> %spv.ddx
float4 test_f32_ddx4(float4 val) {
return ddx(val);
}
86 changes: 86 additions & 0 deletions clang/test/CodeGenHLSL/builtins/ddy.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +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-pixel %s \
// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
// RUN: FileCheck %s --check-prefixes=CHECK-SPIRV

// CHECK-LABEL: define {{.*}} half @_ZN4hlsl8__detail8ddy_implIDhEET_S2_
// CHECK: %hlsl.ddy.coarse = call {{.*}} half @llvm.dx.ddy.coarse.f16(half %{{.*}})
// CHECK: ret half %hlsl.ddy.coarse
// CHECK-LABEL-SPIRV: half @_ZN4hlsl8__detail8ddy_implIDhEET_S2_
// CHECK-SPIRV: %spv.ddy = call {{.*}} half @llvm.spv.ddy.f16(half %{{.*}})
// CHECK-SPIRV: ret half %spv.ddy
half test_f16_ddy(half val) {
return ddy(val);
}

// CHECK-LABEL: define {{.*}} <2 x half> @_ZN4hlsl8__detail8ddy_implIDv2_DhEET_S3_
// 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> @_ZN4hlsl8__detail8ddy_implIDv2_DhEET_S3_
// CHECK-SPIRV: %spv.ddy = call {{.*}} <2 x half> @llvm.spv.ddy.v2f16(<2 x half> %{{.*}})
// CHECK-SPIRV: ret <2 x half> %spv.ddy
half2 test_f16_ddy2(half2 val) {
return ddy(val);
}

// CHECK-LABEL: define {{.*}} <3 x half> @_ZN4hlsl8__detail8ddy_implIDv3_DhEET_S3_
// 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> @_ZN4hlsl8__detail8ddy_implIDv3_DhEET_S3_
// CHECK-SPIRV: %spv.ddy = call {{.*}} <3 x half> @llvm.spv.ddy.v3f16(<3 x half> %{{.*}})
// CHECK-SPIRV: ret <3 x half> %spv.ddy
half3 test_f16_ddy3(half3 val) {
return ddy(val);
}

// CHECK-LABEL: define {{.*}} <4 x half> @_ZN4hlsl8__detail8ddy_implIDv4_DhEET_S3_
// 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> @_ZN4hlsl8__detail8ddy_implIDv4_DhEET_S3_
// CHECK-SPIRV: %spv.ddy = call {{.*}} <4 x half> @llvm.spv.ddy.v4f16(<4 x half> %{{.*}})
// CHECK-SPIRV: ret <4 x half> %spv.ddy
half4 test_f16_ddy4(half4 val) {
return ddy(val);
}

// CHECK-LABEL: define {{.*}} float @_ZN4hlsl8__detail8ddy_implIfEET_S2_
// CHECK: %hlsl.ddy.coarse = call {{.*}} float @llvm.dx.ddy.coarse.f32(float %{{.*}})
// CHECK: ret float %hlsl.ddy.coarse
// CHECK-LABEL-SPIRV: float @_ZN4hlsl8__detail8ddy_implIfEET_S2_
// CHECK-SPIRV: %spv.ddy = call {{.*}} float @llvm.spv.ddy.f32(float %{{.*}})
// CHECK-SPIRV: ret float %spv.ddy
float test_f32_ddy(float val) {
return ddy(val);
}

// CHECK-LABEL: define {{.*}} <2 x float> @_ZN4hlsl8__detail8ddy_implIDv2_fEET_S3_
// 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> @_ZN4hlsl8__detail8ddy_implIDv2_fEET_S3_
// CHECK-SPIRV: %spv.ddy = call {{.*}} <2 x float> @llvm.spv.ddy.v2f32(<2 x float> %{{.*}})
// CHECK-SPIRV: ret <2 x float> %spv.ddy
float2 test_f32_ddy2(float2 val) {
return ddy(val);
}

// CHECK-LABEL: define {{.*}} <3 x float> @_ZN4hlsl8__detail8ddy_implIDv3_fEET_S3_
// 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> @_ZN4hlsl8__detail8ddy_implIDv3_fEET_S3_
// CHECK-SPIRV: %spv.ddy = call {{.*}} <3 x float> @llvm.spv.ddy.v3f32(<3 x float> %{{.*}})
// CHECK-SPIRV: ret <3 x float> %spv.ddy
float3 test_f32_ddy3(float3 val) {
return ddy(val);
}

// CHECK-LABEL: define {{.*}} <4 x float> @_ZN4hlsl8__detail8ddy_implIDv4_fEET_S3_
// 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> @_ZN4hlsl8__detail8ddy_implIDv4_fEET_S3_
// CHECK-SPIRV: %spv.ddy = call {{.*}} <4 x float> @llvm.spv.ddy.v4f32(<4 x float> %{{.*}})
// CHECK-SPIRV: ret <4 x float> %spv.ddy
float4 test_f32_ddy4(float4 val) {
return ddy(val);
}
41 changes: 41 additions & 0 deletions clang/test/CodeGenSPIRV/Builtins/ddx.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// RUN: %clang_cc1 -O1 -triple spirv-pc-vulkan-pixel %s -emit-llvm -o - | FileCheck %s

typedef _Float16 half;
typedef half half2 __attribute__((ext_vector_type(2)));
typedef half half3 __attribute__((ext_vector_type(3)));
typedef half half4 __attribute__((ext_vector_type(4)));
typedef float float2 __attribute__((ext_vector_type(2)));
typedef float float3 __attribute__((ext_vector_type(3)));
typedef float float4 __attribute__((ext_vector_type(4)));

// CHECK: [[ddx0:%.*]] = tail call half @llvm.spv.ddx.f16(half {{%.*}})
// CHECK: ret half [[ddx0]]
half test_ddx_half(half X) { return __builtin_spirv_ddx(X); }

// CHECK: [[ddx0:%.*]] = tail call <2 x half> @llvm.spv.ddx.v2f16(<2 x half> {{%.*}})
// CHECK: ret <2 x half> [[ddx0]]
half2 test_ddx_half2(half2 X) { return __builtin_spirv_ddx(X); }

// CHECK: [[ddx0:%.*]] = tail call <3 x half> @llvm.spv.ddx.v3f16(<3 x half> {{%.*}})
// CHECK: ret <3 x half> [[ddx0]]
half3 test_ddx_half3(half3 X) { return __builtin_spirv_ddx(X); }

// CHECK: [[ddx0:%.*]] = tail call <4 x half> @llvm.spv.ddx.v4f16(<4 x half> {{%.*}})
// CHECK: ret <4 x half> [[ddx0]]
half4 test_ddx_half4(half4 X) { return __builtin_spirv_ddx(X); }

// CHECK: [[ddx0:%.*]] = tail call float @llvm.spv.ddx.f32(float {{%.*}})
// CHECK: ret float [[ddx0]]
float test_ddx_float(float X) { return __builtin_spirv_ddx(X); }

// CHECK: [[ddx1:%.*]] = tail call <2 x float> @llvm.spv.ddx.v2f32(<2 x float> {{%.*}})
// CHECK: ret <2 x float> [[ddx1]]
float2 test_ddx_float2(float2 X) { return __builtin_spirv_ddx(X); }

// CHECK: [[ddx2:%.*]] = tail call <3 x float> @llvm.spv.ddx.v3f32(<3 x float> {{%.*}})
// CHECK: ret <3 x float> [[ddx2]]
float3 test_ddx_float3(float3 X) { return __builtin_spirv_ddx(X); }

// CHECK: [[ddx3:%.*]] = tail call <4 x float> @llvm.spv.ddx.v4f32(<4 x float> {{%.*}})
// CHECK: ret <4 x float> [[ddx3]]
float4 test_ddx_float4(float4 X) { return __builtin_spirv_ddx(X); }
41 changes: 41 additions & 0 deletions clang/test/CodeGenSPIRV/Builtins/ddy.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// RUN: %clang_cc1 -O1 -triple spirv-pc-vulkan-pixel %s -emit-llvm -o - | FileCheck %s

typedef _Float16 half;
typedef half half2 __attribute__((ext_vector_type(2)));
typedef half half3 __attribute__((ext_vector_type(3)));
typedef half half4 __attribute__((ext_vector_type(4)));
typedef float float2 __attribute__((ext_vector_type(2)));
typedef float float3 __attribute__((ext_vector_type(3)));
typedef float float4 __attribute__((ext_vector_type(4)));

// CHECK: [[ddy0:%.*]] = tail call half @llvm.spv.ddy.f16(half {{%.*}})
// CHECK: ret half [[ddy0]]
half test_ddy_half(half X) { return __builtin_spirv_ddy(X); }

// CHECK: [[ddy0:%.*]] = tail call <2 x half> @llvm.spv.ddy.v2f16(<2 x half> {{%.*}})
// CHECK: ret <2 x half> [[ddy0]]
half2 test_ddy_half2(half2 X) { return __builtin_spirv_ddy(X); }

// CHECK: [[ddy0:%.*]] = tail call <3 x half> @llvm.spv.ddy.v3f16(<3 x half> {{%.*}})
// CHECK: ret <3 x half> [[ddy0]]
half3 test_ddy_half3(half3 X) { return __builtin_spirv_ddy(X); }

// CHECK: [[ddy0:%.*]] = tail call <4 x half> @llvm.spv.ddy.v4f16(<4 x half> {{%.*}})
// CHECK: ret <4 x half> [[ddy0]]
half4 test_ddy_half4(half4 X) { return __builtin_spirv_ddy(X); }

// CHECK: [[ddy0:%.*]] = tail call float @llvm.spv.ddy.f32(float {{%.*}})
// CHECK: ret float [[ddy0]]
float test_ddy_float(float X) { return __builtin_spirv_ddy(X); }

// CHECK: [[ddy1:%.*]] = tail call <2 x float> @llvm.spv.ddy.v2f32(<2 x float> {{%.*}})
// CHECK: ret <2 x float> [[ddy1]]
float2 test_ddy_float2(float2 X) { return __builtin_spirv_ddy(X); }

// CHECK: [[ddy2:%.*]] = tail call <3 x float> @llvm.spv.ddy.v3f32(<3 x float> {{%.*}})
// CHECK: ret <3 x float> [[ddy2]]
float3 test_ddy_float3(float3 X) { return __builtin_spirv_ddy(X); }

// CHECK: [[ddy3:%.*]] = tail call <4 x float> @llvm.spv.ddy.v4f32(<4 x float> {{%.*}})
// CHECK: ret <4 x float> [[ddy3]]
float4 test_ddy_float4(float4 X) { return __builtin_spirv_ddy(X); }
Loading
Loading