[clang] Adding `asuint` implementation to hlsl (PR #107292)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Sep 10 08:50:10 PDT 2024
https://github.com/joaosaffran updated https://github.com/llvm/llvm-project/pull/107292
>From a88a4eda4ce2ad32ee2ec02549b25c9f08aa14e9 Mon Sep 17 00:00:00 2001
From: Joao Saffran <jderezende at microsoft.com>
Date: Tue, 3 Sep 2024 19:06:22 +0000
Subject: [PATCH 1/4] Adding `asuint` implementation to hlsl
---
clang/include/clang/Basic/Builtins.td | 6 +++
clang/lib/CodeGen/CGBuiltin.cpp | 17 +++++++
clang/lib/Headers/hlsl/hlsl_intrinsics.h | 38 ++++++++++-----
clang/lib/Sema/SemaHLSL.cpp | 19 ++++++++
clang/test/CodeGenHLSL/builtins/asuint.hlsl | 53 +++++++++++++++++++++
5 files changed, 122 insertions(+), 11 deletions(-)
create mode 100644 clang/test/CodeGenHLSL/builtins/asuint.hlsl
diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index 92118418d9d459..83bca9b342ef15 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4751,6 +4751,12 @@ def HLSLRcp : LangBuiltin<"HLSL_LANG"> {
let Prototype = "void(...)";
}
+def HLSLAsUint : LangBuiltin<"HLSL_LANG"> {
+ let Spellings = ["__builtin_hlsl_elementwise_asuint"];
+ let Attributes = [NoThrow, Const];
+ let Prototype = "void(...)";
+}
+
def HLSLRSqrt : LangBuiltin<"HLSL_LANG"> {
let Spellings = ["__builtin_hlsl_elementwise_rsqrt"];
let Attributes = [NoThrow, Const];
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index da7a1a55da5313..4a6a60fcac8a14 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -27,9 +27,11 @@
#include "clang/AST/Decl.h"
#include "clang/AST/OSLog.h"
#include "clang/AST/OperationKinds.h"
+#include "clang/Basic/Builtins.h"
#include "clang/Basic/TargetBuiltins.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/TargetOptions.h"
+#include "clang/Basic/TokenKinds.h"
#include "clang/CodeGen/CGFunctionInfo.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "llvm/ADT/APFloat.h"
@@ -39,6 +41,7 @@
#include "llvm/ADT/StringExtras.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/InlineAsm.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/IntrinsicsAArch64.h"
@@ -62,6 +65,7 @@
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/ScopedPrinter.h"
+#include "llvm/Support/raw_ostream.h"
#include "llvm/TargetParser/AArch64TargetParser.h"
#include "llvm/TargetParser/RISCVISAInfo.h"
#include "llvm/TargetParser/X86TargetParser.h"
@@ -18815,6 +18819,19 @@ 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_asuint: {
+ Value *Op = EmitScalarExpr(E->getArg(0));
+ E->dump();
+ llvm::Type *DestTy = llvm::Type::getInt32Ty(this->getLLVMContext());
+
+ if (Op -> getType()->isVectorTy()){
+ auto VecTy = E->getArg(0)->getType()->getAs<VectorType>();
+ DestTy = llvm::VectorType::get(DestTy, VecTy->getNumElements(),
+ VecTy->isSizelessVectorType());
+ }
+
+ return Builder.CreateBitCast(Op, DestTy);
+ }
case Builtin::BI__builtin_hlsl_wave_is_first_lane: {
Intrinsic::ID ID = CGM.getHLSLRuntime().getWaveIsFirstLaneIntrinsic();
return EmitRuntimeCall(Intrinsic::getDeclaration(&CGM.getModule(), ID));
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
index 5c08a45a35377d..18426597569098 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
@@ -367,17 +367,6 @@ bool any(double4);
/// \brief Returns the arcsine of the input value, \a Val.
/// \param Val The input value.
-#ifdef __HLSL_ENABLE_16_BIT
-_HLSL_BUILTIN_ALIAS(__builtin_elementwise_asin)
-half asin(half);
-_HLSL_BUILTIN_ALIAS(__builtin_elementwise_asin)
-half2 asin(half2);
-_HLSL_BUILTIN_ALIAS(__builtin_elementwise_asin)
-half3 asin(half3);
-_HLSL_BUILTIN_ALIAS(__builtin_elementwise_asin)
-half4 asin(half4);
-#endif
-
_HLSL_BUILTIN_ALIAS(__builtin_elementwise_asin)
float asin(float);
_HLSL_BUILTIN_ALIAS(__builtin_elementwise_asin)
@@ -387,6 +376,33 @@ float3 asin(float3);
_HLSL_BUILTIN_ALIAS(__builtin_elementwise_asin)
float4 asin(float4);
+//===----------------------------------------------------------------------===//
+// asin builtins
+//===----------------------------------------------------------------------===//
+
+/// \fn uint asin(T Val)
+/// \brief Reinterprest.
+/// \param Val The input value.
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_asuint)
+uint asuint(float);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_asuint)
+uint2 asuint(float2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_asuint)
+uint3 asuint(float3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_asuint)
+uint4 asuint(float4);
+
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_asuint)
+uint asuint(double);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_asuint)
+uint2 asuint(double2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_asuint)
+uint3 asuint(double3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_asuint)
+uint4 asuint(double4);
+
//===----------------------------------------------------------------------===//
// atan builtins
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 3b40769939f12f..5b325035b6b2f5 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -28,6 +28,8 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/Type.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/DXILABI.h"
#include "llvm/Support/ErrorHandling.h"
@@ -1646,6 +1648,23 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
return true;
break;
}
+ case Builtin::BI__builtin_hlsl_elementwise_asuint: {
+ if (SemaRef.checkArgCount(TheCall, 1))
+ return true;
+
+ ExprResult A = TheCall->getArg(0);
+ QualType ArgTyA = A.get()->getType();
+
+ if(ArgTyA->isVectorType()){
+ auto VecTy = TheCall->getArg(0)->getType()->getAs<VectorType>();
+ auto ReturnType = this->getASTContext().getVectorType(TheCall->getCallReturnType(this->getASTContext()), VecTy->getNumElements(),
+ VectorKind::Generic);
+
+ TheCall->setType(ReturnType);
+ }
+
+ break;
+ }
case Builtin::BI__builtin_elementwise_acos:
case Builtin::BI__builtin_elementwise_asin:
case Builtin::BI__builtin_elementwise_atan:
diff --git a/clang/test/CodeGenHLSL/builtins/asuint.hlsl b/clang/test/CodeGenHLSL/builtins/asuint.hlsl
new file mode 100644
index 00000000000000..33acb00ae11182
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/asuint.hlsl
@@ -0,0 +1,53 @@
+// 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_asuint_float
+// // CHECK: bitcast float %0 to i32
+// // CHECK: ret <4 x i32> %dx.clamp
+// export uint builtin_test_asuint_float(float p0) {
+// return __builtin_hlsl_elementwise_asuint(p0);
+// }
+
+
+// // CHECK-LABEL: builtin_test_asuint_float
+// // CHECK: bitcast float %0 to i32
+// // CHECK: ret <4 x i32> %dx.clamp
+// export uint builtin_test_asuint_double(double p0) {
+// return __builtin_hlsl_elementwise_asuint(p0);
+// }
+
+
+// // CHECK-LABEL: builtin_test_asuint_float
+// // CHECK: bitcast float %0 to i32
+// // CHECK: ret <4 x i32> %dx.clamp
+// export uint builtin_test_asuint_half(half p0) {
+// return __builtin_hlsl_elementwise_asuint(p0);
+// }
+
+
+// // CHECK-LABEL: builtin_test_asuint_float
+// // CHECK: bitcast float %0 to i32
+// // CHECK: ret <4 x i32> %dx.clamp
+// export uint4 builtin_test_asuint_float_vector(float p0) {
+// return __builtin_hlsl_elementwise_asuint(p0);
+// }
+
+
+// CHECK-LABEL: builtin_test_asuint_float
+// CHECK: bitcast float %0 to i32
+// CHECK: ret <4 x i32> %dx.clamp
+export uint4 builtin_test_asuint_floa4t(float p0) {
+ return asuint(p0);
+}
+
+// export uint4 builtin_test_asuint4_uint(uint p0) {
+// return __builtin_hlsl_elementwise_asuint(p0);
+// }
+
+
+// export uint4 builtin_test_asuint4_int(int p0) {
+// return __builtin_hlsl_elementwise_asuint(p0);
+// }
+
+// export uint builtin_test_asuint_float(float p0) {
+// return __builtin_hlsl_elementwise_asuint(p0);
+// }
\ No newline at end of file
>From 82fca9ea6716114e4f483fcead9039deaa27f592 Mon Sep 17 00:00:00 2001
From: Joao Saffran <jderezende at microsoft.com>
Date: Tue, 3 Sep 2024 19:06:22 +0000
Subject: [PATCH 2/4] Adding `asuint` implementation to hlsl
---
clang/lib/CodeGen/CGBuiltin.cpp | 16 ++---
clang/lib/Headers/hlsl/hlsl_intrinsics.h | 27 ++++----
clang/lib/Sema/SemaHLSL.cpp | 43 +++++++++----
clang/test/CodeGenHLSL/builtins/asuint.hlsl | 63 ++++++-------------
.../test/SemaHLSL/BuiltIns/asuint-errors.hlsl | 18 ++++++
5 files changed, 86 insertions(+), 81 deletions(-)
create mode 100644 clang/test/SemaHLSL/BuiltIns/asuint-errors.hlsl
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 4a6a60fcac8a14..afbcd96bc14b2f 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -27,11 +27,9 @@
#include "clang/AST/Decl.h"
#include "clang/AST/OSLog.h"
#include "clang/AST/OperationKinds.h"
-#include "clang/Basic/Builtins.h"
#include "clang/Basic/TargetBuiltins.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/TargetOptions.h"
-#include "clang/Basic/TokenKinds.h"
#include "clang/CodeGen/CGFunctionInfo.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "llvm/ADT/APFloat.h"
@@ -41,7 +39,6 @@
#include "llvm/ADT/StringExtras.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/IR/DataLayout.h"
-#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/InlineAsm.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/IntrinsicsAArch64.h"
@@ -65,7 +62,6 @@
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/ScopedPrinter.h"
-#include "llvm/Support/raw_ostream.h"
#include "llvm/TargetParser/AArch64TargetParser.h"
#include "llvm/TargetParser/RISCVISAInfo.h"
#include "llvm/TargetParser/X86TargetParser.h"
@@ -18820,14 +18816,14 @@ case Builtin::BI__builtin_hlsl_elementwise_isinf: {
{}, false, true));
}
case Builtin::BI__builtin_hlsl_elementwise_asuint: {
- Value *Op = EmitScalarExpr(E->getArg(0));
- E->dump();
+ Value *Op = EmitScalarExpr(E->getArg(0)->IgnoreImpCasts());
+
llvm::Type *DestTy = llvm::Type::getInt32Ty(this->getLLVMContext());
- if (Op -> getType()->isVectorTy()){
- auto VecTy = E->getArg(0)->getType()->getAs<VectorType>();
- DestTy = llvm::VectorType::get(DestTy, VecTy->getNumElements(),
- VecTy->isSizelessVectorType());
+ if (Op->getType()->isVectorTy()) {
+ const VectorType *VecTy = E->getArg(0)->getType()->getAs<VectorType>();
+ DestTy = llvm::VectorType::get(
+ DestTy, ElementCount::getFixed(VecTy->getNumElements()));
}
return Builder.CreateBitCast(Op, DestTy);
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
index 18426597569098..f40469937ddc38 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
@@ -367,6 +367,17 @@ bool any(double4);
/// \brief Returns the arcsine of the input value, \a Val.
/// \param Val The input value.
+#ifdef __HLSL_ENABLE_16_BIT
+_HLSL_BUILTIN_ALIAS(__builtin_elementwise_asin)
+half asin(half);
+_HLSL_BUILTIN_ALIAS(__builtin_elementwise_asin)
+half2 asin(half2);
+_HLSL_BUILTIN_ALIAS(__builtin_elementwise_asin)
+half3 asin(half3);
+_HLSL_BUILTIN_ALIAS(__builtin_elementwise_asin)
+half4 asin(half4);
+#endif
+
_HLSL_BUILTIN_ALIAS(__builtin_elementwise_asin)
float asin(float);
_HLSL_BUILTIN_ALIAS(__builtin_elementwise_asin)
@@ -377,11 +388,11 @@ _HLSL_BUILTIN_ALIAS(__builtin_elementwise_asin)
float4 asin(float4);
//===----------------------------------------------------------------------===//
-// asin builtins
+// asuint builtins
//===----------------------------------------------------------------------===//
-/// \fn uint asin(T Val)
-/// \brief Reinterprest.
+/// \fn uint asuint(T Val)
+/// \brief Interprets the bit pattern of x as an unsigned integer.
/// \param Val The input value.
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_asuint)
@@ -393,16 +404,6 @@ uint3 asuint(float3);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_asuint)
uint4 asuint(float4);
-
-_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_asuint)
-uint asuint(double);
-_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_asuint)
-uint2 asuint(double2);
-_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_asuint)
-uint3 asuint(double3);
-_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_asuint)
-uint4 asuint(double4);
-
//===----------------------------------------------------------------------===//
// atan builtins
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 5b325035b6b2f5..123a724d444c33 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -9,7 +9,6 @@
//===----------------------------------------------------------------------===//
#include "clang/Sema/SemaHLSL.h"
-#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
@@ -28,8 +27,6 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/IR/DerivedTypes.h"
-#include "llvm/IR/Type.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/DXILABI.h"
#include "llvm/Support/ErrorHandling.h"
@@ -1468,6 +1465,25 @@ bool CheckVectorElementCallArgs(Sema *S, CallExpr *TheCall) {
return true;
}
+bool CheckArgTypeWithoutImplicits(
+ Sema *S, Expr *Arg, QualType ExpectedType,
+ llvm::function_ref<bool(clang::QualType PassedType)> Check) {
+
+ QualType ArgTy = Arg->IgnoreImpCasts()->getType();
+
+ clang::QualType BaseType =
+ ArgTy->isVectorType()
+ ? ArgTy->getAs<clang::VectorType>()->getElementType()
+ : ArgTy;
+
+ if (Check(BaseType)) {
+ S->Diag(Arg->getBeginLoc(), diag::err_typecheck_convert_incompatible)
+ << ArgTy << ExpectedType << 1 << 0 << 0;
+ return true;
+ }
+ return false;
+}
+
bool CheckArgsTypesAreCorrect(
Sema *S, CallExpr *TheCall, QualType ExpectedType,
llvm::function_ref<bool(clang::QualType PassedType)> Check) {
@@ -1494,6 +1510,14 @@ bool CheckAllArgsHaveFloatRepresentation(Sema *S, CallExpr *TheCall) {
checkAllFloatTypes);
}
+bool CheckArgIsFloatOrIntWithoutImplicits(Sema *S, Expr *Arg) {
+ auto checkFloat = [](clang::QualType PassedType) -> bool {
+ return !PassedType->isFloat32Type() && !PassedType->isIntegerType();
+ };
+
+ return CheckArgTypeWithoutImplicits(S, Arg, S->Context.FloatTy, checkFloat);
+}
+
bool CheckFloatOrHalfRepresentations(Sema *S, CallExpr *TheCall) {
auto checkFloatorHalf = [](clang::QualType PassedType) -> bool {
clang::QualType BaseType =
@@ -1652,16 +1676,9 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
if (SemaRef.checkArgCount(TheCall, 1))
return true;
- ExprResult A = TheCall->getArg(0);
- QualType ArgTyA = A.get()->getType();
-
- if(ArgTyA->isVectorType()){
- auto VecTy = TheCall->getArg(0)->getType()->getAs<VectorType>();
- auto ReturnType = this->getASTContext().getVectorType(TheCall->getCallReturnType(this->getASTContext()), VecTy->getNumElements(),
- VectorKind::Generic);
-
- TheCall->setType(ReturnType);
- }
+ Expr *Arg = TheCall->getArg(0);
+ if (CheckArgIsFloatOrIntWithoutImplicits(&SemaRef, Arg))
+ return true;
break;
}
diff --git a/clang/test/CodeGenHLSL/builtins/asuint.hlsl b/clang/test/CodeGenHLSL/builtins/asuint.hlsl
index 33acb00ae11182..2ae7d8219ac671 100644
--- a/clang/test/CodeGenHLSL/builtins/asuint.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/asuint.hlsl
@@ -1,53 +1,26 @@
// 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_asuint_float
-// // CHECK: bitcast float %0 to i32
-// // CHECK: ret <4 x i32> %dx.clamp
-// export uint builtin_test_asuint_float(float p0) {
-// return __builtin_hlsl_elementwise_asuint(p0);
-// }
-
-// // CHECK-LABEL: builtin_test_asuint_float
-// // CHECK: bitcast float %0 to i32
-// // CHECK: ret <4 x i32> %dx.clamp
-// export uint builtin_test_asuint_double(double p0) {
-// return __builtin_hlsl_elementwise_asuint(p0);
-// }
-
-
-// // CHECK-LABEL: builtin_test_asuint_float
-// // CHECK: bitcast float %0 to i32
-// // CHECK: ret <4 x i32> %dx.clamp
-// export uint builtin_test_asuint_half(half p0) {
-// return __builtin_hlsl_elementwise_asuint(p0);
-// }
-
-
-// // CHECK-LABEL: builtin_test_asuint_float
-// // CHECK: bitcast float %0 to i32
-// // CHECK: ret <4 x i32> %dx.clamp
-// export uint4 builtin_test_asuint_float_vector(float p0) {
-// return __builtin_hlsl_elementwise_asuint(p0);
-// }
-
-
-// CHECK-LABEL: builtin_test_asuint_float
-// CHECK: bitcast float %0 to i32
-// CHECK: ret <4 x i32> %dx.clamp
-export uint4 builtin_test_asuint_floa4t(float p0) {
+// CHECK-LABEL: test_asuint4_uint
+// CHECK: ret i32 %0
+export uint test_asuint4_uint(uint p0) {
return asuint(p0);
}
-// export uint4 builtin_test_asuint4_uint(uint p0) {
-// return __builtin_hlsl_elementwise_asuint(p0);
-// }
-
+// CHECK-LABEL: test_asuint4_int
+// CHECK: %splat.splatinsert = insertelement <4 x i32> poison, i32 %0, i64 0
+export uint4 test_asuint4_int(int p0) {
+ return asuint(p0);
+}
-// export uint4 builtin_test_asuint4_int(int p0) {
-// return __builtin_hlsl_elementwise_asuint(p0);
-// }
+// CHECK-LABEL: test_asuint_float
+// CHECK: %1 = bitcast float %0 to i32
+export uint test_asuint_float(float p0) {
+ return asuint(p0);
+}
-// export uint builtin_test_asuint_float(float p0) {
-// return __builtin_hlsl_elementwise_asuint(p0);
-// }
\ No newline at end of file
+// CHECK-LABEL: test_asuint_float
+// CHECK: %1 = bitcast <4 x float> %0 to <4 x i32>
+export uint4 test_asuint_float4(float4 p0) {
+ return asuint(p0);
+}
\ No newline at end of file
diff --git a/clang/test/SemaHLSL/BuiltIns/asuint-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/asuint-errors.hlsl
new file mode 100644
index 00000000000000..e9da975bff1b5e
--- /dev/null
+++ b/clang/test/SemaHLSL/BuiltIns/asuint-errors.hlsl
@@ -0,0 +1,18 @@
+// 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
+
+
+export uint4 test_asuint_too_many_arg(float p0, float p1) {
+ return __builtin_hlsl_elementwise_asuint(p0, p1);
+ // expected-error at -1 {{too many arguments to function call, expected 1, have 2}}
+}
+
+
+export uint fn(double p1) {
+ return asuint(p1);
+ // expected-error at -1 {{passing 'double' to parameter of incompatible type 'float'}}
+}
+
+export uint fn(half p1) {
+ return asuint(p1);
+ // expected-error at -1 {{passing 'half' to parameter of incompatible type 'float'}}
+}
>From d0619c7c9b5aa7a9c4137bf67af5a3647da75236 Mon Sep 17 00:00:00 2001
From: Joao Saffran <jderezende at microsoft.com>
Date: Fri, 6 Sep 2024 18:44:38 +0000
Subject: [PATCH 3/4] Adding `asuint` implementation to hlsl
---
clang/include/clang/Basic/Builtins.td | 7 +++-
clang/lib/CodeGen/CGBuiltin.cpp | 2 +-
clang/lib/Headers/hlsl/hlsl_intrinsics.h | 18 +++++++++
clang/lib/Sema/SemaHLSL.cpp | 32 ++++-----------
clang/test/CodeGenHLSL/builtins/asuint.hlsl | 43 ++++++++++++++-------
5 files changed, 61 insertions(+), 41 deletions(-)
diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index 83bca9b342ef15..0e6c1c284da6cf 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -53,6 +53,9 @@ class MSInt32_64Template : Template<["msint32_t", "int64_t"],
class FloatDoubleTemplate : Template<["float", "double"],
["f", ""]>;
+class HLSLFloatAndIntTemplate : Template<
+ ["unsigned int", "int", "float"],
+ ["", "si", "f"]>;
// FIXME: These assume that char -> i8, short -> i16, int -> i32,
// long long -> i64.
class SyncBuiltinsTemplate :
@@ -4751,10 +4754,10 @@ def HLSLRcp : LangBuiltin<"HLSL_LANG"> {
let Prototype = "void(...)";
}
-def HLSLAsUint : LangBuiltin<"HLSL_LANG"> {
+def HLSLAsUint : LangBuiltin<"HLSL_LANG">, HLSLFloatAndIntTemplate {
let Spellings = ["__builtin_hlsl_elementwise_asuint"];
let Attributes = [NoThrow, Const];
- let Prototype = "void(...)";
+ let Prototype = "unsigned int (T)";
}
def HLSLRSqrt : LangBuiltin<"HLSL_LANG"> {
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index afbcd96bc14b2f..012623a3d7032f 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -18816,7 +18816,7 @@ case Builtin::BI__builtin_hlsl_elementwise_isinf: {
{}, false, true));
}
case Builtin::BI__builtin_hlsl_elementwise_asuint: {
- Value *Op = EmitScalarExpr(E->getArg(0)->IgnoreImpCasts());
+ Value *Op = EmitScalarExpr(E->getArg(0));
llvm::Type *DestTy = llvm::Type::getInt32Ty(this->getLLVMContext());
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
index f40469937ddc38..178484f5852f51 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
@@ -404,6 +404,24 @@ uint3 asuint(float3);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_asuint)
uint4 asuint(float4);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_asuint)
+uint asuint(uint);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_asuint)
+uint2 asuint(uint2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_asuint)
+uint3 asuint(uint3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_asuint)
+uint4 asuint(uint4);
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_asuint)
+uint asuint(int);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_asuint)
+uint2 asuint(int2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_asuint)
+uint3 asuint(int3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_asuint)
+uint4 asuint(int4);
+
//===----------------------------------------------------------------------===//
// atan builtins
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 123a724d444c33..10019067c803eb 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -1465,25 +1465,6 @@ bool CheckVectorElementCallArgs(Sema *S, CallExpr *TheCall) {
return true;
}
-bool CheckArgTypeWithoutImplicits(
- Sema *S, Expr *Arg, QualType ExpectedType,
- llvm::function_ref<bool(clang::QualType PassedType)> Check) {
-
- QualType ArgTy = Arg->IgnoreImpCasts()->getType();
-
- clang::QualType BaseType =
- ArgTy->isVectorType()
- ? ArgTy->getAs<clang::VectorType>()->getElementType()
- : ArgTy;
-
- if (Check(BaseType)) {
- S->Diag(Arg->getBeginLoc(), diag::err_typecheck_convert_incompatible)
- << ArgTy << ExpectedType << 1 << 0 << 0;
- return true;
- }
- return false;
-}
-
bool CheckArgsTypesAreCorrect(
Sema *S, CallExpr *TheCall, QualType ExpectedType,
llvm::function_ref<bool(clang::QualType PassedType)> Check) {
@@ -1510,12 +1491,16 @@ bool CheckAllArgsHaveFloatRepresentation(Sema *S, CallExpr *TheCall) {
checkAllFloatTypes);
}
-bool CheckArgIsFloatOrIntWithoutImplicits(Sema *S, Expr *Arg) {
+bool CheckNotFloatAndInt(Sema *S, CallExpr *TheCall) {
auto checkFloat = [](clang::QualType PassedType) -> bool {
- return !PassedType->isFloat32Type() && !PassedType->isIntegerType();
+ clang::QualType BaseType =
+ PassedType->isVectorType()
+ ? PassedType->getAs<clang::VectorType>()->getElementType()
+ : PassedType;
+ return !(BaseType->isFloat32Type() || BaseType->isIntegerType());
};
- return CheckArgTypeWithoutImplicits(S, Arg, S->Context.FloatTy, checkFloat);
+ return CheckArgsTypesAreCorrect(S, TheCall, S->Context.FloatTy, checkFloat);
}
bool CheckFloatOrHalfRepresentations(Sema *S, CallExpr *TheCall) {
@@ -1676,8 +1661,7 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
if (SemaRef.checkArgCount(TheCall, 1))
return true;
- Expr *Arg = TheCall->getArg(0);
- if (CheckArgIsFloatOrIntWithoutImplicits(&SemaRef, Arg))
+ if (CheckNotFloatAndInt(&SemaRef, TheCall))
return true;
break;
diff --git a/clang/test/CodeGenHLSL/builtins/asuint.hlsl b/clang/test/CodeGenHLSL/builtins/asuint.hlsl
index 2ae7d8219ac671..1edf07942d3a09 100644
--- a/clang/test/CodeGenHLSL/builtins/asuint.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/asuint.hlsl
@@ -1,26 +1,41 @@
-// 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
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s -fnative-half-type -emit-llvm -O1 -o - | FileCheck %s
+// CHECK: define {{.*}}test_uint{{.*}}(i32 {{.*}} [[VAL:%.*]]){{.*}}
+// CHECK-NOT: bitcast
+// CHECK: ret i32 [[VAL]]
+export uint test_uint(uint p0) {
+ return asuint(p0);
+}
+
+// CHECK: define {{.*}}test_int{{.*}}(i32 {{.*}} [[VAL:%.*]]){{.*}}
+// CHECK-NOT: bitcast
+// CHECK: ret i32 [[VAL]]
+export uint test_int(int p0) {
+ return asuint(p0);
+}
-// CHECK-LABEL: test_asuint4_uint
-// CHECK: ret i32 %0
-export uint test_asuint4_uint(uint p0) {
+// CHECK: define {{.*}}test_float{{.*}}(float {{.*}} [[VAL:%.*]]){{.*}}
+// CHECK: bitcast float [[VAL]] to i32
+export uint test_float(float p0) {
return asuint(p0);
}
-// CHECK-LABEL: test_asuint4_int
-// CHECK: %splat.splatinsert = insertelement <4 x i32> poison, i32 %0, i64 0
-export uint4 test_asuint4_int(int p0) {
+// CHECK: define {{.*}}test_vector_uint{{.*}}(<4 x i32> {{.*}} [[VAL:%.*]]){{.*}}
+// CHECK-NOT: bitcast
+// CHECK: ret <4 x i32> [[VAL]]
+export uint4 test_vector_uint(uint4 p0) {
return asuint(p0);
}
-// CHECK-LABEL: test_asuint_float
-// CHECK: %1 = bitcast float %0 to i32
-export uint test_asuint_float(float p0) {
+// CHECK: define {{.*}}test_vector_int{{.*}}(<4 x i32> {{.*}} [[VAL:%.*]]){{.*}}
+// CHECK-NOT: bitcast
+// CHECK: ret <4 x i32> [[VAL]]
+export uint4 test_vector_int(int4 p0) {
return asuint(p0);
}
-// CHECK-LABEL: test_asuint_float
-// CHECK: %1 = bitcast <4 x float> %0 to <4 x i32>
-export uint4 test_asuint_float4(float4 p0) {
+// CHECK: define {{.*}}test_vector_float{{.*}}(<4 x float> {{.*}} [[VAL:%.*]]){{.*}}
+// CHECK: bitcast <4 x float> [[VAL]] to <4 x i32>
+export uint4 test_vector_float(float4 p0) {
return asuint(p0);
-}
\ No newline at end of file
+}
>From 472c796b8d36dfc8459394ac25e5cbdcf514618e Mon Sep 17 00:00:00 2001
From: Joao Saffran <jderezende at microsoft.com>
Date: Mon, 9 Sep 2024 18:35:20 +0000
Subject: [PATCH 4/4] changing asuint implementation to call __builtin_bit_cast
---
clang/include/clang/Basic/Builtins.td | 9 -----
clang/lib/CodeGen/CGBuiltin.cpp | 13 -------
clang/lib/Headers/hlsl/hlsl_intrinsics.h | 38 ++++++-------------
clang/lib/Sema/SemaHLSL.cpp | 22 +----------
clang/test/CodeGenHLSL/builtins/asuint.hlsl | 12 +++---
.../test/SemaHLSL/BuiltIns/asuint-errors.hlsl | 16 ++++----
6 files changed, 27 insertions(+), 83 deletions(-)
diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index 0e6c1c284da6cf..92118418d9d459 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -53,9 +53,6 @@ class MSInt32_64Template : Template<["msint32_t", "int64_t"],
class FloatDoubleTemplate : Template<["float", "double"],
["f", ""]>;
-class HLSLFloatAndIntTemplate : Template<
- ["unsigned int", "int", "float"],
- ["", "si", "f"]>;
// FIXME: These assume that char -> i8, short -> i16, int -> i32,
// long long -> i64.
class SyncBuiltinsTemplate :
@@ -4754,12 +4751,6 @@ def HLSLRcp : LangBuiltin<"HLSL_LANG"> {
let Prototype = "void(...)";
}
-def HLSLAsUint : LangBuiltin<"HLSL_LANG">, HLSLFloatAndIntTemplate {
- let Spellings = ["__builtin_hlsl_elementwise_asuint"];
- let Attributes = [NoThrow, Const];
- let Prototype = "unsigned int (T)";
-}
-
def HLSLRSqrt : LangBuiltin<"HLSL_LANG"> {
let Spellings = ["__builtin_hlsl_elementwise_rsqrt"];
let Attributes = [NoThrow, Const];
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 012623a3d7032f..da7a1a55da5313 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -18815,19 +18815,6 @@ 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_asuint: {
- Value *Op = EmitScalarExpr(E->getArg(0));
-
- llvm::Type *DestTy = llvm::Type::getInt32Ty(this->getLLVMContext());
-
- if (Op->getType()->isVectorTy()) {
- const VectorType *VecTy = E->getArg(0)->getType()->getAs<VectorType>();
- DestTy = llvm::VectorType::get(
- DestTy, ElementCount::getFixed(VecTy->getNumElements()));
- }
-
- return Builder.CreateBitCast(Op, DestTy);
- }
case Builtin::BI__builtin_hlsl_wave_is_first_lane: {
Intrinsic::ID ID = CGM.getHLSLRuntime().getWaveIsFirstLaneIntrinsic();
return EmitRuntimeCall(Intrinsic::getDeclaration(&CGM.getModule(), ID));
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
index 178484f5852f51..9e5a303baaceba 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
@@ -395,32 +395,18 @@ float4 asin(float4);
/// \brief Interprets the bit pattern of x as an unsigned integer.
/// \param Val The input value.
-_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_asuint)
-uint asuint(float);
-_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_asuint)
-uint2 asuint(float2);
-_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_asuint)
-uint3 asuint(float3);
-_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_asuint)
-uint4 asuint(float4);
-
-_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_asuint)
-uint asuint(uint);
-_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_asuint)
-uint2 asuint(uint2);
-_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_asuint)
-uint3 asuint(uint3);
-_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_asuint)
-uint4 asuint(uint4);
-
-_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_asuint)
-uint asuint(int);
-_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_asuint)
-uint2 asuint(int2);
-_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_asuint)
-uint3 asuint(int3);
-_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_asuint)
-uint4 asuint(int4);
+template <typename T, int N>
+__attribute__((__always_inline__, __nodebug__)) static inline vector<uint, N>
+asuint(vector<T, N> V) {
+ _Static_assert(sizeof(T) == 4, "Input type to asuint must be 32-bit");
+ return __builtin_bit_cast(vector<uint, N>, V);
+}
+
+template <typename T>
+__attribute__((__always_inline__, __nodebug__)) static inline uint asuint(T F) {
+ _Static_assert(sizeof(T) == 4, "Input type to asuint must be 32-bit");
+ return __builtin_bit_cast(uint, F);
+}
//===----------------------------------------------------------------------===//
// atan builtins
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 10019067c803eb..3b40769939f12f 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -9,6 +9,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Sema/SemaHLSL.h"
+#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
@@ -1491,18 +1492,6 @@ bool CheckAllArgsHaveFloatRepresentation(Sema *S, CallExpr *TheCall) {
checkAllFloatTypes);
}
-bool CheckNotFloatAndInt(Sema *S, CallExpr *TheCall) {
- auto checkFloat = [](clang::QualType PassedType) -> bool {
- clang::QualType BaseType =
- PassedType->isVectorType()
- ? PassedType->getAs<clang::VectorType>()->getElementType()
- : PassedType;
- return !(BaseType->isFloat32Type() || BaseType->isIntegerType());
- };
-
- return CheckArgsTypesAreCorrect(S, TheCall, S->Context.FloatTy, checkFloat);
-}
-
bool CheckFloatOrHalfRepresentations(Sema *S, CallExpr *TheCall) {
auto checkFloatorHalf = [](clang::QualType PassedType) -> bool {
clang::QualType BaseType =
@@ -1657,15 +1646,6 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
return true;
break;
}
- case Builtin::BI__builtin_hlsl_elementwise_asuint: {
- if (SemaRef.checkArgCount(TheCall, 1))
- return true;
-
- if (CheckNotFloatAndInt(&SemaRef, TheCall))
- return true;
-
- break;
- }
case Builtin::BI__builtin_elementwise_acos:
case Builtin::BI__builtin_elementwise_asin:
case Builtin::BI__builtin_elementwise_atan:
diff --git a/clang/test/CodeGenHLSL/builtins/asuint.hlsl b/clang/test/CodeGenHLSL/builtins/asuint.hlsl
index 1edf07942d3a09..ac3dae26d6caed 100644
--- a/clang/test/CodeGenHLSL/builtins/asuint.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/asuint.hlsl
@@ -3,39 +3,39 @@
// CHECK: define {{.*}}test_uint{{.*}}(i32 {{.*}} [[VAL:%.*]]){{.*}}
// CHECK-NOT: bitcast
// CHECK: ret i32 [[VAL]]
-export uint test_uint(uint p0) {
+uint test_uint(uint p0) {
return asuint(p0);
}
// CHECK: define {{.*}}test_int{{.*}}(i32 {{.*}} [[VAL:%.*]]){{.*}}
// CHECK-NOT: bitcast
// CHECK: ret i32 [[VAL]]
-export uint test_int(int p0) {
+uint test_int(int p0) {
return asuint(p0);
}
// CHECK: define {{.*}}test_float{{.*}}(float {{.*}} [[VAL:%.*]]){{.*}}
// CHECK: bitcast float [[VAL]] to i32
-export uint test_float(float p0) {
+uint test_float(float p0) {
return asuint(p0);
}
// CHECK: define {{.*}}test_vector_uint{{.*}}(<4 x i32> {{.*}} [[VAL:%.*]]){{.*}}
// CHECK-NOT: bitcast
// CHECK: ret <4 x i32> [[VAL]]
-export uint4 test_vector_uint(uint4 p0) {
+uint4 test_vector_uint(uint4 p0) {
return asuint(p0);
}
// CHECK: define {{.*}}test_vector_int{{.*}}(<4 x i32> {{.*}} [[VAL:%.*]]){{.*}}
// CHECK-NOT: bitcast
// CHECK: ret <4 x i32> [[VAL]]
-export uint4 test_vector_int(int4 p0) {
+uint4 test_vector_int(int4 p0) {
return asuint(p0);
}
// CHECK: define {{.*}}test_vector_float{{.*}}(<4 x float> {{.*}} [[VAL:%.*]]){{.*}}
// CHECK: bitcast <4 x float> [[VAL]] to <4 x i32>
-export uint4 test_vector_float(float4 p0) {
+uint4 test_vector_float(float4 p0) {
return asuint(p0);
}
diff --git a/clang/test/SemaHLSL/BuiltIns/asuint-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/asuint-errors.hlsl
index e9da975bff1b5e..5b37eb55aeba27 100644
--- a/clang/test/SemaHLSL/BuiltIns/asuint-errors.hlsl
+++ b/clang/test/SemaHLSL/BuiltIns/asuint-errors.hlsl
@@ -1,18 +1,18 @@
// 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
-export uint4 test_asuint_too_many_arg(float p0, float p1) {
- return __builtin_hlsl_elementwise_asuint(p0, p1);
- // expected-error at -1 {{too many arguments to function call, expected 1, have 2}}
+uint4 test_asuint_too_many_arg(float p0, float p1) {
+ return asuint(p0, p1);
+ // expected-error at -1 {{no matching function for call to 'asuint'}}
}
-
-export uint fn(double p1) {
+uint test_asuint_double(double p1) {
return asuint(p1);
- // expected-error at -1 {{passing 'double' to parameter of incompatible type 'float'}}
+ // expected-error at -1 {/clang/20/include/hlsl/hlsl_intrinsics.h} {{static assertion failed due to requirement 'sizeof(double) == 4': Input type to asuint must be 32-bit}}
}
-export uint fn(half p1) {
+
+uint test_asuint_half(half p1) {
return asuint(p1);
- // expected-error at -1 {{passing 'half' to parameter of incompatible type 'float'}}
+ // expected-error at -1 {/clang/20/include/hlsl/hlsl_intrinsics.h} {{static assertion failed due to requirement 'sizeof(double) == 4': Input type to asuint must be 32-bit}}
}
More information about the cfe-commits
mailing list