llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang-codegen Author: Farzon Lotfi (farzonl) <details> <summary>Changes</summary> closes #<!-- -->70071 - `CGBuiltin.cpp` - Add the unsigned\generic clamp intrinsic emitter. - `IntrinsicsDirectX.td` - add the `dx.clamp` & `dx.uclamp` intrinsics - `DXILIntrinsicExpansion.cpp` - add the `clamp` instruction expansion while maintaining vector form. - `SemaChecking.cpp` - Add `clamp` builtin Sema Checks. - `Builtins.td` - add a `clamp` builtin - `hlsl_intrinsics.h` - add the `clamp` api Why `clamp` as instruction expansion for DXIL? 1. SPIR-V has a GLSL `clamp` extension via: - [FClamp](https://registry.khronos.org/SPIR-V/specs/1.0/GLSL.std.450.html#FClamp) - [UClamp](https://registry.khronos.org/SPIR-V/specs/1.0/GLSL.std.450.html#UClamp) - [SClamp](https://registry.khronos.org/SPIR-V/specs/1.0/GLSL.std.450.html#SClamp) 2. Further Clamp lowers to `min(max( x, min_range ), max_range)` which we have float, signed, & unsigned dixilOps. --- Patch is 42.11 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/85424.diff 19 Files Affected: - (modified) clang/include/clang/Basic/Builtins.td (+6) - (modified) clang/lib/CodeGen/CGBuiltin.cpp (+15) - (modified) clang/lib/Headers/hlsl/hlsl_intrinsics.h (+110) - (modified) clang/lib/Sema/SemaChecking.cpp (+14-1) - (added) clang/test/CodeGenHLSL/builtins/clamp-builtin.hlsl (+8) - (added) clang/test/CodeGenHLSL/builtins/clamp.hlsl (+134) - (added) clang/test/SemaHLSL/BuiltIns/clamp-errors.hlsl (+91) - (modified) clang/test/SemaHLSL/BuiltIns/mad-errors.hlsl (+3-3) - (modified) llvm/include/llvm/IR/IntrinsicsDirectX.td (+2-1) - (modified) llvm/lib/Target/DirectX/DXIL.td (+10) - (modified) llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp (+50) - (added) llvm/test/CodeGen/DirectX/clamp-vec.ll (+74) - (added) llvm/test/CodeGen/DirectX/clamp.ll (+94) - (added) llvm/test/CodeGen/DirectX/fmax.ll (+31) - (added) llvm/test/CodeGen/DirectX/fmin.ll (+31) - (added) llvm/test/CodeGen/DirectX/smax.ll (+31) - (added) llvm/test/CodeGen/DirectX/smin.ll (+31) - (modified) llvm/test/CodeGen/DirectX/umax.ll (+15-14) - (added) llvm/test/CodeGen/DirectX/umin.ll (+31) ``````````diff diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 58a2d22e7641fc..64599aaee0ced7 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -4554,6 +4554,12 @@ def HLSLWaveActiveCountBits : LangBuiltin<"HLSL_LANG"> { let Prototype = "unsigned int(bool)"; } +def HLSLClamp : LangBuiltin<"HLSL_LANG"> { + let Spellings = ["__builtin_hlsl_elementwise_clamp"]; + let Attributes = [NoThrow, Const]; + let Prototype = "void(...)"; +} + def HLSLCreateHandle : LangBuiltin<"HLSL_LANG"> { let Spellings = ["__builtin_hlsl_create_handle"]; let Attributes = [NoThrow, Const]; diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index b09bf563622089..77fb1bc0f4eb3a 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -17981,6 +17981,21 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, /*ReturnType=*/llvm::Type::getInt1Ty(getLLVMContext()), Intrinsic::dx_any, ArrayRef<Value *>{Op0}, nullptr, "dx.any"); } + case Builtin::BI__builtin_hlsl_elementwise_clamp: { + Value *OpX = EmitScalarExpr(E->getArg(0)); + Value *OpMin = EmitScalarExpr(E->getArg(1)); + Value *OpMax = EmitScalarExpr(E->getArg(2)); + + QualType Ty = E->getArg(0)->getType(); + bool IsUnsigned = false; + if (auto *VecTy = Ty->getAs<VectorType>()) + Ty = VecTy->getElementType(); + IsUnsigned = Ty->isUnsignedIntegerType(); + return Builder.CreateIntrinsic( + /*ReturnType=*/OpX->getType(), + IsUnsigned ? Intrinsic::dx_uclamp : Intrinsic::dx_clamp, + ArrayRef<Value *>{OpX, OpMin, OpMax}, nullptr, "dx.clamp"); + } case Builtin::BI__builtin_hlsl_dot: { Value *Op0 = EmitScalarExpr(E->getArg(0)); Value *Op1 = EmitScalarExpr(E->getArg(1)); diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index 718fb9a9b35c04..5e703772b7ee4f 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -252,6 +252,116 @@ double3 ceil(double3); _HLSL_BUILTIN_ALIAS(__builtin_elementwise_ceil) double4 ceil(double4); +//===----------------------------------------------------------------------===// +// clamp builtins +//===----------------------------------------------------------------------===// + +/// \fn T clamp(T X, T Min, T Max) +/// \brief Clamps the specified value \a X to the specified +/// minimum ( \a Min) and maximum ( \a Max) range. +/// \param X A value to clamp. +/// \param Min The specified minimum range. +/// \param Max The specified maximum range. +/// +/// Returns The clamped value for the \a X parameter. +/// For values of -INF or INF, clamp will behave as expected. +/// However for values of NaN, the results are undefined. + +_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2) +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +half clamp(half, half, half); +_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2) +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +half2 clamp(half2, half2, half2); +_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2) +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +half3 clamp(half3, half3, half3); +_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2) +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +half4 clamp(half4, half4, half4); + +#ifdef __HLSL_ENABLE_16_BIT +_HLSL_AVAILABILITY(shadermodel, 6.2) +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +int16_t clamp(int16_t, int16_t, int16_t); +_HLSL_AVAILABILITY(shadermodel, 6.2) +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +int16_t2 clamp(int16_t2, int16_t2, int16_t2); +_HLSL_AVAILABILITY(shadermodel, 6.2) +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +int16_t3 clamp(int16_t3, int16_t3, int16_t3); +_HLSL_AVAILABILITY(shadermodel, 6.2) +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +int16_t4 clamp(int16_t4, int16_t4, int16_t4); + +_HLSL_AVAILABILITY(shadermodel, 6.2) +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +uint16_t clamp(uint16_t, uint16_t, uint16_t); +_HLSL_AVAILABILITY(shadermodel, 6.2) +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +uint16_t2 clamp(uint16_t2, uint16_t2, uint16_t2); +_HLSL_AVAILABILITY(shadermodel, 6.2) +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +uint16_t3 clamp(uint16_t3, uint16_t3, uint16_t3); +_HLSL_AVAILABILITY(shadermodel, 6.2) +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +uint16_t4 clamp(uint16_t4, uint16_t4, uint16_t4); +#endif + +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +int clamp(int, int, int); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +int2 clamp(int2, int2, int2); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +int3 clamp(int3, int3, int3); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +int4 clamp(int4, int4, int4); + +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +uint clamp(uint, uint, uint); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +uint2 clamp(uint2, uint2, uint2); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +uint3 clamp(uint3, uint3, uint3); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +uint4 clamp(uint4, uint4, uint4); + +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +int64_t clamp(int64_t, int64_t, int64_t); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +int64_t2 clamp(int64_t2, int64_t2, int64_t2); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +int64_t3 clamp(int64_t3, int64_t3, int64_t3); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +int64_t4 clamp(int64_t4, int64_t4, int64_t4); + +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +uint64_t clamp(uint64_t, uint64_t, uint64_t); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +uint64_t2 clamp(uint64_t2, uint64_t2, uint64_t2); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +uint64_t3 clamp(uint64_t3, uint64_t3, uint64_t3); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +uint64_t4 clamp(uint64_t4, uint64_t4, uint64_t4); + +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +float clamp(float, float, float); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +float2 clamp(float2, float2, float2); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +float3 clamp(float3, float3, float3); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +float4 clamp(float4, float4, float4); + +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +double clamp(double, double, double); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +double2 clamp(double2, double2, double2); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +double3 clamp(double3, double3, double3); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +double4 clamp(double4, double4, double4); + //===----------------------------------------------------------------------===// // cos builtins //===----------------------------------------------------------------------===// diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index d88a38eb6eb97b..c47b47d4670e53 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -5303,6 +5303,17 @@ bool Sema::CheckHLSLBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { return true; break; } + case Builtin::BI__builtin_hlsl_elementwise_clamp: { + if (checkArgCount(*this, TheCall, 3)) + return true; + if (CheckVectorElementCallArgs(this, TheCall)) + return true; + if (SemaBuiltinElementwiseTernaryMath( + TheCall, /*CheckForFloatArgs*/ + TheCall->getArg(0)->getType()->hasFloatingRepresentation())) + return true; + break; + } case Builtin::BI__builtin_hlsl_dot: { if (checkArgCount(*this, TheCall, 2)) return true; @@ -5351,7 +5362,9 @@ bool Sema::CheckHLSLBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { return true; if (CheckVectorElementCallArgs(this, TheCall)) return true; - if (SemaBuiltinElementwiseTernaryMath(TheCall, /*CheckForFloatArgs*/ false)) + if (SemaBuiltinElementwiseTernaryMath( + TheCall, /*CheckForFloatArgs*/ + TheCall->getArg(0)->getType()->hasFloatingRepresentation())) return true; } } diff --git a/clang/test/CodeGenHLSL/builtins/clamp-builtin.hlsl b/clang/test/CodeGenHLSL/builtins/clamp-builtin.hlsl new file mode 100644 index 00000000000000..e3ef26429e7e40 --- /dev/null +++ b/clang/test/CodeGenHLSL/builtins/clamp-builtin.hlsl @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -o - | FileCheck %s + +// CHECK-LABEL: builtin_test_clamp_int4 +// CHECK: %dx.clamp = call <4 x i32> @llvm.dx.clamp.v4i32(<4 x i32> %0, <4 x i32> %1, <4 x i32> %2) +// CHECK: ret <4 x i32> %dx.clamp +int4 builtin_test_clamp_int4(int4 p0, int4 p1, int4 p2) { + return __builtin_hlsl_elementwise_clamp(p0, p1, p2); +} diff --git a/clang/test/CodeGenHLSL/builtins/clamp.hlsl b/clang/test/CodeGenHLSL/builtins/clamp.hlsl new file mode 100644 index 00000000000000..029e48ffe25865 --- /dev/null +++ b/clang/test/CodeGenHLSL/builtins/clamp.hlsl @@ -0,0 +1,134 @@ +// RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \ +// RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \ +// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \ +// RUN: --check-prefixes=CHECK,NATIVE_HALF +// RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \ +// RUN: dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \ +// RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF + +#ifdef __HLSL_ENABLE_16_BIT +// NATIVE_HALF: define noundef i16 @ +// NATIVE_HALF: call i16 @llvm.dx.clamp.i16( +int16_t test_clamp_short(int16_t p0, int16_t p1) { return clamp(p0, p1,p1); } +// NATIVE_HALF: define noundef <2 x i16> @ +// NATIVE_HALF: call <2 x i16> @llvm.dx.clamp.v2i16( +int16_t2 test_clamp_short2(int16_t2 p0, int16_t2 p1) { return clamp(p0, p1,p1); } +// NATIVE_HALF: define noundef <3 x i16> @ +// NATIVE_HALF: call <3 x i16> @llvm.dx.clamp.v3i16 +int16_t3 test_clamp_short3(int16_t3 p0, int16_t3 p1) { return clamp(p0, p1,p1); } +// NATIVE_HALF: define noundef <4 x i16> @ +// NATIVE_HALF: call <4 x i16> @llvm.dx.clamp.v4i16 +int16_t4 test_clamp_short4(int16_t4 p0, int16_t4 p1) { return clamp(p0, p1,p1); } + +// NATIVE_HALF: define noundef i16 @ +// NATIVE_HALF: call i16 @llvm.dx.uclamp.i16( +uint16_t test_clamp_ushort(uint16_t p0, uint16_t p1) { return clamp(p0, p1,p1); } +// NATIVE_HALF: define noundef <2 x i16> @ +// NATIVE_HALF: call <2 x i16> @llvm.dx.uclamp.v2i16 +uint16_t2 test_clamp_ushort2(uint16_t2 p0, uint16_t2 p1) { return clamp(p0, p1,p1); } +// NATIVE_HALF: define noundef <3 x i16> @ +// NATIVE_HALF: call <3 x i16> @llvm.dx.uclamp.v3i16 +uint16_t3 test_clamp_ushort3(uint16_t3 p0, uint16_t3 p1) { return clamp(p0, p1,p1); } +// NATIVE_HALF: define noundef <4 x i16> @ +// NATIVE_HALF: call <4 x i16> @llvm.dx.uclamp.v4i16 +uint16_t4 test_clamp_ushort4(uint16_t4 p0, uint16_t4 p1) { return clamp(p0, p1,p1); } +#endif + +// CHECK: define noundef i32 @ +// CHECK: call i32 @llvm.dx.clamp.i32( +int test_clamp_int(int p0, int p1) { return clamp(p0, p1,p1); } +// CHECK: define noundef <2 x i32> @ +// CHECK: call <2 x i32> @llvm.dx.clamp.v2i32 +int2 test_clamp_int2(int2 p0, int2 p1) { return clamp(p0, p1,p1); } +// CHECK: define noundef <3 x i32> @ +// CHECK: call <3 x i32> @llvm.dx.clamp.v3i32 +int3 test_clamp_int3(int3 p0, int3 p1) { return clamp(p0, p1,p1); } +// CHECK: define noundef <4 x i32> @ +// CHECK: call <4 x i32> @llvm.dx.clamp.v4i32 +int4 test_clamp_int4(int4 p0, int4 p1) { return clamp(p0, p1,p1); } + +// CHECK: define noundef i32 @ +// CHECK: call i32 @llvm.dx.uclamp.i32( +int test_clamp_uint(uint p0, uint p1) { return clamp(p0, p1,p1); } +// CHECK: define noundef <2 x i32> @ +// CHECK: call <2 x i32> @llvm.dx.uclamp.v2i32 +uint2 test_clamp_uint2(uint2 p0, uint2 p1) { return clamp(p0, p1,p1); } +// CHECK: define noundef <3 x i32> @ +// CHECK: call <3 x i32> @llvm.dx.uclamp.v3i32 +uint3 test_clamp_uint3(uint3 p0, uint3 p1) { return clamp(p0, p1,p1); } +// CHECK: define noundef <4 x i32> @ +// CHECK: call <4 x i32> @llvm.dx.uclamp.v4i32 +uint4 test_clamp_uint4(uint4 p0, uint4 p1) { return clamp(p0, p1,p1); } + +// CHECK: define noundef i64 @ +// CHECK: call i64 @llvm.dx.clamp.i64( +int64_t test_clamp_long(int64_t p0, int64_t p1) { return clamp(p0, p1,p1); } +// CHECK: define noundef <2 x i64> @ +// CHECK: call <2 x i64> @llvm.dx.clamp.v2i64 +int64_t2 test_clamp_long2(int64_t2 p0, int64_t2 p1) { return clamp(p0, p1,p1); } +// CHECK: define noundef <3 x i64> @ +// CHECK: call <3 x i64> @llvm.dx.clamp.v3i64 +int64_t3 test_clamp_long3(int64_t3 p0, int64_t3 p1) { return clamp(p0, p1,p1); } +// CHECK: define noundef <4 x i64> @ +// CHECK: call <4 x i64> @llvm.dx.clamp.v4i64 +int64_t4 test_clamp_long4(int64_t4 p0, int64_t4 p1) { return clamp(p0, p1,p1); } + +// CHECK: define noundef i64 @ +// CHECK: call i64 @llvm.dx.uclamp.i64( +uint64_t test_clamp_long(uint64_t p0, uint64_t p1) { return clamp(p0, p1,p1); } +// CHECK: define noundef <2 x i64> @ +// CHECK: call <2 x i64> @llvm.dx.uclamp.v2i64 +uint64_t2 test_clamp_long2(uint64_t2 p0, uint64_t2 p1) { return clamp(p0, p1,p1); } +// CHECK: define noundef <3 x i64> @ +// CHECK: call <3 x i64> @llvm.dx.uclamp.v3i64 +uint64_t3 test_clamp_long3(uint64_t3 p0, uint64_t3 p1) { return clamp(p0, p1,p1); } +// CHECK: define noundef <4 x i64> @ +// CHECK: call <4 x i64> @llvm.dx.uclamp.v4i64 +uint64_t4 test_clamp_long4(uint64_t4 p0, uint64_t4 p1) { return clamp(p0, p1,p1); } + +// NATIVE_HALF: define noundef half @ +// NATIVE_HALF: call half @llvm.dx.clamp.f16( +// NO_HALF: define noundef float @"?test_clamp_half +// NO_HALF: call float @llvm.dx.clamp.f32( +half test_clamp_half(half p0, half p1) { return clamp(p0, p1,p1); } +// NATIVE_HALF: define noundef <2 x half> @ +// NATIVE_HALF: call <2 x half> @llvm.dx.clamp.v2f16 +// NO_HALF: define noundef <2 x float> @"?test_clamp_half2 +// NO_HALF: call <2 x float> @llvm.dx.clamp.v2f32( +half2 test_clamp_half2(half2 p0, half2 p1) { return clamp(p0, p1,p1); } +// NATIVE_HALF: define noundef <3 x half> @ +// NATIVE_HALF: call <3 x half> @llvm.dx.clamp.v3f16 +// NO_HALF: define noundef <3 x float> @"?test_clamp_half3 +// NO_HALF: call <3 x float> @llvm.dx.clamp.v3f32( +half3 test_clamp_half3(half3 p0, half3 p1) { return clamp(p0, p1,p1); } +// NATIVE_HALF: define noundef <4 x half> @ +// NATIVE_HALF: call <4 x half> @llvm.dx.clamp.v4f16 +// NO_HALF: define noundef <4 x float> @"?test_clamp_half4 +// NO_HALF: call <4 x float> @llvm.dx.clamp.v4f32( +half4 test_clamp_half4(half4 p0, half4 p1) { return clamp(p0, p1,p1); } + +// CHECK: define noundef float @"?test_clamp_float +// CHECK: call float @llvm.dx.clamp.f32( +float test_clamp_float(float p0, float p1) { return clamp(p0, p1,p1); } +// CHECK: define noundef <2 x float> @"?test_clamp_float2 +// CHECK: call <2 x float> @llvm.dx.clamp.v2f32 +float2 test_clamp_float2(float2 p0, float2 p1) { return clamp(p0, p1,p1); } +// CHECK: define noundef <3 x float> @"?test_clamp_float3 +// CHECK: call <3 x float> @llvm.dx.clamp.v3f32 +float3 test_clamp_float3(float3 p0, float3 p1) { return clamp(p0, p1,p1); } +// CHECK: define noundef <4 x float> @"?test_clamp_float4 +// CHECK: call <4 x float> @llvm.dx.clamp.v4f32 +float4 test_clamp_float4(float4 p0, float4 p1) { return clamp(p0, p1,p1); } + +// CHECK: define noundef double @ +// CHECK: call double @llvm.dx.clamp.f64( +double test_clamp_double(double p0, double p1) { return clamp(p0, p1,p1); } +// CHECK: define noundef <2 x double> @ +// CHECK: call <2 x double> @llvm.dx.clamp.v2f64 +double2 test_clamp_double2(double2 p0, double2 p1) { return clamp(p0, p1,p1); } +// CHECK: define noundef <3 x double> @ +// CHECK: call <3 x double> @llvm.dx.clamp.v3f64 +double3 test_clamp_double3(double3 p0, double3 p1) { return clamp(p0, p1,p1); } +// CHECK: define noundef <4 x double> @ +// CHECK: call <4 x double> @llvm.dx.clamp.v4f64 +double4 test_clamp_double4(double4 p0, double4 p1) { return clamp(p0, p1,p1); } diff --git a/clang/test/SemaHLSL/BuiltIns/clamp-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/clamp-errors.hlsl new file mode 100644 index 00000000000000..4c0e5315ce532e --- /dev/null +++ b/clang/test/SemaHLSL/BuiltIns/clamp-errors.hlsl @@ -0,0 +1,91 @@ +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -verify-ignore-unexpected + +float2 test_no_second_arg(float2 p0) { + return __builtin_hlsl_elementwise_clamp(p0); + // expected-error@-1 {{too few arguments to function call, expected 3, have 1}} +} + +float2 test_no_third_arg(float2 p0) { + return __builtin_hlsl_elementwise_clamp(p0, p0); + // expected-error@-1 {{too few arguments to function call, expected 3, have 2}} +} + +float2 test_too_many_arg(float2 p0) { + return __builtin_hlsl_elementwise_clamp(p0, p0, p0, p0); + // expected-error@-1 {{too many arguments to function call, expected 3, have 4}} +} + +float2 test_clamp_no_second_arg(float2 p0) { + return clamp(p0); + // expected-error@-1 {{no matching function for call to 'clamp'}} +} + +float2 test_clamp_vector_size_mismatch(float3 p0, float2 p1) { + return clamp(p0, p0, p1); + // expected-warning@-1 {{implicit conversion truncates vector: 'float3' (aka 'vector<float, 3>') to 'float __attribute__((ext_vector_type(2)))' (vector of 2 'float' values)}} +} + +float2 test_clamp_builtin_vector_size_mismatch(float3 p0, float2 p1) { + return __builtin_hlsl_elementwise_clamp(p0, p1, p1); + // expected-error@-1 {{all arguments to '__builtin_hlsl_elementwise_clamp' must have the same type}} +} + +float test_clamp_scalar_mismatch(float p0, half p1) { + return clamp(p1, p0, p1); + // expected-error@-1 {{call to 'clamp' is ambiguous}} +} + +float2 test_clamp_element_type_mismatch(half2 p0, float2 p1) { + return clamp(p1, p0, p1); + // expected-error@-1 {{call to 'clamp' is ambiguous}} +} + +float2 test_builtin_clamp_float2_splat(float p0, float2 p1) { + return __builtin_hlsl_elementwise_clamp(p0, p1, p1); + // expected-error@-1 {{all arguments to '__builtin_hlsl_elementwise_clamp' must be vectors}} +} + +float3 test_builtin_clamp_float3_splat(float p0, float3 p1) { + return __builtin_hlsl_elementwise_clamp(p0, p1, p1); + // expected-error@-1 {{all arguments to '__builtin_hlsl_elementwise_clamp' must be vectors}} +} + +float4 test_builtin_clamp_float4_splat(float p0, float4 p1) { + return __builtin_hlsl_elementwise_clamp(p0, p1, p1); + // expected-error@-1 {{all arguments to '__builtin_hlsl_elementwise_clamp' must be vectors}} +} + +float2 test_clamp_float2_int_splat(float2 p0, int p1) { + return __builtin_hlsl_elementwise_clamp(p0, p1, p1); + // expected-error@-1 {{all arguments to '__builtin_hlsl_elementwise_clamp' must be vectors}} +} + +float3 test_clamp_float3_int_splat(float3 p0, int p1) { + return __builtin_hlsl_elementwise_clamp(p0, p1, p1); + // expected-error@-1 {{all arguments to '__builtin_hlsl_elementwise_clamp' must be vectors}} +} + +float2 test_builtin_clamp_int_vect_to_float_vec_promotion(int2 p0, float p1) { + return __builtin_hlsl_elementwise_clamp(p0, p1, p1); + // expected-error@-1 {{all arguments to '__builtin_hlsl_elementwise_clamp' must be vectors}} +} + +float test_builtin_clamp_bool_type_promotion(bool p0) { + return __builtin_hlsl_elementwise_clamp(p0, p0, p0); + // expected-error@-1 {{1st argument must be a vector, integer or floating point type (was 'bool')}} +} + +float builtin_bool_to_float_type_promotion(float p0, bool p1) { + return __builtin_hlsl_elementwise_clamp(p0, p0, p1); + // expected-error@-1 {{3rd argument must be a floating point type (was 'bool')}} +} + +float builtin_bool_to_float_type_promotion2(bool p0, float p1) { + return __builtin_hlsl_elementwise_clamp(p1, p0, p1); + // expected-error@-1 {{2nd argument must be a floating point type (was 'bool')}} +} + +float builtin_clamp_int_to_float_promotion(float p0, int p1) { + return __built... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/85424 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits