[clang] [clang][HLSL] Add sign intrinsic part 3 (PR #101989)

Tim Gymnich via cfe-commits cfe-commits at lists.llvm.org
Thu Aug 29 11:10:00 PDT 2024


https://github.com/tgymnich updated https://github.com/llvm/llvm-project/pull/101989

>From 4516f38d4cba70f2368dc68c72e0024f3f3e0732 Mon Sep 17 00:00:00 2001
From: Tim Gymnich <tgymnich at icloud.com>
Date: Fri, 2 Aug 2024 21:40:24 +0200
Subject: [PATCH 1/5] [clang][HLSL] Add sign intrinsic part 3

---
 clang/include/clang/Basic/Builtins.td    |  6 ++
 clang/lib/CodeGen/CGBuiltin.cpp          | 17 ++++++
 clang/lib/CodeGen/CGHLSLRuntime.h        |  1 +
 clang/lib/Headers/hlsl/hlsl_intrinsics.h | 71 ++++++++++++++++++++++++
 clang/lib/Sema/SemaHLSL.cpp              | 17 ++++++
 5 files changed, 112 insertions(+)

diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index ac33672a32b336..c22b277efde90b 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4751,6 +4751,12 @@ def HLSLSaturate : LangBuiltin<"HLSL_LANG"> {
   let Prototype = "void(...)";
 }
 
+def HLSLSign : LangBuiltin<"HLSL_LANG"> {
+  let Spellings = ["__builtin_hlsl_elementwise_sign"];
+  let Attributes = [NoThrow, Const];
+  let Prototype = "int(...)";
+}
+
 // Builtins for XRay.
 def XRayCustomEvent : Builtin {
   let Spellings = ["__xray_customevent"];
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 4204c8ff276ab1..b0a0c41118da4a 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -18700,6 +18700,23 @@ case Builtin::BI__builtin_hlsl_elementwise_isinf: {
         llvm::FunctionType::get(IntTy, {}, false), "__hlsl_wave_get_lane_index",
         {}, false, true));
   }
+  case Builtin::BI__builtin_hlsl_elementwise_sign: {
+    Value *Op0 = EmitScalarExpr(E->getArg(0));
+    llvm::Type *Xty = Op0->getType();
+    llvm::Type *retType = llvm::Type::getInt32Ty(this->getLLVMContext());
+    if (Xty->isVectorTy()) {
+      auto *XVecTy = E->getArg(0)->getType()->getAs<VectorType>();
+      retType = llvm::VectorType::get(
+          retType, ElementCount::getFixed(XVecTy->getNumElements()));
+    }
+    if (!E->getArg(0)->getType()->hasFloatingRepresentation() &&
+        !E->getArg(0)->getType()->hasSignedIntegerRepresentation())
+      llvm_unreachable("sign operand must have a float or int representation");
+
+    return Builder.CreateIntrinsic(
+        retType, CGM.getHLSLRuntime().getSignIntrinsic(),
+        ArrayRef<Value *>{Op0}, nullptr, "hlsl.sign");
+  }
   }
   return nullptr;
 }
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h
index 55a4b97c160cd6..dc1013d1134d6a 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -80,6 +80,7 @@ class CGHLSLRuntime {
   GENERATE_HLSL_INTRINSIC_FUNCTION(Normalize, normalize)
   GENERATE_HLSL_INTRINSIC_FUNCTION(Rsqrt, rsqrt)
   GENERATE_HLSL_INTRINSIC_FUNCTION(Saturate, saturate)
+  GENERATE_HLSL_INTRINSIC_FUNCTION(Sign, sign)
   GENERATE_HLSL_INTRINSIC_FUNCTION(ThreadId, thread_id)
   GENERATE_HLSL_INTRINSIC_FUNCTION(FDot, fdot)
   GENERATE_HLSL_INTRINSIC_FUNCTION(SDot, sdot)
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
index 6d38b668fe770e..1c172094f2d02c 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
@@ -1796,5 +1796,76 @@ _HLSL_AVAILABILITY(shadermodel, 6.0)
 _HLSL_BUILTIN_ALIAS(__builtin_hlsl_wave_get_lane_index)
 __attribute__((convergent)) uint WaveGetLaneIndex();
 
+//===----------------------------------------------------------------------===//
+// sign builtins
+//===----------------------------------------------------------------------===//
+
+/// \fn T sign(T Val)
+/// \brief Returns -1 if \a Val is less than zero; 0 if \a Val equals zero; and
+/// 1 if \a Val is greater than zero. \param Val The input value.
+
+#ifdef __HLSL_ENABLE_16_BIT
+_HLSL_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
+int16_t sign(int16_t);
+_HLSL_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
+int16_t2 sign(int16_t2);
+_HLSL_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
+int16_t3 sign(int16_t3);
+_HLSL_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
+int16_t4 sign(int16_t4);
+#endif
+
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
+half sign(half);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
+half2 sign(half2);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
+half3 sign(half3);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
+half4 sign(half4);
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
+int sign(int);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
+int2 sign(int2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
+int3 sign(int3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
+int4 sign(int4);
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
+float sign(float);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
+float2 sign(float2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
+float3 sign(float3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
+float4 sign(float4);
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
+int64_t sign(int64_t);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
+int64_t2 sign(int64_t2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
+int64_t3 sign(int64_t3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
+int64_t4 sign(int64_t4);
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
+double sign(double);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
+double2 sign(double2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
+double3 sign(double3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
+double4 sign(double4);
 } // namespace hlsl
 #endif //_HLSL_HLSL_INTRINSICS_H_
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 714e8f5cfa9926..563ee37304131d 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -12,6 +12,7 @@
 #include "clang/AST/Decl.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/Basic/Builtins.h"
 #include "clang/Basic/DiagnosticSema.h"
 #include "clang/Basic/LLVM.h"
 #include "clang/Basic/TargetInfo.h"
@@ -1364,6 +1365,14 @@ bool CheckNoDoubleVectors(Sema *S, CallExpr *TheCall) {
   return CheckArgsTypesAreCorrect(S, TheCall, S->Context.FloatTy,
                                   checkDoubleVector);
 }
+bool CheckFloatingOrSignedIntRepresentation(Sema *S, CallExpr *TheCall) {
+  auto checkAllSignedTypes = [](clang::QualType PassedType) -> bool {
+    return !PassedType->hasSignedIntegerRepresentation() &&
+           !PassedType->hasFloatingRepresentation();
+  };
+  return CheckArgsTypesAreCorrect(S, TheCall, S->Context.IntTy,
+                                  checkAllSignedTypes);
+}
 
 bool CheckUnsignedIntRepresentation(Sema *S, CallExpr *TheCall) {
   auto checkAllUnsignedTypes = [](clang::QualType PassedType) -> bool {
@@ -1490,6 +1499,14 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
     TheCall->setType(ArgTyA);
     break;
   }
+  case Builtin::BI__builtin_hlsl_elementwise_sign: {
+    if (CheckFloatingOrSignedIntRepresentation(&SemaRef, TheCall))
+      return true;
+    if (SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
+      return true;
+    SetElementTypeAsReturnType(&SemaRef, TheCall, getASTContext().IntTy);
+    break;
+  }
   // Note these are llvm builtins that we want to catch invalid intrinsic
   // generation. Normal handling of these builitns will occur elsewhere.
   case Builtin::BI__builtin_elementwise_bitreverse: {

>From 3041d0ad28c3b4058fe684b03d63e6010f6cb40b Mon Sep 17 00:00:00 2001
From: Tim Gymnich <tgymnich at icloud.com>
Date: Fri, 2 Aug 2024 21:40:32 +0200
Subject: [PATCH 2/5] add tests

---
 clang/test/CodeGenHLSL/builtins/sign.hlsl     | 209 ++++++++++++++++++
 clang/test/SemaHLSL/BuiltIns/sign-errors.hlsl |  16 ++
 2 files changed, 225 insertions(+)
 create mode 100644 clang/test/CodeGenHLSL/builtins/sign.hlsl
 create mode 100644 clang/test/SemaHLSL/BuiltIns/sign-errors.hlsl

diff --git a/clang/test/CodeGenHLSL/builtins/sign.hlsl b/clang/test/CodeGenHLSL/builtins/sign.hlsl
new file mode 100644
index 00000000000000..61596764231ec4
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/sign.hlsl
@@ -0,0 +1,209 @@
+// RUN: %clang_cc1 -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,DXIL_CHECK,DXIL_NATIVE_HALF,NATIVE_HALF
+// RUN: %clang_cc1 -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,DXIL_CHECK,NO_HALF,DXIL_NO_HALF
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
+// RUN:   spirv-unknown-vulkan-compute %s -fnative-half-type \
+// RUN:   -emit-llvm -disable-llvm-passes -o - | FileCheck %s \
+// RUN:   --check-prefixes=CHECK,SPIR_CHECK,NATIVE_HALF,SPIR_NATIVE_HALF
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
+// RUN:   spirv-unknown-vulkan-compute %s -emit-llvm -disable-llvm-passes \
+// RUN:   -o - | FileCheck %s --check-prefixes=CHECK,SPIR_CHECK,NO_HALF,SPIR_NO_HALF
+
+// DXIL_NATIVE_HALF: define noundef i32 @
+// SPIR_NATIVE_HALF: define spir_func noundef i32 @
+// DXIL_NATIVE_HALF: %hlsl.sign = call i32 @llvm.dx.sign.f16(
+// SPIR_NATIVE_HALF: %hlsl.sign = call i32 @llvm.spv.sign.f16(
+// NATIVE_HALF: ret i32 %hlsl.sign
+// DXIL_NO_HALF: define noundef i32 @
+// SPIR_NO_HALF: define spir_func noundef i32 @
+// DXIL_NO_HALF: %hlsl.sign = call i32 @llvm.dx.sign.f32(
+// SPIR_NO_HALF: %hlsl.sign = call i32 @llvm.spv.sign.f32(
+// NO_HALF: ret i32 %hlsl.sign
+int test_sign_half(half p0) { return sign(p0); }
+
+// DXIL_NATIVE_HALF: define noundef <2 x i32> @
+// SPIR_NATIVE_HALF: define spir_func noundef <2 x i32> @
+// DXIL_NATIVE_HALF: %hlsl.sign = call <2 x i32> @llvm.dx.sign.v2f16(
+// SPIR_NATIVE_HALF: %hlsl.sign = call <2 x i32> @llvm.spv.sign.v2f16(
+// NATIVE_HALF: ret <2 x i32> %hlsl.sign
+// DXIL_NO_HALF: define noundef <2 x i32> @
+// SPIR_NO_HALF: define spir_func noundef <2 x i32> @
+// DXIL_NO_HALF: %hlsl.sign = call <2 x i32> @llvm.dx.sign.v2f32(
+// SPIR_NO_HALF: %hlsl.sign = call <2 x i32> @llvm.spv.sign.v2f32(
+// NO_HALF: ret <2 x i32> %hlsl.sign
+int2 test_sign_half2(half2 p0) { return sign(p0); }
+
+// DXIL_NATIVE_HALF: define noundef <3 x i32> @
+// SPIR_NATIVE_HALF: define spir_func noundef <3 x i32> @
+// DXIL_NATIVE_HALF: %hlsl.sign = call <3 x i32> @llvm.dx.sign.v3f16(
+// SPIR_NATIVE_HALF: %hlsl.sign = call <3 x i32> @llvm.spv.sign.v3f16(
+// NATIVE_HALF: ret <3 x i32> %hlsl.sign
+// DXIL_NO_HALF: define noundef <3 x i32> @
+// SPIR_NO_HALF: define spir_func noundef <3 x i32> @
+// DXIL_NO_HALF: %hlsl.sign = call <3 x i32> @llvm.dx.sign.v3f32(
+// SPIR_NO_HALF: %hlsl.sign = call <3 x i32> @llvm.spv.sign.v3f32(
+// NO_HALF: ret <3 x i32> %hlsl.sign
+int3 test_sign_half3(half3 p0) { return sign(p0); }
+
+// DXIL_NATIVE_HALF: define noundef <4 x i32> @
+// SPIR_NATIVE_HALF: define spir_func noundef <4 x i32> @
+// DXIL_NATIVE_HALF: %hlsl.sign = call <4 x i32> @llvm.dx.sign.v4f16(
+// SPIR_NATIVE_HALF: %hlsl.sign = call <4 x i32> @llvm.spv.sign.v4f16(
+// NATIVE_HALF: ret <4 x i32> %hlsl.sign
+// DXIL_NO_HALF: define noundef <4 x i32> @
+// SPIR_NO_HALF: define spir_func noundef <4 x i32> @
+// DXIL_NO_HALF: %hlsl.sign = call <4 x i32> @llvm.dx.sign.v4f32(
+// SPIR_NO_HALF: %hlsl.sign = call <4 x i32> @llvm.spv.sign.v4f32(
+// NO_HALF: ret <4 x i32> %hlsl.sign
+int4 test_sign_half4(half4 p0) { return sign(p0); }
+
+
+// DXIL_CHECK: define noundef i32 @
+// SPIR_CHECK: define spir_func noundef i32 @
+// DXIL_CHECK: %hlsl.sign = call i32 @llvm.dx.sign.f32(
+// SPIR_CHECK: %hlsl.sign = call i32 @llvm.spv.sign.f32(
+// CHECK: ret i32 %hlsl.sign
+int test_sign_float(float p0) { return sign(p0); }
+
+// DXIL_CHECK: define noundef <2 x i32> @
+// SPIR_CHECK: define spir_func noundef <2 x i32> @
+// DXIL_CHECK: %hlsl.sign = call <2 x i32> @llvm.dx.sign.v2f32(
+// SPIR_CHECK: %hlsl.sign = call <2 x i32> @llvm.spv.sign.v2f32(
+// CHECK: ret <2 x i32> %hlsl.sign
+int2 test_sign_float2(float2 p0) { return sign(p0); }
+
+// DXIL_CHECK: define noundef <3 x i32> @
+// SPIR_CHECK: define spir_func noundef <3 x i32> @
+// DXIL_CHECK: %hlsl.sign = call <3 x i32> @llvm.dx.sign.v3f32(
+// SPIR_CHECK: %hlsl.sign = call <3 x i32> @llvm.spv.sign.v3f32(
+// CHECK: ret <3 x i32> %hlsl.sign
+int3 test_sign_float3(float3 p0) { return sign(p0); }
+
+// DXIL_CHECK: define noundef <4 x i32> @
+// SPIR_CHECK: define spir_func noundef <4 x i32> @
+// DXIL_CHECK: %hlsl.sign = call <4 x i32> @llvm.dx.sign.v4f32(
+// SPIR_CHECK: %hlsl.sign = call <4 x i32> @llvm.spv.sign.v4f32(
+// CHECK: ret <4 x i32> %hlsl.sign
+int4 test_sign_float4(float4 p0) { return sign(p0); }
+
+
+// DXIL_CHECK: define noundef i32 @
+// SPIR_CHECK: define spir_func noundef i32 @
+// DXIL_CHECK: %hlsl.sign = call i32 @llvm.dx.sign.f64(
+// SPIR_CHECK: %hlsl.sign = call i32 @llvm.spv.sign.f64(
+// CHECK: ret i32 %hlsl.sign
+int test_sign_double(double p0) { return sign(p0); }
+
+// DXIL_CHECK: define noundef <2 x i32> @
+// SPIR_CHECK: define spir_func noundef <2 x i32> @
+// DXIL_CHECK: %hlsl.sign = call <2 x i32> @llvm.dx.sign.v2f64(
+// SPIR_CHECK: %hlsl.sign = call <2 x i32> @llvm.spv.sign.v2f64(
+// CHECK: ret <2 x i32> %hlsl.sign
+int2 test_sign_double2(double2 p0) { return sign(p0); }
+
+// DXIL_CHECK: define noundef <3 x i32> @
+// SPIR_CHECK: define spir_func noundef <3 x i32> @
+// DXIL_CHECK: %hlsl.sign = call <3 x i32> @llvm.dx.sign.v3f64(
+// SPIR_CHECK: %hlsl.sign = call <3 x i32> @llvm.spv.sign.v3f64(
+// CHECK: ret <3 x i32> %hlsl.sign
+int3 test_sign_double3(double3 p0) { return sign(p0); }
+
+// DXIL_CHECK: define noundef <4 x i32> @
+// SPIR_CHECK: define spir_func noundef <4 x i32> @
+// DXIL_CHECK: %hlsl.sign = call <4 x i32> @llvm.dx.sign.v4f64(
+// SPIR_CHECK: %hlsl.sign = call <4 x i32> @llvm.spv.sign.v4f64(
+// CHECK: ret <4 x i32> %hlsl.sign
+int4 test_sign_double4(double4 p0) { return sign(p0); }
+
+
+#ifdef __HLSL_ENABLE_16_BIT
+// DXIL_NATIVE_HALF: define noundef i32 @
+// SPIR_NATIVE_HALF: define spir_func noundef i32 @
+// DXIL_NATIVE_HALF: %hlsl.sign = call i32 @llvm.dx.sign.i16(
+// SPIR_NATIVE_HALF: %hlsl.sign = call i32 @llvm.spv.sign.i16(
+// NATIVE_HALF: ret i32 %hlsl.sign
+int test_sign_int16_t(int16_t p0) { return sign(p0); }
+
+// DXIL_NATIVE_HALF: define noundef <2 x i32> @
+// SPIR_NATIVE_HALF: define spir_func noundef <2 x i32> @
+// DXIL_NATIVE_HALF: %hlsl.sign = call <2 x i32> @llvm.dx.sign.v2i16(
+// SPIR_NATIVE_HALF: %hlsl.sign = call <2 x i32> @llvm.spv.sign.v2i16(
+// NATIVE_HALF: ret <2 x i32> %hlsl.sign
+int2 test_sign_int16_t2(int16_t2 p0) { return sign(p0); }
+
+// DXIL_NATIVE_HALF: define noundef <3 x i32> @
+// SPIR_NATIVE_HALF: define spir_func noundef <3 x i32> @
+// DXIL_NATIVE_HALF: %hlsl.sign = call <3 x i32> @llvm.dx.sign.v3i16(
+// SPIR_NATIVE_HALF: %hlsl.sign = call <3 x i32> @llvm.spv.sign.v3i16(
+// NATIVE_HALF: ret <3 x i32> %hlsl.sign
+int3 test_sign_int16_t3(int16_t3 p0) { return sign(p0); }
+
+// DXIL_NATIVE_HALF: define noundef <4 x i32> @
+// SPIR_NATIVE_HALF: define spir_func noundef <4 x i32> @
+// DXIL_NATIVE_HALF: %hlsl.sign = call <4 x i32> @llvm.dx.sign.v4i16(
+// SPIR_NATIVE_HALF: %hlsl.sign = call <4 x i32> @llvm.spv.sign.v4i16(
+// NATIVE_HALF: ret <4 x i32> %hlsl.sign
+int4 test_sign_int16_t4(int16_t4 p0) { return sign(p0); }
+#endif // __HLSL_ENABLE_16_BIT
+
+
+// DXIL_CHECK: define noundef i32 @
+// SPIR_CHECK: define spir_func noundef i32 @
+// DXIL_CHECK: %hlsl.sign = call i32 @llvm.dx.sign.i32(
+// SPIR_CHECK: %hlsl.sign = call i32 @llvm.spv.sign.i32(
+// CHECK: ret i32 %hlsl.sign
+int test_sign_int(int p0) { return sign(p0); }
+
+// DXIL_CHECK: define noundef <2 x i32> @
+// SPIR_CHECK: define spir_func noundef <2 x i32> @
+// DXIL_CHECK: %hlsl.sign = call <2 x i32> @llvm.dx.sign.v2i32(
+// SPIR_CHECK: %hlsl.sign = call <2 x i32> @llvm.spv.sign.v2i32(
+// CHECK: ret <2 x i32> %hlsl.sign
+int2 test_sign_int2(int2 p0) { return sign(p0); }
+
+// DXIL_CHECK: define noundef <3 x i32> @
+// SPIR_CHECK: define spir_func noundef <3 x i32> @
+// DXIL_CHECK: %hlsl.sign = call <3 x i32> @llvm.dx.sign.v3i32(
+// SPIR_CHECK: %hlsl.sign = call <3 x i32> @llvm.spv.sign.v3i32(
+// CHECK: ret <3 x i32> %hlsl.sign
+int3 test_sign_int3(int3 p0) { return sign(p0); }
+
+// DXIL_CHECK: define noundef <4 x i32> @
+// SPIR_CHECK: define spir_func noundef <4 x i32> @
+// DXIL_CHECK: %hlsl.sign = call <4 x i32> @llvm.dx.sign.v4i32(
+// SPIR_CHECK: %hlsl.sign = call <4 x i32> @llvm.spv.sign.v4i32(
+// CHECK: ret <4 x i32> %hlsl.sign
+int4 test_sign_int4(int4 p0) { return sign(p0); }
+
+
+// DXIL_CHECK: define noundef i32 @
+// SPIR_CHECK: define spir_func noundef i32 @
+// DXIL_CHECK: %hlsl.sign = call i32 @llvm.dx.sign.i64(
+// SPIR_CHECK: %hlsl.sign = call i32 @llvm.spv.sign.i64(
+// CHECK: ret i32 %hlsl.sign
+int test_sign_int64_t(int64_t p0) { return sign(p0); }
+
+// DXIL_CHECK: define noundef <2 x i32> @
+// SPIR_CHECK: define spir_func noundef <2 x i32> @
+// DXIL_CHECK: %hlsl.sign = call <2 x i32> @llvm.dx.sign.v2i64(
+// SPIR_CHECK: %hlsl.sign = call <2 x i32> @llvm.spv.sign.v2i64(
+// CHECK: ret <2 x i32> %hlsl.sign
+int2 test_sign_int64_t2(int64_t2 p0) { return sign(p0); }
+
+// DXIL_CHECK: define noundef <3 x i32> @
+// SPIR_CHECK: define spir_func noundef <3 x i32> @
+// DXIL_CHECK: %hlsl.sign = call <3 x i32> @llvm.dx.sign.v3i64(
+// SPIR_CHECK: %hlsl.sign = call <3 x i32> @llvm.spv.sign.v3i64(
+// CHECK: ret <3 x i32> %hlsl.sign
+int3 test_sign_int64_t3(int64_t3 p0) { return sign(p0); }
+
+// DXIL_CHECK: define noundef <4 x i32> @
+// SPIR_CHECK: define spir_func noundef <4 x i32> @
+// DXIL_CHECK: %hlsl.sign = call <4 x i32> @llvm.dx.sign.v4i64(
+// SPIR_CHECK: %hlsl.sign = call <4 x i32> @llvm.spv.sign.v4i64(
+// CHECK: ret <4 x i32> %hlsl.sign
+int4 test_sign_int64_t4(int64_t4 p0) { return sign(p0); }
diff --git a/clang/test/SemaHLSL/BuiltIns/sign-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/sign-errors.hlsl
new file mode 100644
index 00000000000000..b67725fc77e52e
--- /dev/null
+++ b/clang/test/SemaHLSL/BuiltIns/sign-errors.hlsl
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -verify-ignore-unexpected
+
+bool test_too_few_arg() {
+  return __builtin_hlsl_elementwise_sign();
+  // expected-error at -1 {{too few arguments to function call, expected 1, have 0}}
+}
+
+bool2 test_too_many_arg(float2 p0) {
+  return __builtin_hlsl_elementwise_sign(p0, p0);
+  // expected-error at -1 {{too many arguments to function call, expected 1, have 2}}
+}
+
+bool builtin_bool_to_float_type_promotion(bool p1) {
+  return __builtin_hlsl_elementwise_sign(p1);
+  // expected-error at -1 {passing 'bool' to parameter of incompatible type 'float'}}
+}

>From dafb7693463744898342308c9d5637b674b2da74 Mon Sep 17 00:00:00 2001
From: Tim Gymnich <tgymnich at icloud.com>
Date: Sun, 11 Aug 2024 13:29:53 +0200
Subject: [PATCH 3/5] fix prototype

---
 clang/include/clang/Basic/Builtins.td | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index c22b277efde90b..47d37f9f07e23f 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4754,7 +4754,7 @@ def HLSLSaturate : LangBuiltin<"HLSL_LANG"> {
 def HLSLSign : LangBuiltin<"HLSL_LANG"> {
   let Spellings = ["__builtin_hlsl_elementwise_sign"];
   let Attributes = [NoThrow, Const];
-  let Prototype = "int(...)";
+  let Prototype = "void(...)";
 }
 
 // Builtins for XRay.

>From 0efd43ea767faeabcc09547d5a81b1ce297c9988 Mon Sep 17 00:00:00 2001
From: Tim Gymnich <tgymnich at icloud.com>
Date: Sun, 11 Aug 2024 13:36:47 +0200
Subject: [PATCH 4/5] fix intrinsic return typers

---
 clang/lib/Headers/hlsl/hlsl_intrinsics.h | 40 ++++++++++++------------
 1 file changed, 20 insertions(+), 20 deletions(-)

diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
index 1c172094f2d02c..e2a40d7f0bb74d 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
@@ -1807,30 +1807,30 @@ __attribute__((convergent)) uint WaveGetLaneIndex();
 #ifdef __HLSL_ENABLE_16_BIT
 _HLSL_AVAILABILITY(shadermodel, 6.2)
 _HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
-int16_t sign(int16_t);
+int sign(int16_t);
 _HLSL_AVAILABILITY(shadermodel, 6.2)
 _HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
-int16_t2 sign(int16_t2);
+int2 sign(int16_t2);
 _HLSL_AVAILABILITY(shadermodel, 6.2)
 _HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
-int16_t3 sign(int16_t3);
+int3 sign(int16_t3);
 _HLSL_AVAILABILITY(shadermodel, 6.2)
 _HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
-int16_t4 sign(int16_t4);
+int4 sign(int16_t4);
 #endif
 
 _HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
 _HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
-half sign(half);
+int sign(half);
 _HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
 _HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
-half2 sign(half2);
+int2 sign(half2);
 _HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
 _HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
-half3 sign(half3);
+int3 sign(half3);
 _HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
 _HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
-half4 sign(half4);
+int4 sign(half4);
 
 _HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
 int sign(int);
@@ -1842,30 +1842,30 @@ _HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
 int4 sign(int4);
 
 _HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
-float sign(float);
+int sign(float);
 _HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
-float2 sign(float2);
+int2 sign(float2);
 _HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
-float3 sign(float3);
+int3 sign(float3);
 _HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
-float4 sign(float4);
+int4 sign(float4);
 
 _HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
-int64_t sign(int64_t);
+int sign(int64_t);
 _HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
-int64_t2 sign(int64_t2);
+int2 sign(int64_t2);
 _HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
-int64_t3 sign(int64_t3);
+int3 sign(int64_t3);
 _HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
-int64_t4 sign(int64_t4);
+int4 sign(int64_t4);
 
 _HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
-double sign(double);
+int sign(double);
 _HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
-double2 sign(double2);
+int2 sign(double2);
 _HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
-double3 sign(double3);
+int3 sign(double3);
 _HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
-double4 sign(double4);
+int4 sign(double4);
 } // namespace hlsl
 #endif //_HLSL_HLSL_INTRINSICS_H_

>From 78fd3c27d6d74518f8921679947927e9a3b762ac Mon Sep 17 00:00:00 2001
From: Tim Gymnich <tgymnich at icloud.com>
Date: Thu, 15 Aug 2024 14:45:49 +0200
Subject: [PATCH 5/5] replace llvm_unreachable with assertion

---
 clang/lib/CodeGen/CGBuiltin.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index b0a0c41118da4a..479c1f57218cbf 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -18709,9 +18709,9 @@ case Builtin::BI__builtin_hlsl_elementwise_isinf: {
       retType = llvm::VectorType::get(
           retType, ElementCount::getFixed(XVecTy->getNumElements()));
     }
-    if (!E->getArg(0)->getType()->hasFloatingRepresentation() &&
-        !E->getArg(0)->getType()->hasSignedIntegerRepresentation())
-      llvm_unreachable("sign operand must have a float or int representation");
+    assert((E->getArg(0)->getType()->hasFloatingRepresentation() ||
+            E->getArg(0)->getType()->hasSignedIntegerRepresentation()) &&
+           "sign operand must have a float or int representation");
 
     return Builder.CreateIntrinsic(
         retType, CGM.getHLSLRuntime().getSignIntrinsic(),



More information about the cfe-commits mailing list