[clang] [HLSL] Implement support for HLSL intrinsic - select (PR #107129)
@@ -1545,6 +1605,30 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { break; } case Builtin::BI__builtin_hlsl_elementwise_saturate: spall wrote: No I did not; It is supposed to fall through to the next case, so I will reorder these. https://github.com/llvm/llvm-project/pull/107129 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [HLSL] Implement support for HLSL intrinsic - select (PR #107129)
@@ -18695,6 +18695,50 @@ case Builtin::BI__builtin_hlsl_elementwise_isinf: { CGM.getHLSLRuntime().getSaturateIntrinsic(), ArrayRef{Op0}, nullptr, "hlsl.saturate"); } + case Builtin::BI__builtin_hlsl_select: { +Value *OpCond = EmitScalarExpr(E->getArg(0)); +Value *OpTrue = EmitScalarExpr(E->getArg(1)); +Value *OpFalse = EmitScalarExpr(E->getArg(2)); +llvm::Type *TCond = OpCond->getType(); + +// if cond is a bool emit a select instruction +if (TCond->isIntegerTy(1)) + return Builder.CreateSelect(OpCond, OpTrue, OpFalse, "hlsl.select"); + +// if cond is a vector of bools lower to a shufflevector +// todo check if that true and false are vectors spall wrote: I likely just forgot to remove them; because yes they were for my own bookkeeping. https://github.com/llvm/llvm-project/pull/107129 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [HLSL] Implement support for HLSL intrinsic - select (PR #107129)
https://github.com/spall updated https://github.com/llvm/llvm-project/pull/107129 >From 3e0cd3c450eb4aa28742c4879733987e9e2692e7 Mon Sep 17 00:00:00 2001 From: Sarah Spall Date: Wed, 28 Aug 2024 01:44:35 + Subject: [PATCH 1/4] implement select intrinsic --- clang/include/clang/Basic/Builtins.td| 6 ++ clang/lib/CodeGen/CGBuiltin.cpp | 41 clang/lib/Headers/hlsl/hlsl_intrinsics.h | 24 +++ clang/lib/Sema/SemaHLSL.cpp | 84 4 files changed, 155 insertions(+) diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 8668b25661dec8..7e89f84319877b 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 HLSLSelect : LangBuiltin<"HLSL_LANG"> { + let Spellings = ["__builtin_hlsl_select"]; + let Attributes = [NoThrow, Const]; + let Prototype = "void(...)"; +} + // 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 e4d169d2ad6030..7fe198c207ce22 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -18695,6 +18695,47 @@ case Builtin::BI__builtin_hlsl_elementwise_isinf: { CGM.getHLSLRuntime().getSaturateIntrinsic(), ArrayRef{Op0}, nullptr, "hlsl.saturate"); } + case Builtin::BI__builtin_hlsl_select: { +Value *OpCond = EmitScalarExpr(E->getArg(0)); +Value *OpTrue = EmitScalarExpr(E->getArg(1)); +Value *OpFalse = EmitScalarExpr(E->getArg(2)); +llvm::Type *TCond = OpCond->getType(); + +// if cond is a bool emit a select instruction +if (TCond->isIntegerTy(1)) + return Builder.CreateSelect(OpCond, OpTrue, OpFalse); + +// if cond is a vector of bools lower to a shufflevector +// todo check if that true and false are vectors +// todo check that the size of true and false and cond are the same +if (TCond->isVectorTy() && + E->getArg(0)->getType()->getAs()->isBooleanType()) { + assert(OpTrue->getType()->isVectorTy() && OpFalse->getType()->isVectorTy() && +"Select's second and third operands must be vectors if first operand is a vector."); + + auto *VecTyTrue = E->getArg(1)->getType()->getAs(); + auto *VecTyFalse = E->getArg(2)->getType()->getAs(); + + assert(VecTyTrue->getElementType() == VecTyFalse->getElementType() && +"Select's second and third vectors need the same element types."); + + const unsigned N = VecTyTrue->getNumElements(); + assert(N == VecTyFalse->getNumElements() && +N == E->getArg(0)->getType()->getAs()->getNumElements() && +"Select requires vectors to be of the same size."); + + llvm::SmallVector Mask; + for (unsigned I = 0; I < N; I++) { + Value *Index = ConstantInt::get(IntTy, I); + Value *IndexBool = Builder.CreateExtractElement(OpCond, Index); + Mask.push_back(Builder.CreateSelect(IndexBool, Index, ConstantInt::get(IntTy, I + N))); + } + + return Builder.CreateShuffleVector(OpTrue, OpFalse, BuildVector(Mask)); +} + +llvm_unreachable("Select requires a bool or vector of bools as its first operand."); + } case Builtin::BI__builtin_hlsl_wave_get_lane_index: { return EmitRuntimeCall(CGM.CreateRuntimeFunction( llvm::FunctionType::get(IntTy, {}, false), "__hlsl_wave_get_lane_index", diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index 6d38b668fe770e..4319d9775c4bae 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -1603,6 +1603,30 @@ double3 saturate(double3); _HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_saturate) double4 saturate(double4); +//===--===// +// select builtins +//===--===// + +/// \fn T select(bool Cond, T TrueVal, T FalseVal) +/// \brief ternary operator. +/// \param Cond The Condition input value. +/// \param TrueVal The Value returned if Cond is true. +/// \param FalseVal The Value returned if Cond is false. + +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_select) +template +T select(bool, T, T); + +/// \fn vector select(vector Conds, vector TrueVals, vector, FalseVals) +/// \brief ternary operator for vectors. All vectors must be the same size. +/// \param Conds The Condition input values. +/// \param TrueVals The vector values are chosen from when conditions are true. +/// \param FalseVals The vector values are chosen from when conditions are false. + +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_select) +template +vector select(vector, vector, vector); + //===
[clang] [HLSL] Implement support for HLSL intrinsic - select (PR #107129)
https://github.com/spall updated https://github.com/llvm/llvm-project/pull/107129 >From 3e0cd3c450eb4aa28742c4879733987e9e2692e7 Mon Sep 17 00:00:00 2001 From: Sarah Spall Date: Wed, 28 Aug 2024 01:44:35 + Subject: [PATCH 1/5] implement select intrinsic --- clang/include/clang/Basic/Builtins.td| 6 ++ clang/lib/CodeGen/CGBuiltin.cpp | 41 clang/lib/Headers/hlsl/hlsl_intrinsics.h | 24 +++ clang/lib/Sema/SemaHLSL.cpp | 84 4 files changed, 155 insertions(+) diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 8668b25661dec8..7e89f84319877b 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 HLSLSelect : LangBuiltin<"HLSL_LANG"> { + let Spellings = ["__builtin_hlsl_select"]; + let Attributes = [NoThrow, Const]; + let Prototype = "void(...)"; +} + // 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 e4d169d2ad6030..7fe198c207ce22 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -18695,6 +18695,47 @@ case Builtin::BI__builtin_hlsl_elementwise_isinf: { CGM.getHLSLRuntime().getSaturateIntrinsic(), ArrayRef{Op0}, nullptr, "hlsl.saturate"); } + case Builtin::BI__builtin_hlsl_select: { +Value *OpCond = EmitScalarExpr(E->getArg(0)); +Value *OpTrue = EmitScalarExpr(E->getArg(1)); +Value *OpFalse = EmitScalarExpr(E->getArg(2)); +llvm::Type *TCond = OpCond->getType(); + +// if cond is a bool emit a select instruction +if (TCond->isIntegerTy(1)) + return Builder.CreateSelect(OpCond, OpTrue, OpFalse); + +// if cond is a vector of bools lower to a shufflevector +// todo check if that true and false are vectors +// todo check that the size of true and false and cond are the same +if (TCond->isVectorTy() && + E->getArg(0)->getType()->getAs()->isBooleanType()) { + assert(OpTrue->getType()->isVectorTy() && OpFalse->getType()->isVectorTy() && +"Select's second and third operands must be vectors if first operand is a vector."); + + auto *VecTyTrue = E->getArg(1)->getType()->getAs(); + auto *VecTyFalse = E->getArg(2)->getType()->getAs(); + + assert(VecTyTrue->getElementType() == VecTyFalse->getElementType() && +"Select's second and third vectors need the same element types."); + + const unsigned N = VecTyTrue->getNumElements(); + assert(N == VecTyFalse->getNumElements() && +N == E->getArg(0)->getType()->getAs()->getNumElements() && +"Select requires vectors to be of the same size."); + + llvm::SmallVector Mask; + for (unsigned I = 0; I < N; I++) { + Value *Index = ConstantInt::get(IntTy, I); + Value *IndexBool = Builder.CreateExtractElement(OpCond, Index); + Mask.push_back(Builder.CreateSelect(IndexBool, Index, ConstantInt::get(IntTy, I + N))); + } + + return Builder.CreateShuffleVector(OpTrue, OpFalse, BuildVector(Mask)); +} + +llvm_unreachable("Select requires a bool or vector of bools as its first operand."); + } case Builtin::BI__builtin_hlsl_wave_get_lane_index: { return EmitRuntimeCall(CGM.CreateRuntimeFunction( llvm::FunctionType::get(IntTy, {}, false), "__hlsl_wave_get_lane_index", diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index 6d38b668fe770e..4319d9775c4bae 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -1603,6 +1603,30 @@ double3 saturate(double3); _HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_saturate) double4 saturate(double4); +//===--===// +// select builtins +//===--===// + +/// \fn T select(bool Cond, T TrueVal, T FalseVal) +/// \brief ternary operator. +/// \param Cond The Condition input value. +/// \param TrueVal The Value returned if Cond is true. +/// \param FalseVal The Value returned if Cond is false. + +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_select) +template +T select(bool, T, T); + +/// \fn vector select(vector Conds, vector TrueVals, vector, FalseVals) +/// \brief ternary operator for vectors. All vectors must be the same size. +/// \param Conds The Condition input values. +/// \param TrueVals The vector values are chosen from when conditions are true. +/// \param FalseVals The vector values are chosen from when conditions are false. + +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_select) +template +vector select(vector, vector, vector); + //===
[clang] [HLSL] Implement support for HLSL intrinsic - select (PR #107129)
@@ -1544,6 +1604,30 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { return true; break; } + case Builtin::BI__builtin_hlsl_select: { spall wrote: I think it is slightly special. It is a template function, and the first argument must be either a bool or a vector of bools. Both of those cases have slightly different checks; so I made a function for each. I don't believe any of the existing Check functions checked for the correct things; most of them require all args are the same type. https://github.com/llvm/llvm-project/pull/107129 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [HLSL] Implement support for HLSL intrinsic - select (PR #107129)
https://github.com/spall updated https://github.com/llvm/llvm-project/pull/107129 >From 3e0cd3c450eb4aa28742c4879733987e9e2692e7 Mon Sep 17 00:00:00 2001 From: Sarah Spall Date: Wed, 28 Aug 2024 01:44:35 + Subject: [PATCH 1/6] implement select intrinsic --- clang/include/clang/Basic/Builtins.td| 6 ++ clang/lib/CodeGen/CGBuiltin.cpp | 41 clang/lib/Headers/hlsl/hlsl_intrinsics.h | 24 +++ clang/lib/Sema/SemaHLSL.cpp | 84 4 files changed, 155 insertions(+) diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 8668b25661dec8..7e89f84319877b 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 HLSLSelect : LangBuiltin<"HLSL_LANG"> { + let Spellings = ["__builtin_hlsl_select"]; + let Attributes = [NoThrow, Const]; + let Prototype = "void(...)"; +} + // 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 e4d169d2ad6030..7fe198c207ce22 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -18695,6 +18695,47 @@ case Builtin::BI__builtin_hlsl_elementwise_isinf: { CGM.getHLSLRuntime().getSaturateIntrinsic(), ArrayRef{Op0}, nullptr, "hlsl.saturate"); } + case Builtin::BI__builtin_hlsl_select: { +Value *OpCond = EmitScalarExpr(E->getArg(0)); +Value *OpTrue = EmitScalarExpr(E->getArg(1)); +Value *OpFalse = EmitScalarExpr(E->getArg(2)); +llvm::Type *TCond = OpCond->getType(); + +// if cond is a bool emit a select instruction +if (TCond->isIntegerTy(1)) + return Builder.CreateSelect(OpCond, OpTrue, OpFalse); + +// if cond is a vector of bools lower to a shufflevector +// todo check if that true and false are vectors +// todo check that the size of true and false and cond are the same +if (TCond->isVectorTy() && + E->getArg(0)->getType()->getAs()->isBooleanType()) { + assert(OpTrue->getType()->isVectorTy() && OpFalse->getType()->isVectorTy() && +"Select's second and third operands must be vectors if first operand is a vector."); + + auto *VecTyTrue = E->getArg(1)->getType()->getAs(); + auto *VecTyFalse = E->getArg(2)->getType()->getAs(); + + assert(VecTyTrue->getElementType() == VecTyFalse->getElementType() && +"Select's second and third vectors need the same element types."); + + const unsigned N = VecTyTrue->getNumElements(); + assert(N == VecTyFalse->getNumElements() && +N == E->getArg(0)->getType()->getAs()->getNumElements() && +"Select requires vectors to be of the same size."); + + llvm::SmallVector Mask; + for (unsigned I = 0; I < N; I++) { + Value *Index = ConstantInt::get(IntTy, I); + Value *IndexBool = Builder.CreateExtractElement(OpCond, Index); + Mask.push_back(Builder.CreateSelect(IndexBool, Index, ConstantInt::get(IntTy, I + N))); + } + + return Builder.CreateShuffleVector(OpTrue, OpFalse, BuildVector(Mask)); +} + +llvm_unreachable("Select requires a bool or vector of bools as its first operand."); + } case Builtin::BI__builtin_hlsl_wave_get_lane_index: { return EmitRuntimeCall(CGM.CreateRuntimeFunction( llvm::FunctionType::get(IntTy, {}, false), "__hlsl_wave_get_lane_index", diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index 6d38b668fe770e..4319d9775c4bae 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -1603,6 +1603,30 @@ double3 saturate(double3); _HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_saturate) double4 saturate(double4); +//===--===// +// select builtins +//===--===// + +/// \fn T select(bool Cond, T TrueVal, T FalseVal) +/// \brief ternary operator. +/// \param Cond The Condition input value. +/// \param TrueVal The Value returned if Cond is true. +/// \param FalseVal The Value returned if Cond is false. + +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_select) +template +T select(bool, T, T); + +/// \fn vector select(vector Conds, vector TrueVals, vector, FalseVals) +/// \brief ternary operator for vectors. All vectors must be the same size. +/// \param Conds The Condition input values. +/// \param TrueVals The vector values are chosen from when conditions are true. +/// \param FalseVals The vector values are chosen from when conditions are false. + +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_select) +template +vector select(vector, vector, vector); + //===
[clang] [HLSL] Implement support for HLSL intrinsic - select (PR #107129)
@@ -0,0 +1,45 @@ +// 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 + +// CHECK: %hlsl.select = select i1 +// CHECK: ret i32 %hlsl.select +int test_select_bool_int(bool cond0, int tVal, int fVal) { + return select(cond0, tVal, fVal); } + +struct S { int a; }; +// CHECK: %hlsl.select = select i1 +// CHECK: store ptr %hlsl.select +// CHECK: ret void +struct S test_select_infer(bool cond0, struct S tVal, struct S fVal) { + return select(cond0, tVal, fVal); } + +// CHECK: %hlsl.select = select i1 +// CHECK: ret <2 x i32> %hlsl.select +vector test_select_bool_vector(bool cond0, vector tVal, + vector fVal) { + return select >(cond0, tVal, fVal); } spall wrote: No, would it be better to use that form in all the tests? I can change that. https://github.com/llvm/llvm-project/pull/107129 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [HLSL] Implement support for HLSL intrinsic - select (PR #107129)
https://github.com/spall updated https://github.com/llvm/llvm-project/pull/107129 >From 3e0cd3c450eb4aa28742c4879733987e9e2692e7 Mon Sep 17 00:00:00 2001 From: Sarah Spall Date: Wed, 28 Aug 2024 01:44:35 + Subject: [PATCH 1/7] implement select intrinsic --- clang/include/clang/Basic/Builtins.td| 6 ++ clang/lib/CodeGen/CGBuiltin.cpp | 41 clang/lib/Headers/hlsl/hlsl_intrinsics.h | 24 +++ clang/lib/Sema/SemaHLSL.cpp | 84 4 files changed, 155 insertions(+) diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 8668b25661dec8..7e89f84319877b 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 HLSLSelect : LangBuiltin<"HLSL_LANG"> { + let Spellings = ["__builtin_hlsl_select"]; + let Attributes = [NoThrow, Const]; + let Prototype = "void(...)"; +} + // 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 e4d169d2ad6030..7fe198c207ce22 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -18695,6 +18695,47 @@ case Builtin::BI__builtin_hlsl_elementwise_isinf: { CGM.getHLSLRuntime().getSaturateIntrinsic(), ArrayRef{Op0}, nullptr, "hlsl.saturate"); } + case Builtin::BI__builtin_hlsl_select: { +Value *OpCond = EmitScalarExpr(E->getArg(0)); +Value *OpTrue = EmitScalarExpr(E->getArg(1)); +Value *OpFalse = EmitScalarExpr(E->getArg(2)); +llvm::Type *TCond = OpCond->getType(); + +// if cond is a bool emit a select instruction +if (TCond->isIntegerTy(1)) + return Builder.CreateSelect(OpCond, OpTrue, OpFalse); + +// if cond is a vector of bools lower to a shufflevector +// todo check if that true and false are vectors +// todo check that the size of true and false and cond are the same +if (TCond->isVectorTy() && + E->getArg(0)->getType()->getAs()->isBooleanType()) { + assert(OpTrue->getType()->isVectorTy() && OpFalse->getType()->isVectorTy() && +"Select's second and third operands must be vectors if first operand is a vector."); + + auto *VecTyTrue = E->getArg(1)->getType()->getAs(); + auto *VecTyFalse = E->getArg(2)->getType()->getAs(); + + assert(VecTyTrue->getElementType() == VecTyFalse->getElementType() && +"Select's second and third vectors need the same element types."); + + const unsigned N = VecTyTrue->getNumElements(); + assert(N == VecTyFalse->getNumElements() && +N == E->getArg(0)->getType()->getAs()->getNumElements() && +"Select requires vectors to be of the same size."); + + llvm::SmallVector Mask; + for (unsigned I = 0; I < N; I++) { + Value *Index = ConstantInt::get(IntTy, I); + Value *IndexBool = Builder.CreateExtractElement(OpCond, Index); + Mask.push_back(Builder.CreateSelect(IndexBool, Index, ConstantInt::get(IntTy, I + N))); + } + + return Builder.CreateShuffleVector(OpTrue, OpFalse, BuildVector(Mask)); +} + +llvm_unreachable("Select requires a bool or vector of bools as its first operand."); + } case Builtin::BI__builtin_hlsl_wave_get_lane_index: { return EmitRuntimeCall(CGM.CreateRuntimeFunction( llvm::FunctionType::get(IntTy, {}, false), "__hlsl_wave_get_lane_index", diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index 6d38b668fe770e..4319d9775c4bae 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -1603,6 +1603,30 @@ double3 saturate(double3); _HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_saturate) double4 saturate(double4); +//===--===// +// select builtins +//===--===// + +/// \fn T select(bool Cond, T TrueVal, T FalseVal) +/// \brief ternary operator. +/// \param Cond The Condition input value. +/// \param TrueVal The Value returned if Cond is true. +/// \param FalseVal The Value returned if Cond is false. + +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_select) +template +T select(bool, T, T); + +/// \fn vector select(vector Conds, vector TrueVals, vector, FalseVals) +/// \brief ternary operator for vectors. All vectors must be the same size. +/// \param Conds The Condition input values. +/// \param TrueVals The vector values are chosen from when conditions are true. +/// \param FalseVals The vector values are chosen from when conditions are false. + +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_select) +template +vector select(vector, vector, vector); + //===
[clang] [HLSL] Implement support for HLSL intrinsic - select (PR #107129)
@@ -1512,6 +1512,83 @@ void SetElementTypeAsReturnType(Sema *S, CallExpr *TheCall, TheCall->setType(ReturnType); } +static bool CheckScalarOrVector(Sema *S, CallExpr *TheCall, QualType Scalar, + unsigned ArgIndex) { + assert(TheCall->getNumArgs() >= ArgIndex); + QualType ArgType = TheCall->getArg(ArgIndex)->getType(); + auto *VTy = ArgType->getAs(); + // not the scalar or vector + if (!(S->Context.hasSameUnqualifiedType(ArgType, Scalar) || + (VTy && S->Context.hasSameUnqualifiedType(VTy->getElementType(), + Scalar { +S->Diag(TheCall->getArg(0)->getBeginLoc(), + diag::err_typecheck_expect_scalar_or_vector) + << ArgType << Scalar; +return true; + } + return false; +} + +static bool CheckBoolSelect(Sema *S, CallExpr *TheCall) { + assert(TheCall->getNumArgs() == 3); + Expr *Arg1 = TheCall->getArg(1); + Expr *Arg2 = TheCall->getArg(2); + if(!S->Context.hasSameUnqualifiedType(Arg1->getType(), + Arg2->getType())) { +S->Diag(TheCall->getBeginLoc(), + diag::err_typecheck_call_different_arg_types) + << Arg1->getType() << Arg2->getType() + << Arg1->getSourceRange() << Arg2->getSourceRange(); +return true; + } + + TheCall->setType(Arg1->getType()); + return false; +} + +static bool CheckVectorSelect(Sema *S, CallExpr *TheCall) { + assert(TheCall->getNumArgs() == 3); + Expr *Arg1 = TheCall->getArg(1); + Expr *Arg2 = TheCall->getArg(2); + if (!Arg1->getType()->isVectorType()) { +S->Diag(Arg1->getBeginLoc(), + diag::err_builtin_non_vector_type) + << "Second" << "__builtin_hlsl_select" << Arg1->getType() + << Arg1->getSourceRange(); +return true; + } + + if (!Arg2->getType()->isVectorType()) { +S->Diag(Arg2->getBeginLoc(), + diag::err_builtin_non_vector_type) + << "Third" << "__builtin_hlsl_select" << Arg2->getType() + << Arg2->getSourceRange(); +return true; + } + + if (!S->Context.hasSameUnqualifiedType(Arg1->getType(), +Arg2->getType())) { +S->Diag(TheCall->getBeginLoc(), + diag::err_typecheck_call_different_arg_types) + << Arg1->getType() << Arg2->getType() + << Arg1->getSourceRange() << Arg2->getSourceRange(); +return true; + } + + // caller has checked that Arg0 is a vector. + // check all three args have the same length. + if (TheCall->getArg(0)->getType()->getAs()->getNumElements() != spall wrote: checkVectorElementCallArgs, checks that all of the vector arguments are the same, as far as I can tell, for select only the last two vectors should be the same. I could generalize that function and use it instead. https://github.com/llvm/llvm-project/pull/107129 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [HLSL] Implement support for HLSL intrinsic - select (PR #107129)
@@ -0,0 +1,45 @@ +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ spall wrote: How do I fix this? https://github.com/llvm/llvm-project/pull/107129 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [HLSL] Implement support for HLSL intrinsic - select (PR #107129)
https://github.com/spall deleted https://github.com/llvm/llvm-project/pull/107129 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [HLSL] Implement support for HLSL intrinsic - select (PR #107129)
https://github.com/spall updated https://github.com/llvm/llvm-project/pull/107129 >From 3e0cd3c450eb4aa28742c4879733987e9e2692e7 Mon Sep 17 00:00:00 2001 From: Sarah Spall Date: Wed, 28 Aug 2024 01:44:35 + Subject: [PATCH 1/8] implement select intrinsic --- clang/include/clang/Basic/Builtins.td| 6 ++ clang/lib/CodeGen/CGBuiltin.cpp | 41 clang/lib/Headers/hlsl/hlsl_intrinsics.h | 24 +++ clang/lib/Sema/SemaHLSL.cpp | 84 4 files changed, 155 insertions(+) diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 8668b25661dec8..7e89f84319877b 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 HLSLSelect : LangBuiltin<"HLSL_LANG"> { + let Spellings = ["__builtin_hlsl_select"]; + let Attributes = [NoThrow, Const]; + let Prototype = "void(...)"; +} + // 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 e4d169d2ad6030..7fe198c207ce22 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -18695,6 +18695,47 @@ case Builtin::BI__builtin_hlsl_elementwise_isinf: { CGM.getHLSLRuntime().getSaturateIntrinsic(), ArrayRef{Op0}, nullptr, "hlsl.saturate"); } + case Builtin::BI__builtin_hlsl_select: { +Value *OpCond = EmitScalarExpr(E->getArg(0)); +Value *OpTrue = EmitScalarExpr(E->getArg(1)); +Value *OpFalse = EmitScalarExpr(E->getArg(2)); +llvm::Type *TCond = OpCond->getType(); + +// if cond is a bool emit a select instruction +if (TCond->isIntegerTy(1)) + return Builder.CreateSelect(OpCond, OpTrue, OpFalse); + +// if cond is a vector of bools lower to a shufflevector +// todo check if that true and false are vectors +// todo check that the size of true and false and cond are the same +if (TCond->isVectorTy() && + E->getArg(0)->getType()->getAs()->isBooleanType()) { + assert(OpTrue->getType()->isVectorTy() && OpFalse->getType()->isVectorTy() && +"Select's second and third operands must be vectors if first operand is a vector."); + + auto *VecTyTrue = E->getArg(1)->getType()->getAs(); + auto *VecTyFalse = E->getArg(2)->getType()->getAs(); + + assert(VecTyTrue->getElementType() == VecTyFalse->getElementType() && +"Select's second and third vectors need the same element types."); + + const unsigned N = VecTyTrue->getNumElements(); + assert(N == VecTyFalse->getNumElements() && +N == E->getArg(0)->getType()->getAs()->getNumElements() && +"Select requires vectors to be of the same size."); + + llvm::SmallVector Mask; + for (unsigned I = 0; I < N; I++) { + Value *Index = ConstantInt::get(IntTy, I); + Value *IndexBool = Builder.CreateExtractElement(OpCond, Index); + Mask.push_back(Builder.CreateSelect(IndexBool, Index, ConstantInt::get(IntTy, I + N))); + } + + return Builder.CreateShuffleVector(OpTrue, OpFalse, BuildVector(Mask)); +} + +llvm_unreachable("Select requires a bool or vector of bools as its first operand."); + } case Builtin::BI__builtin_hlsl_wave_get_lane_index: { return EmitRuntimeCall(CGM.CreateRuntimeFunction( llvm::FunctionType::get(IntTy, {}, false), "__hlsl_wave_get_lane_index", diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index 6d38b668fe770e..4319d9775c4bae 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -1603,6 +1603,30 @@ double3 saturate(double3); _HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_saturate) double4 saturate(double4); +//===--===// +// select builtins +//===--===// + +/// \fn T select(bool Cond, T TrueVal, T FalseVal) +/// \brief ternary operator. +/// \param Cond The Condition input value. +/// \param TrueVal The Value returned if Cond is true. +/// \param FalseVal The Value returned if Cond is false. + +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_select) +template +T select(bool, T, T); + +/// \fn vector select(vector Conds, vector TrueVals, vector, FalseVals) +/// \brief ternary operator for vectors. All vectors must be the same size. +/// \param Conds The Condition input values. +/// \param TrueVals The vector values are chosen from when conditions are true. +/// \param FalseVals The vector values are chosen from when conditions are false. + +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_select) +template +vector select(vector, vector, vector); + //===
[clang] [HLSL] Implement support for HLSL intrinsic - select (PR #107129)
https://github.com/spall updated https://github.com/llvm/llvm-project/pull/107129 >From 3e0cd3c450eb4aa28742c4879733987e9e2692e7 Mon Sep 17 00:00:00 2001 From: Sarah Spall Date: Wed, 28 Aug 2024 01:44:35 + Subject: [PATCH 1/9] implement select intrinsic --- clang/include/clang/Basic/Builtins.td| 6 ++ clang/lib/CodeGen/CGBuiltin.cpp | 41 clang/lib/Headers/hlsl/hlsl_intrinsics.h | 24 +++ clang/lib/Sema/SemaHLSL.cpp | 84 4 files changed, 155 insertions(+) diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 8668b25661dec8..7e89f84319877b 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 HLSLSelect : LangBuiltin<"HLSL_LANG"> { + let Spellings = ["__builtin_hlsl_select"]; + let Attributes = [NoThrow, Const]; + let Prototype = "void(...)"; +} + // 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 e4d169d2ad6030..7fe198c207ce22 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -18695,6 +18695,47 @@ case Builtin::BI__builtin_hlsl_elementwise_isinf: { CGM.getHLSLRuntime().getSaturateIntrinsic(), ArrayRef{Op0}, nullptr, "hlsl.saturate"); } + case Builtin::BI__builtin_hlsl_select: { +Value *OpCond = EmitScalarExpr(E->getArg(0)); +Value *OpTrue = EmitScalarExpr(E->getArg(1)); +Value *OpFalse = EmitScalarExpr(E->getArg(2)); +llvm::Type *TCond = OpCond->getType(); + +// if cond is a bool emit a select instruction +if (TCond->isIntegerTy(1)) + return Builder.CreateSelect(OpCond, OpTrue, OpFalse); + +// if cond is a vector of bools lower to a shufflevector +// todo check if that true and false are vectors +// todo check that the size of true and false and cond are the same +if (TCond->isVectorTy() && + E->getArg(0)->getType()->getAs()->isBooleanType()) { + assert(OpTrue->getType()->isVectorTy() && OpFalse->getType()->isVectorTy() && +"Select's second and third operands must be vectors if first operand is a vector."); + + auto *VecTyTrue = E->getArg(1)->getType()->getAs(); + auto *VecTyFalse = E->getArg(2)->getType()->getAs(); + + assert(VecTyTrue->getElementType() == VecTyFalse->getElementType() && +"Select's second and third vectors need the same element types."); + + const unsigned N = VecTyTrue->getNumElements(); + assert(N == VecTyFalse->getNumElements() && +N == E->getArg(0)->getType()->getAs()->getNumElements() && +"Select requires vectors to be of the same size."); + + llvm::SmallVector Mask; + for (unsigned I = 0; I < N; I++) { + Value *Index = ConstantInt::get(IntTy, I); + Value *IndexBool = Builder.CreateExtractElement(OpCond, Index); + Mask.push_back(Builder.CreateSelect(IndexBool, Index, ConstantInt::get(IntTy, I + N))); + } + + return Builder.CreateShuffleVector(OpTrue, OpFalse, BuildVector(Mask)); +} + +llvm_unreachable("Select requires a bool or vector of bools as its first operand."); + } case Builtin::BI__builtin_hlsl_wave_get_lane_index: { return EmitRuntimeCall(CGM.CreateRuntimeFunction( llvm::FunctionType::get(IntTy, {}, false), "__hlsl_wave_get_lane_index", diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index 6d38b668fe770e..4319d9775c4bae 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -1603,6 +1603,30 @@ double3 saturate(double3); _HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_saturate) double4 saturate(double4); +//===--===// +// select builtins +//===--===// + +/// \fn T select(bool Cond, T TrueVal, T FalseVal) +/// \brief ternary operator. +/// \param Cond The Condition input value. +/// \param TrueVal The Value returned if Cond is true. +/// \param FalseVal The Value returned if Cond is false. + +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_select) +template +T select(bool, T, T); + +/// \fn vector select(vector Conds, vector TrueVals, vector, FalseVals) +/// \brief ternary operator for vectors. All vectors must be the same size. +/// \param Conds The Condition input values. +/// \param TrueVals The vector values are chosen from when conditions are true. +/// \param FalseVals The vector values are chosen from when conditions are false. + +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_select) +template +vector select(vector, vector, vector); + //===
[clang] [llvm] [HLSL] Implement elementwise popcount (PR #108121)
https://github.com/spall created https://github.com/llvm/llvm-project/pull/108121 Implement elementwise popcount to support HLSL function 'countbits'. Closes #99094 >From 365886deae6e35ee2761c2fae2a28caa0e214880 Mon Sep 17 00:00:00 2001 From: Sarah Spall Date: Fri, 6 Sep 2024 21:03:05 + Subject: [PATCH] implement elementwise popcount to implement countbits --- clang/docs/LanguageExtensions.rst | 1 + clang/include/clang/Basic/Builtins.td | 6 ++ clang/lib/CodeGen/CGBuiltin.cpp | 3 + clang/lib/Headers/hlsl/hlsl_intrinsics.h | 71 +++ clang/lib/Sema/SemaChecking.cpp | 2 +- clang/lib/Sema/SemaHLSL.cpp | 8 +++ .../test/CodeGen/builtins-elementwise-math.c | 37 ++ clang/test/Sema/builtins-elementwise-math.c | 21 ++ .../SemaCXX/builtins-elementwise-math.cpp | 8 +++ llvm/lib/Target/DirectX/DXIL.td | 11 +++ llvm/test/CodeGen/DirectX/countbits.ll| 31 llvm/test/CodeGen/DirectX/countbits_error.ll | 10 +++ .../SPIRV/hlsl-intrinsics/countbits.ll| 21 ++ 13 files changed, 229 insertions(+), 1 deletion(-) create mode 100644 llvm/test/CodeGen/DirectX/countbits.ll create mode 100644 llvm/test/CodeGen/DirectX/countbits_error.ll create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/countbits.ll diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index c08697282cbfe8..f62f90fb9650a9 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -667,6 +667,7 @@ Unless specified otherwise operation(±0) = ±0 and operation(±infinity) = ±in T __builtin_elementwise_log(T x)return the natural logarithm of x floating point types T __builtin_elementwise_log2(T x) return the base 2 logarithm of x floating point types T __builtin_elementwise_log10(T x) return the base 10 logarithm of x floating point types + T __builtin_elementwise_popcount(T x) return the number of 1 bits in x integer types T __builtin_elementwise_pow(T x, T y) return x raised to the power of y floating point types T __builtin_elementwise_bitreverse(T x) return the integer represented after reversing the bits of x integer types T __builtin_elementwise_exp(T x)returns the base-e exponential, e^x, of the specified value floating point types diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 92118418d9d459..6281fa144bae35 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -1322,6 +1322,12 @@ def ElementwiseLog10 : Builtin { let Prototype = "void(...)"; } +def ElementwisePopcount : Builtin { + let Spellings = ["__builtin_elementwise_popcount"]; + let Attributes = [NoThrow, Const, CustomTypeChecking]; + let Prototype = "void(...)"; +} + def ElementwisePow : Builtin { let Spellings = ["__builtin_elementwise_pow"]; let Attributes = [NoThrow, Const, CustomTypeChecking]; diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index da7a1a55da5313..c5d50e57fa638c 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -3834,6 +3834,9 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__builtin_elementwise_floor: return RValue::get(emitBuiltinWithOneOverloadedType<1>( *this, E, llvm::Intrinsic::floor, "elt.floor")); + case Builtin::BI__builtin_elementwise_popcount: +return RValue::get(emitBuiltinWithOneOverloadedType<1>( + *this, E, llvm::Intrinsic::ctpop, "elt.ctpop")); case Builtin::BI__builtin_elementwise_roundeven: return RValue::get(emitBuiltinWithOneOverloadedType<1>( *this, E, llvm::Intrinsic::roundeven, "elt.roundeven")); diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index 5c08a45a35377d..9d667bb61b74ae 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -614,6 +614,77 @@ float3 cosh(float3); _HLSL_BUILTIN_ALIAS(__builtin_elementwise_cosh) float4 cosh(float4); +//===--===// +// count bits builtins +//===--===// + +/// \fn T countbits(T Val) +/// \brief Return the number of bits (per component) set in the input integer. +/// \param Val The input value. + +#ifdef __HLSL_ENABLE_16_BIT +_HLSL_AVAILABILITY(shadermodel, 6.2) +_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) +int16_t countbits(int16_t); +_HLSL_AVAILABILITY(shadermodel, 6.2) +_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) +int16_t
[clang] [llvm] [HLSL] Implement elementwise popcount (PR #108121)
spall wrote: This pull request is missing the appropriate text in 'ReleaseNotes.rst'. I am looking for advice on what is appropriate to put in that file, and where. https://github.com/llvm/llvm-project/pull/108121 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [HLSL] fix elementwise bitreverse test (PR #108128)
https://github.com/spall created https://github.com/llvm/llvm-project/pull/108128 The test called 'ceil' instead of 'bitreverse', which I assume was a copy paste leftover. >From 86e24b508c47ee6ad09cbaec299baeab32cf964b Mon Sep 17 00:00:00 2001 From: Sarah Spall Date: Wed, 11 Sep 2024 01:22:37 + Subject: [PATCH] fix elementwise bitreverse test --- clang/test/Sema/builtins-elementwise-math.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/test/Sema/builtins-elementwise-math.c b/clang/test/Sema/builtins-elementwise-math.c index 2673f1f519af69..628274380ae5f2 100644 --- a/clang/test/Sema/builtins-elementwise-math.c +++ b/clang/test/Sema/builtins-elementwise-math.c @@ -275,8 +275,8 @@ void test_builtin_elementwise_min(int i, short s, double d, float4 v, int3 iv, u void test_builtin_elementwise_bitreverse(int i, float f, double d, float4 v, int3 iv, unsigned u, unsigned4 uv) { - struct Foo s = __builtin_elementwise_ceil(f); - // expected-error@-1 {{initializing 'struct Foo' with an expression of incompatible type 'float'}} + struct Foo s = __builtin_elementwise_bitreverse(i); + // expected-error@-1 {{initializing 'struct Foo' with an expression of incompatible type 'int'}} i = __builtin_elementwise_bitreverse(); // expected-error@-1 {{too few arguments to function call, expected 1, have 0}} ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [HLSL] fix elementwise bitreverse test (PR #108128)
https://github.com/spall updated https://github.com/llvm/llvm-project/pull/108128 >From 8146b03b49a94532335f9bb238c6c41c9a800034 Mon Sep 17 00:00:00 2001 From: Sarah Spall Date: Wed, 11 Sep 2024 01:22:37 + Subject: [PATCH] fix elementwise bitreverse test --- clang/test/Sema/builtins-elementwise-math.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/test/Sema/builtins-elementwise-math.c b/clang/test/Sema/builtins-elementwise-math.c index 2673f1f519af69..628274380ae5f2 100644 --- a/clang/test/Sema/builtins-elementwise-math.c +++ b/clang/test/Sema/builtins-elementwise-math.c @@ -275,8 +275,8 @@ void test_builtin_elementwise_min(int i, short s, double d, float4 v, int3 iv, u void test_builtin_elementwise_bitreverse(int i, float f, double d, float4 v, int3 iv, unsigned u, unsigned4 uv) { - struct Foo s = __builtin_elementwise_ceil(f); - // expected-error@-1 {{initializing 'struct Foo' with an expression of incompatible type 'float'}} + struct Foo s = __builtin_elementwise_bitreverse(i); + // expected-error@-1 {{initializing 'struct Foo' with an expression of incompatible type 'int'}} i = __builtin_elementwise_bitreverse(); // expected-error@-1 {{too few arguments to function call, expected 1, have 0}} ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Implement elementwise popcount (PR #108121)
spall wrote: > > This pull request is missing the appropriate text in 'ReleaseNotes.rst'. I > > am looking for advice on what is appropriate to put in that file, and where. > > Here's a PR with ReleaseNotes.rst change > [57f879c#diff-ec770381d76c859f5f572db789175fe44410a72608f58ad5dbb14335ba56eb97](https://github.com/llvm/llvm-project/commit/57f879cdd4c63189c569bdc1ce4e87e7342eea46#diff-ec770381d76c859f5f572db789175fe44410a72608f58ad5dbb14335ba56eb97) Yeah I saw this example but am unsure where to put my text because the contents of that file are not the same now. https://github.com/llvm/llvm-project/pull/108121 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [HLSL] Implement support for HLSL intrinsic - select (PR #107129)
https://github.com/spall created https://github.com/llvm/llvm-project/pull/107129 Implement support for HLSL intrinsic select. This would close issue #75377 >From 226ea652f160b22922e9582c5a5c53511042d735 Mon Sep 17 00:00:00 2001 From: Sarah Spall Date: Wed, 28 Aug 2024 01:44:35 + Subject: [PATCH 1/3] implement select intrinsic --- clang/include/clang/Basic/Builtins.td| 6 ++ clang/lib/CodeGen/CGBuiltin.cpp | 41 clang/lib/Headers/hlsl/hlsl_intrinsics.h | 24 +++ clang/lib/Sema/SemaHLSL.cpp | 84 4 files changed, 155 insertions(+) diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index ac33672a32b336..291f417a7243d6 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 HLSLSelect : LangBuiltin<"HLSL_LANG"> { + let Spellings = ["__builtin_hlsl_select"]; + let Attributes = [NoThrow, Const]; + let Prototype = "void(...)"; +} + // 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 2a733e4d834cfa..ba18a2be319698 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -18695,6 +18695,47 @@ case Builtin::BI__builtin_hlsl_elementwise_isinf: { CGM.getHLSLRuntime().getSaturateIntrinsic(), ArrayRef{Op0}, nullptr, "hlsl.saturate"); } + case Builtin::BI__builtin_hlsl_select: { +Value *OpCond = EmitScalarExpr(E->getArg(0)); +Value *OpTrue = EmitScalarExpr(E->getArg(1)); +Value *OpFalse = EmitScalarExpr(E->getArg(2)); +llvm::Type *TCond = OpCond->getType(); + +// if cond is a bool emit a select instruction +if (TCond->isIntegerTy(1)) + return Builder.CreateSelect(OpCond, OpTrue, OpFalse); + +// if cond is a vector of bools lower to a shufflevector +// todo check if that true and false are vectors +// todo check that the size of true and false and cond are the same +if (TCond->isVectorTy() && + E->getArg(0)->getType()->getAs()->isBooleanType()) { + assert(OpTrue->getType()->isVectorTy() && OpFalse->getType()->isVectorTy() && +"Select's second and third operands must be vectors if first operand is a vector."); + + auto *VecTyTrue = E->getArg(1)->getType()->getAs(); + auto *VecTyFalse = E->getArg(2)->getType()->getAs(); + + assert(VecTyTrue->getElementType() == VecTyFalse->getElementType() && +"Select's second and third vectors need the same element types."); + + const unsigned N = VecTyTrue->getNumElements(); + assert(N == VecTyFalse->getNumElements() && +N == E->getArg(0)->getType()->getAs()->getNumElements() && +"Select requires vectors to be of the same size."); + + llvm::SmallVector Mask; + for (unsigned I = 0; I < N; I++) { + Value *Index = ConstantInt::get(IntTy, I); + Value *IndexBool = Builder.CreateExtractElement(OpCond, Index); + Mask.push_back(Builder.CreateSelect(IndexBool, Index, ConstantInt::get(IntTy, I + N))); + } + + return Builder.CreateShuffleVector(OpTrue, OpFalse, BuildVector(Mask)); +} + +llvm_unreachable("Select requires a bool or vector of bools as its first operand."); + } case Builtin::BI__builtin_hlsl_wave_get_lane_index: { return EmitRuntimeCall(CGM.CreateRuntimeFunction( llvm::FunctionType::get(IntTy, {}, false), "__hlsl_wave_get_lane_index", diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index 6d38b668fe770e..4319d9775c4bae 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -1603,6 +1603,30 @@ double3 saturate(double3); _HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_saturate) double4 saturate(double4); +//===--===// +// select builtins +//===--===// + +/// \fn T select(bool Cond, T TrueVal, T FalseVal) +/// \brief ternary operator. +/// \param Cond The Condition input value. +/// \param TrueVal The Value returned if Cond is true. +/// \param FalseVal The Value returned if Cond is false. + +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_select) +template +T select(bool, T, T); + +/// \fn vector select(vector Conds, vector TrueVals, vector, FalseVals) +/// \brief ternary operator for vectors. All vectors must be the same size. +/// \param Conds The Condition input values. +/// \param TrueVals The vector values are chosen from when conditions are true. +/// \param FalseVals The vector values are chosen from when conditions are false. + +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_select) +template +vector select
[clang] [HLSL] Implement support for HLSL intrinsic - select (PR #107129)
https://github.com/spall updated https://github.com/llvm/llvm-project/pull/107129 >From 3e0cd3c450eb4aa28742c4879733987e9e2692e7 Mon Sep 17 00:00:00 2001 From: Sarah Spall Date: Wed, 28 Aug 2024 01:44:35 + Subject: [PATCH 1/3] implement select intrinsic --- clang/include/clang/Basic/Builtins.td| 6 ++ clang/lib/CodeGen/CGBuiltin.cpp | 41 clang/lib/Headers/hlsl/hlsl_intrinsics.h | 24 +++ clang/lib/Sema/SemaHLSL.cpp | 84 4 files changed, 155 insertions(+) diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 8668b25661dec8..7e89f84319877b 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 HLSLSelect : LangBuiltin<"HLSL_LANG"> { + let Spellings = ["__builtin_hlsl_select"]; + let Attributes = [NoThrow, Const]; + let Prototype = "void(...)"; +} + // 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 e4d169d2ad6030..7fe198c207ce22 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -18695,6 +18695,47 @@ case Builtin::BI__builtin_hlsl_elementwise_isinf: { CGM.getHLSLRuntime().getSaturateIntrinsic(), ArrayRef{Op0}, nullptr, "hlsl.saturate"); } + case Builtin::BI__builtin_hlsl_select: { +Value *OpCond = EmitScalarExpr(E->getArg(0)); +Value *OpTrue = EmitScalarExpr(E->getArg(1)); +Value *OpFalse = EmitScalarExpr(E->getArg(2)); +llvm::Type *TCond = OpCond->getType(); + +// if cond is a bool emit a select instruction +if (TCond->isIntegerTy(1)) + return Builder.CreateSelect(OpCond, OpTrue, OpFalse); + +// if cond is a vector of bools lower to a shufflevector +// todo check if that true and false are vectors +// todo check that the size of true and false and cond are the same +if (TCond->isVectorTy() && + E->getArg(0)->getType()->getAs()->isBooleanType()) { + assert(OpTrue->getType()->isVectorTy() && OpFalse->getType()->isVectorTy() && +"Select's second and third operands must be vectors if first operand is a vector."); + + auto *VecTyTrue = E->getArg(1)->getType()->getAs(); + auto *VecTyFalse = E->getArg(2)->getType()->getAs(); + + assert(VecTyTrue->getElementType() == VecTyFalse->getElementType() && +"Select's second and third vectors need the same element types."); + + const unsigned N = VecTyTrue->getNumElements(); + assert(N == VecTyFalse->getNumElements() && +N == E->getArg(0)->getType()->getAs()->getNumElements() && +"Select requires vectors to be of the same size."); + + llvm::SmallVector Mask; + for (unsigned I = 0; I < N; I++) { + Value *Index = ConstantInt::get(IntTy, I); + Value *IndexBool = Builder.CreateExtractElement(OpCond, Index); + Mask.push_back(Builder.CreateSelect(IndexBool, Index, ConstantInt::get(IntTy, I + N))); + } + + return Builder.CreateShuffleVector(OpTrue, OpFalse, BuildVector(Mask)); +} + +llvm_unreachable("Select requires a bool or vector of bools as its first operand."); + } case Builtin::BI__builtin_hlsl_wave_get_lane_index: { return EmitRuntimeCall(CGM.CreateRuntimeFunction( llvm::FunctionType::get(IntTy, {}, false), "__hlsl_wave_get_lane_index", diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index 6d38b668fe770e..4319d9775c4bae 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -1603,6 +1603,30 @@ double3 saturate(double3); _HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_saturate) double4 saturate(double4); +//===--===// +// select builtins +//===--===// + +/// \fn T select(bool Cond, T TrueVal, T FalseVal) +/// \brief ternary operator. +/// \param Cond The Condition input value. +/// \param TrueVal The Value returned if Cond is true. +/// \param FalseVal The Value returned if Cond is false. + +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_select) +template +T select(bool, T, T); + +/// \fn vector select(vector Conds, vector TrueVals, vector, FalseVals) +/// \brief ternary operator for vectors. All vectors must be the same size. +/// \param Conds The Condition input values. +/// \param TrueVals The vector values are chosen from when conditions are true. +/// \param FalseVals The vector values are chosen from when conditions are false. + +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_select) +template +vector select(vector, vector, vector); + //===
[clang] [llvm] [HLSL] Implement elementwise popcount (PR #108121)
https://github.com/spall updated https://github.com/llvm/llvm-project/pull/108121 >From 4a892930ab4d97b5621d8066b23c48c7278d14e0 Mon Sep 17 00:00:00 2001 From: Sarah Spall Date: Fri, 6 Sep 2024 21:03:05 + Subject: [PATCH 1/2] implement elementwise popcount to implement countbits --- clang/docs/LanguageExtensions.rst | 1 + clang/include/clang/Basic/Builtins.td | 6 ++ clang/lib/CodeGen/CGBuiltin.cpp | 3 + clang/lib/Headers/hlsl/hlsl_intrinsics.h | 71 +++ clang/lib/Sema/SemaChecking.cpp | 2 +- clang/lib/Sema/SemaHLSL.cpp | 8 +++ .../test/CodeGen/builtins-elementwise-math.c | 37 ++ clang/test/Sema/builtins-elementwise-math.c | 21 ++ .../SemaCXX/builtins-elementwise-math.cpp | 8 +++ llvm/lib/Target/DirectX/DXIL.td | 11 +++ llvm/test/CodeGen/DirectX/countbits.ll| 31 llvm/test/CodeGen/DirectX/countbits_error.ll | 10 +++ .../SPIRV/hlsl-intrinsics/countbits.ll| 21 ++ 13 files changed, 229 insertions(+), 1 deletion(-) create mode 100644 llvm/test/CodeGen/DirectX/countbits.ll create mode 100644 llvm/test/CodeGen/DirectX/countbits_error.ll create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/countbits.ll diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index c08697282cbfe8..f62f90fb9650a9 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -667,6 +667,7 @@ Unless specified otherwise operation(±0) = ±0 and operation(±infinity) = ±in T __builtin_elementwise_log(T x)return the natural logarithm of x floating point types T __builtin_elementwise_log2(T x) return the base 2 logarithm of x floating point types T __builtin_elementwise_log10(T x) return the base 10 logarithm of x floating point types + T __builtin_elementwise_popcount(T x) return the number of 1 bits in x integer types T __builtin_elementwise_pow(T x, T y) return x raised to the power of y floating point types T __builtin_elementwise_bitreverse(T x) return the integer represented after reversing the bits of x integer types T __builtin_elementwise_exp(T x)returns the base-e exponential, e^x, of the specified value floating point types diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 3dc04f68b3172a..33aef520ad23c0 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -1322,6 +1322,12 @@ def ElementwiseLog10 : Builtin { let Prototype = "void(...)"; } +def ElementwisePopcount : Builtin { + let Spellings = ["__builtin_elementwise_popcount"]; + let Attributes = [NoThrow, Const, CustomTypeChecking]; + let Prototype = "void(...)"; +} + def ElementwisePow : Builtin { let Spellings = ["__builtin_elementwise_pow"]; let Attributes = [NoThrow, Const, CustomTypeChecking]; diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 9950c06a0b9a6b..91ed0806dcdbdb 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -3834,6 +3834,9 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__builtin_elementwise_floor: return RValue::get(emitBuiltinWithOneOverloadedType<1>( *this, E, llvm::Intrinsic::floor, "elt.floor")); + case Builtin::BI__builtin_elementwise_popcount: +return RValue::get(emitBuiltinWithOneOverloadedType<1>( + *this, E, llvm::Intrinsic::ctpop, "elt.ctpop")); case Builtin::BI__builtin_elementwise_roundeven: return RValue::get(emitBuiltinWithOneOverloadedType<1>( *this, E, llvm::Intrinsic::roundeven, "elt.roundeven")); diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index 7a1edd93984de7..6ec5e0820026a0 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -614,6 +614,77 @@ float3 cosh(float3); _HLSL_BUILTIN_ALIAS(__builtin_elementwise_cosh) float4 cosh(float4); +//===--===// +// count bits builtins +//===--===// + +/// \fn T countbits(T Val) +/// \brief Return the number of bits (per component) set in the input integer. +/// \param Val The input value. + +#ifdef __HLSL_ENABLE_16_BIT +_HLSL_AVAILABILITY(shadermodel, 6.2) +_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) +int16_t countbits(int16_t); +_HLSL_AVAILABILITY(shadermodel, 6.2) +_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) +int16_t2 countbits(int16_t2); +_HLSL_AVAILABILITY(shadermodel, 6.2) +_HLSL_BUILTIN_ALIAS(
[clang] [llvm] [HLSL] Implement elementwise popcount (PR #108121)
https://github.com/spall edited https://github.com/llvm/llvm-project/pull/108121 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [HLSL][Docs] Update function calls docs (PR #106860)
@@ -248,13 +248,14 @@ which is a term made up for HLSL. A cx-value is a temporary value which may be the result of a cast, and stores its value back to an lvalue when the value expires. -To represent this concept in Clang we introduce a new ``HLSLOutParamExpr``. An -``HLSLOutParamExpr`` has two forms, one with a single sub-expression and one -with two sub-expressions. +To represent this concept in Clang we introduce a new ``HLSLOutArgExpr``. An +``HLSLOutArgExpr`` has three sub-expressions: -The single sub-expression form is used when the argument expression and the -function parameter are the same type, so no cast is required. As in this -example: +* An OpaqueValueExpr of the argument lvalue expression. +* An OpaqueValueExpr of the copy-initialized parameter temporary. spall wrote: This is not always copy-initialized. It is clarified later in the docs, so maybe its not worth mentioning here, but thought I'd point it out. https://github.com/llvm/llvm-project/pull/106860 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [HLSL][Docs] Update function calls docs (PR #106860)
https://github.com/spall approved this pull request. https://github.com/llvm/llvm-project/pull/106860 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] implement elementwise firstbithigh hlsl builtin (PR #111082)
spall wrote: > It is not correct to limit firstbithigh to 32 bit integers. There are a > couple of reasons that might make one think that it is, but we do in fact > want/need to support int16 and int64 here. > > 1. The [HLSL > docs](https://learn.microsoft.com/en-us/windows/win32/direct3dhlsl/firstbithigh) > only mention integer. Unfortunately that's true for most of these functions, > as many of these docs were not updated as 64 and 16 bit types gained support > in the language. > > 2. DXC's SPIR-V implementation doesn't handle 16- and 64-bit for these > functions. As noted in [Incorrect SPIR-V generated when `firstbithigh` is > used on a `uint64_t` > microsoft/DirectXShaderCompiler#4702](https://github.com/microsoft/DirectXShaderCompiler/issues/4702) > we decided not to implement those overloads in DXC, but should reconsider > this for clang. > > > Despite all of this, DXC does indeed support 16- and 64-bit overloads, as > seen here: https://hlsl.godbolt.org/z/qbc17xz35 > > Note that the return type of the operation is not overloaded - all of the > overloads of this function return uint. Why is the return type not overloaded? It is overloaded for countbits which is a similar function. https://github.com/llvm/llvm-project/pull/111082 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][HLSL] Add sign intrinsic part 4 (PR #108396)
https://github.com/spall approved this pull request. https://github.com/llvm/llvm-project/pull/108396 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] implement elementwise firstbithigh hlsl builtin (PR #111082)
https://github.com/spall updated https://github.com/llvm/llvm-project/pull/111082 >From e9ed9f9a0415544781f8334b305eb3916fc0862c Mon Sep 17 00:00:00 2001 From: Sarah Spall Date: Mon, 23 Sep 2024 22:10:59 + Subject: [PATCH 1/4] implement firstbithigh hlsl builtin --- clang/include/clang/Basic/Builtins.td | 6 + clang/lib/CodeGen/CGBuiltin.cpp | 17 ++ clang/lib/CodeGen/CGHLSLRuntime.h | 2 + clang/lib/Headers/hlsl/hlsl_intrinsics.h | 72 + clang/lib/Sema/SemaHLSL.cpp | 18 +++ .../CodeGenHLSL/builtins/firstbithigh.hlsl| 153 ++ .../BuiltIns/firstbithigh-errors.hlsl | 28 llvm/include/llvm/IR/IntrinsicsDirectX.td | 2 + llvm/include/llvm/IR/IntrinsicsSPIRV.td | 2 + llvm/lib/Target/DirectX/DXIL.td | 24 +++ .../DirectX/DirectXTargetTransformInfo.cpp| 2 + .../Target/SPIRV/SPIRVInstructionSelector.cpp | 14 ++ llvm/test/CodeGen/DirectX/firstbithigh.ll | 91 +++ .../CodeGen/DirectX/firstbitshigh_error.ll| 10 ++ .../CodeGen/DirectX/firstbituhigh_error.ll| 10 ++ .../SPIRV/hlsl-intrinsics/firstbithigh.ll | 37 + 16 files changed, 488 insertions(+) create mode 100644 clang/test/CodeGenHLSL/builtins/firstbithigh.hlsl create mode 100644 clang/test/SemaHLSL/BuiltIns/firstbithigh-errors.hlsl create mode 100644 llvm/test/CodeGen/DirectX/firstbithigh.ll create mode 100644 llvm/test/CodeGen/DirectX/firstbitshigh_error.ll create mode 100644 llvm/test/CodeGen/DirectX/firstbituhigh_error.ll create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/firstbithigh.ll diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index a726a0ef4b4bd2..cc4630c281052d 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -4751,6 +4751,12 @@ def HLSLDotProduct : LangBuiltin<"HLSL_LANG"> { let Prototype = "void(...)"; } +def HLSLFirstBitHigh : LangBuiltin<"HLSL_LANG"> { + let Spellings = ["__builtin_hlsl_elementwise_firstbithigh"]; + let Attributes = [NoThrow, Const]; + let Prototype = "void(...)"; +} + def HLSLFrac : LangBuiltin<"HLSL_LANG"> { let Spellings = ["__builtin_hlsl_elementwise_frac"]; let Attributes = [NoThrow, Const]; diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 43700ea9dd3cfd..6033dcffb3a6da 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -18631,6 +18631,14 @@ static Intrinsic::ID getDotProductIntrinsic(CGHLSLRuntime &RT, QualType QT) { return RT.getUDotIntrinsic(); } +Intrinsic::ID getFirstBitHighIntrinsic(CGHLSLRuntime &RT, QualType QT) { + if (QT->hasSignedIntegerRepresentation()) { +return RT.getFirstBitSHighIntrinsic(); + } + + return RT.getFirstBitUHighIntrinsic(); +} + Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, const CallExpr *E, ReturnValueSlot ReturnValue) { @@ -18720,6 +18728,15 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, getDotProductIntrinsic(CGM.getHLSLRuntime(), VecTy0->getElementType()), ArrayRef{Op0, Op1}, nullptr, "hlsl.dot"); } break; + case Builtin::BI__builtin_hlsl_elementwise_firstbithigh: { + +Value *X = EmitScalarExpr(E->getArg(0)); + +return Builder.CreateIntrinsic( + /*ReturnType=*/X->getType(), + getFirstBitHighIntrinsic(CGM.getHLSLRuntime(), E->getArg(0)->getType()), + ArrayRef{X}, nullptr, "hlsl.firstbithigh"); + } case Builtin::BI__builtin_hlsl_lerp: { Value *X = EmitScalarExpr(E->getArg(0)); Value *Y = EmitScalarExpr(E->getArg(1)); diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h index 6722d2c7c50a2b..03ddef95800e1a 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.h +++ b/clang/lib/CodeGen/CGHLSLRuntime.h @@ -88,6 +88,8 @@ class CGHLSLRuntime { GENERATE_HLSL_INTRINSIC_FUNCTION(SDot, sdot) GENERATE_HLSL_INTRINSIC_FUNCTION(UDot, udot) GENERATE_HLSL_INTRINSIC_FUNCTION(WaveIsFirstLane, wave_is_first_lane) + GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitUHigh, firstbituhigh) + GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitSHigh, firstbitshigh) //===--===// // End of reserved area for HLSL intrinsic getters. diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index c3ecfc7c90d433..afb7bd33374111 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -928,6 +928,78 @@ float3 exp2(float3); _HLSL_BUILTIN_ALIAS(__builtin_elementwise_exp2) float4 exp2(float4); +//===--===// +// firstbithigh builtins +//===---
[clang] [llvm] [HLSL] implement elementwise firstbithigh hlsl builtin (PR #111082)
@@ -0,0 +1,37 @@ +; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %} spall wrote: I removed the non-32 bit tests, except error tests, since it only supports 32 bit integers. https://github.com/llvm/llvm-project/pull/111082 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][HLSL] Add radians intrinsic (PR #110802)
https://github.com/spall approved this pull request. LGTM but I didn't look too closely at the tests. https://github.com/llvm/llvm-project/pull/110802 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Implement the `degrees` intrinsic (PR #111209)
https://github.com/spall edited https://github.com/llvm/llvm-project/pull/111209 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] implement elementwise firstbithigh hlsl builtin (PR #111082)
https://github.com/spall updated https://github.com/llvm/llvm-project/pull/111082 >From e9ed9f9a0415544781f8334b305eb3916fc0862c Mon Sep 17 00:00:00 2001 From: Sarah Spall Date: Mon, 23 Sep 2024 22:10:59 + Subject: [PATCH 1/3] implement firstbithigh hlsl builtin --- clang/include/clang/Basic/Builtins.td | 6 + clang/lib/CodeGen/CGBuiltin.cpp | 17 ++ clang/lib/CodeGen/CGHLSLRuntime.h | 2 + clang/lib/Headers/hlsl/hlsl_intrinsics.h | 72 + clang/lib/Sema/SemaHLSL.cpp | 18 +++ .../CodeGenHLSL/builtins/firstbithigh.hlsl| 153 ++ .../BuiltIns/firstbithigh-errors.hlsl | 28 llvm/include/llvm/IR/IntrinsicsDirectX.td | 2 + llvm/include/llvm/IR/IntrinsicsSPIRV.td | 2 + llvm/lib/Target/DirectX/DXIL.td | 24 +++ .../DirectX/DirectXTargetTransformInfo.cpp| 2 + .../Target/SPIRV/SPIRVInstructionSelector.cpp | 14 ++ llvm/test/CodeGen/DirectX/firstbithigh.ll | 91 +++ .../CodeGen/DirectX/firstbitshigh_error.ll| 10 ++ .../CodeGen/DirectX/firstbituhigh_error.ll| 10 ++ .../SPIRV/hlsl-intrinsics/firstbithigh.ll | 37 + 16 files changed, 488 insertions(+) create mode 100644 clang/test/CodeGenHLSL/builtins/firstbithigh.hlsl create mode 100644 clang/test/SemaHLSL/BuiltIns/firstbithigh-errors.hlsl create mode 100644 llvm/test/CodeGen/DirectX/firstbithigh.ll create mode 100644 llvm/test/CodeGen/DirectX/firstbitshigh_error.ll create mode 100644 llvm/test/CodeGen/DirectX/firstbituhigh_error.ll create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/firstbithigh.ll diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index a726a0ef4b4bd2..cc4630c281052d 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -4751,6 +4751,12 @@ def HLSLDotProduct : LangBuiltin<"HLSL_LANG"> { let Prototype = "void(...)"; } +def HLSLFirstBitHigh : LangBuiltin<"HLSL_LANG"> { + let Spellings = ["__builtin_hlsl_elementwise_firstbithigh"]; + let Attributes = [NoThrow, Const]; + let Prototype = "void(...)"; +} + def HLSLFrac : LangBuiltin<"HLSL_LANG"> { let Spellings = ["__builtin_hlsl_elementwise_frac"]; let Attributes = [NoThrow, Const]; diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 43700ea9dd3cfd..6033dcffb3a6da 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -18631,6 +18631,14 @@ static Intrinsic::ID getDotProductIntrinsic(CGHLSLRuntime &RT, QualType QT) { return RT.getUDotIntrinsic(); } +Intrinsic::ID getFirstBitHighIntrinsic(CGHLSLRuntime &RT, QualType QT) { + if (QT->hasSignedIntegerRepresentation()) { +return RT.getFirstBitSHighIntrinsic(); + } + + return RT.getFirstBitUHighIntrinsic(); +} + Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, const CallExpr *E, ReturnValueSlot ReturnValue) { @@ -18720,6 +18728,15 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, getDotProductIntrinsic(CGM.getHLSLRuntime(), VecTy0->getElementType()), ArrayRef{Op0, Op1}, nullptr, "hlsl.dot"); } break; + case Builtin::BI__builtin_hlsl_elementwise_firstbithigh: { + +Value *X = EmitScalarExpr(E->getArg(0)); + +return Builder.CreateIntrinsic( + /*ReturnType=*/X->getType(), + getFirstBitHighIntrinsic(CGM.getHLSLRuntime(), E->getArg(0)->getType()), + ArrayRef{X}, nullptr, "hlsl.firstbithigh"); + } case Builtin::BI__builtin_hlsl_lerp: { Value *X = EmitScalarExpr(E->getArg(0)); Value *Y = EmitScalarExpr(E->getArg(1)); diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h index 6722d2c7c50a2b..03ddef95800e1a 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.h +++ b/clang/lib/CodeGen/CGHLSLRuntime.h @@ -88,6 +88,8 @@ class CGHLSLRuntime { GENERATE_HLSL_INTRINSIC_FUNCTION(SDot, sdot) GENERATE_HLSL_INTRINSIC_FUNCTION(UDot, udot) GENERATE_HLSL_INTRINSIC_FUNCTION(WaveIsFirstLane, wave_is_first_lane) + GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitUHigh, firstbituhigh) + GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitSHigh, firstbitshigh) //===--===// // End of reserved area for HLSL intrinsic getters. diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index c3ecfc7c90d433..afb7bd33374111 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -928,6 +928,78 @@ float3 exp2(float3); _HLSL_BUILTIN_ALIAS(__builtin_elementwise_exp2) float4 exp2(float4); +//===--===// +// firstbithigh builtins +//===---
[clang] [llvm] [HLSL] Implement the `degrees` intrinsic (PR #111209)
@@ -2625,6 +2645,8 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg, return selectFmix(ResVReg, ResType, I); case Intrinsic::spv_length: return selectLength(ResVReg, ResType, I); + case Intrinsic::spv_degrees: +return selectDegrees(ResVReg, ResType, I); spall wrote: Assuming it does take 1 operand, can you use selectExtInst here instead of a custom function? https://github.com/llvm/llvm-project/pull/111209 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Implement the `degrees` intrinsic (PR #111209)
@@ -1643,6 +1646,23 @@ bool SPIRVInstructionSelector::selectLength(Register ResVReg, .constrainAllUses(TII, TRI, RBI); } +bool SPIRVInstructionSelector::selectDegrees(Register ResVReg, + const SPIRVType *ResType, + MachineInstr &I) const { + + assert(I.getNumOperands() == 3); spall wrote: Doesn't degrees have 1 operand? https://github.com/llvm/llvm-project/pull/111209 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] implement elementwise firstbithigh hlsl builtin (PR #111082)
https://github.com/spall updated https://github.com/llvm/llvm-project/pull/111082 >From 62af64102d96405d9a572a054ad4c2fa87ba8867 Mon Sep 17 00:00:00 2001 From: Sarah Spall Date: Mon, 23 Sep 2024 22:10:59 + Subject: [PATCH 1/4] implement firstbithigh hlsl builtin --- clang/include/clang/Basic/Builtins.td | 6 + clang/lib/CodeGen/CGBuiltin.cpp | 17 ++ clang/lib/CodeGen/CGHLSLRuntime.h | 2 + clang/lib/Headers/hlsl/hlsl_intrinsics.h | 72 + clang/lib/Sema/SemaHLSL.cpp | 18 +++ .../CodeGenHLSL/builtins/firstbithigh.hlsl| 153 ++ .../BuiltIns/firstbithigh-errors.hlsl | 28 llvm/include/llvm/IR/IntrinsicsDirectX.td | 2 + llvm/include/llvm/IR/IntrinsicsSPIRV.td | 2 + llvm/lib/Target/DirectX/DXIL.td | 24 +++ .../DirectX/DirectXTargetTransformInfo.cpp| 2 + .../Target/SPIRV/SPIRVInstructionSelector.cpp | 14 ++ llvm/test/CodeGen/DirectX/firstbithigh.ll | 91 +++ .../CodeGen/DirectX/firstbitshigh_error.ll| 10 ++ .../CodeGen/DirectX/firstbituhigh_error.ll| 10 ++ .../SPIRV/hlsl-intrinsics/firstbithigh.ll | 37 + 16 files changed, 488 insertions(+) create mode 100644 clang/test/CodeGenHLSL/builtins/firstbithigh.hlsl create mode 100644 clang/test/SemaHLSL/BuiltIns/firstbithigh-errors.hlsl create mode 100644 llvm/test/CodeGen/DirectX/firstbithigh.ll create mode 100644 llvm/test/CodeGen/DirectX/firstbitshigh_error.ll create mode 100644 llvm/test/CodeGen/DirectX/firstbituhigh_error.ll create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/firstbithigh.ll diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 382fb6b7a3c031..5c482eba1f4f49 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -4791,6 +4791,12 @@ def HLSLDotProduct : LangBuiltin<"HLSL_LANG"> { let Prototype = "void(...)"; } +def HLSLFirstBitHigh : LangBuiltin<"HLSL_LANG"> { + let Spellings = ["__builtin_hlsl_elementwise_firstbithigh"]; + let Attributes = [NoThrow, Const]; + let Prototype = "void(...)"; +} + def HLSLFrac : LangBuiltin<"HLSL_LANG"> { let Spellings = ["__builtin_hlsl_elementwise_frac"]; let Attributes = [NoThrow, Const]; diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index f6d7db2c204c12..bce44257077ebd 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -18639,6 +18639,14 @@ static Intrinsic::ID getDotProductIntrinsic(CGHLSLRuntime &RT, QualType QT) { return RT.getUDotIntrinsic(); } +Intrinsic::ID getFirstBitHighIntrinsic(CGHLSLRuntime &RT, QualType QT) { + if (QT->hasSignedIntegerRepresentation()) { +return RT.getFirstBitSHighIntrinsic(); + } + + return RT.getFirstBitUHighIntrinsic(); +} + Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, const CallExpr *E, ReturnValueSlot ReturnValue) { @@ -18728,6 +18736,15 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, getDotProductIntrinsic(CGM.getHLSLRuntime(), VecTy0->getElementType()), ArrayRef{Op0, Op1}, nullptr, "hlsl.dot"); } break; + case Builtin::BI__builtin_hlsl_elementwise_firstbithigh: { + +Value *X = EmitScalarExpr(E->getArg(0)); + +return Builder.CreateIntrinsic( + /*ReturnType=*/X->getType(), + getFirstBitHighIntrinsic(CGM.getHLSLRuntime(), E->getArg(0)->getType()), + ArrayRef{X}, nullptr, "hlsl.firstbithigh"); + } case Builtin::BI__builtin_hlsl_lerp: { Value *X = EmitScalarExpr(E->getArg(0)); Value *Y = EmitScalarExpr(E->getArg(1)); diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h index f7621ee20b1243..bbe25a1b50c4e0 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.h +++ b/clang/lib/CodeGen/CGHLSLRuntime.h @@ -91,6 +91,8 @@ class CGHLSLRuntime { GENERATE_HLSL_INTRINSIC_FUNCTION(UDot, udot) GENERATE_HLSL_INTRINSIC_FUNCTION(WaveIsFirstLane, wave_is_first_lane) GENERATE_HLSL_INTRINSIC_FUNCTION(WaveReadLaneAt, wave_readlane) + GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitUHigh, firstbituhigh) + GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitSHigh, firstbitshigh) //===--===// // End of reserved area for HLSL intrinsic getters. diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index 30dce60b3ff702..4b3a4f50ceb981 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -958,6 +958,78 @@ float3 exp2(float3); _HLSL_BUILTIN_ALIAS(__builtin_elementwise_exp2) float4 exp2(float4); +//===--===// +// firstbithigh builtins +//===
[clang] [llvm] [HLSL] implement elementwise firstbithigh hlsl builtin (PR #111082)
https://github.com/spall updated https://github.com/llvm/llvm-project/pull/111082 >From 62af64102d96405d9a572a054ad4c2fa87ba8867 Mon Sep 17 00:00:00 2001 From: Sarah Spall Date: Mon, 23 Sep 2024 22:10:59 + Subject: [PATCH 1/5] implement firstbithigh hlsl builtin --- clang/include/clang/Basic/Builtins.td | 6 + clang/lib/CodeGen/CGBuiltin.cpp | 17 ++ clang/lib/CodeGen/CGHLSLRuntime.h | 2 + clang/lib/Headers/hlsl/hlsl_intrinsics.h | 72 + clang/lib/Sema/SemaHLSL.cpp | 18 +++ .../CodeGenHLSL/builtins/firstbithigh.hlsl| 153 ++ .../BuiltIns/firstbithigh-errors.hlsl | 28 llvm/include/llvm/IR/IntrinsicsDirectX.td | 2 + llvm/include/llvm/IR/IntrinsicsSPIRV.td | 2 + llvm/lib/Target/DirectX/DXIL.td | 24 +++ .../DirectX/DirectXTargetTransformInfo.cpp| 2 + .../Target/SPIRV/SPIRVInstructionSelector.cpp | 14 ++ llvm/test/CodeGen/DirectX/firstbithigh.ll | 91 +++ .../CodeGen/DirectX/firstbitshigh_error.ll| 10 ++ .../CodeGen/DirectX/firstbituhigh_error.ll| 10 ++ .../SPIRV/hlsl-intrinsics/firstbithigh.ll | 37 + 16 files changed, 488 insertions(+) create mode 100644 clang/test/CodeGenHLSL/builtins/firstbithigh.hlsl create mode 100644 clang/test/SemaHLSL/BuiltIns/firstbithigh-errors.hlsl create mode 100644 llvm/test/CodeGen/DirectX/firstbithigh.ll create mode 100644 llvm/test/CodeGen/DirectX/firstbitshigh_error.ll create mode 100644 llvm/test/CodeGen/DirectX/firstbituhigh_error.ll create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/firstbithigh.ll diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 382fb6b7a3c031..5c482eba1f4f49 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -4791,6 +4791,12 @@ def HLSLDotProduct : LangBuiltin<"HLSL_LANG"> { let Prototype = "void(...)"; } +def HLSLFirstBitHigh : LangBuiltin<"HLSL_LANG"> { + let Spellings = ["__builtin_hlsl_elementwise_firstbithigh"]; + let Attributes = [NoThrow, Const]; + let Prototype = "void(...)"; +} + def HLSLFrac : LangBuiltin<"HLSL_LANG"> { let Spellings = ["__builtin_hlsl_elementwise_frac"]; let Attributes = [NoThrow, Const]; diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index f6d7db2c204c12..bce44257077ebd 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -18639,6 +18639,14 @@ static Intrinsic::ID getDotProductIntrinsic(CGHLSLRuntime &RT, QualType QT) { return RT.getUDotIntrinsic(); } +Intrinsic::ID getFirstBitHighIntrinsic(CGHLSLRuntime &RT, QualType QT) { + if (QT->hasSignedIntegerRepresentation()) { +return RT.getFirstBitSHighIntrinsic(); + } + + return RT.getFirstBitUHighIntrinsic(); +} + Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, const CallExpr *E, ReturnValueSlot ReturnValue) { @@ -18728,6 +18736,15 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, getDotProductIntrinsic(CGM.getHLSLRuntime(), VecTy0->getElementType()), ArrayRef{Op0, Op1}, nullptr, "hlsl.dot"); } break; + case Builtin::BI__builtin_hlsl_elementwise_firstbithigh: { + +Value *X = EmitScalarExpr(E->getArg(0)); + +return Builder.CreateIntrinsic( + /*ReturnType=*/X->getType(), + getFirstBitHighIntrinsic(CGM.getHLSLRuntime(), E->getArg(0)->getType()), + ArrayRef{X}, nullptr, "hlsl.firstbithigh"); + } case Builtin::BI__builtin_hlsl_lerp: { Value *X = EmitScalarExpr(E->getArg(0)); Value *Y = EmitScalarExpr(E->getArg(1)); diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h index f7621ee20b1243..bbe25a1b50c4e0 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.h +++ b/clang/lib/CodeGen/CGHLSLRuntime.h @@ -91,6 +91,8 @@ class CGHLSLRuntime { GENERATE_HLSL_INTRINSIC_FUNCTION(UDot, udot) GENERATE_HLSL_INTRINSIC_FUNCTION(WaveIsFirstLane, wave_is_first_lane) GENERATE_HLSL_INTRINSIC_FUNCTION(WaveReadLaneAt, wave_readlane) + GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitUHigh, firstbituhigh) + GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitSHigh, firstbitshigh) //===--===// // End of reserved area for HLSL intrinsic getters. diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index 30dce60b3ff702..4b3a4f50ceb981 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -958,6 +958,78 @@ float3 exp2(float3); _HLSL_BUILTIN_ALIAS(__builtin_elementwise_exp2) float4 exp2(float4); +//===--===// +// firstbithigh builtins +//===
[clang] [llvm] [HLSL] Re-implement countbits with the correct return type (PR #113189)
https://github.com/spall created https://github.com/llvm/llvm-project/pull/113189 Restricts hlsl countbits to always return a uint32. Implements a lowering from llvm.ctpop which has an overloaded return type to dxil cbits op which always returns uint32. Closes #112779 >From f110f3167769d91dd87b260b30c2a61cc754b619 Mon Sep 17 00:00:00 2001 From: Sarah Spall Date: Wed, 16 Oct 2024 19:00:08 + Subject: [PATCH] implement countbits correctly --- clang/lib/Headers/hlsl/hlsl_intrinsics.h | 126 +++--- .../test/CodeGenHLSL/builtins/countbits.hlsl | 42 +++--- .../SemaHLSL/BuiltIns/countbits-errors.hlsl | 14 +- llvm/lib/Target/DirectX/DXIL.td | 5 +- llvm/lib/Target/DirectX/DXILOpLowering.cpp| 64 + llvm/test/CodeGen/DirectX/countbits.ll| 39 -- 6 files changed, 202 insertions(+), 88 deletions(-) diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index 30dce60b3ff702..2a612c3746076c 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -705,66 +705,90 @@ float4 cosh(float4); #ifdef __HLSL_ENABLE_16_BIT _HLSL_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int16_t countbits(int16_t); +constexpr uint countbits(int16_t x) { + return __builtin_elementwise_popcount(x); +} _HLSL_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int16_t2 countbits(int16_t2); +constexpr uint2 countbits(int16_t2 x) { + return __builtin_elementwise_popcount(x); +} _HLSL_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int16_t3 countbits(int16_t3); +constexpr uint3 countbits(int16_t3 x) { + return __builtin_elementwise_popcount(x); +} _HLSL_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int16_t4 countbits(int16_t4); +constexpr uint4 countbits(int16_t4 x) { + return __builtin_elementwise_popcount(x); +} _HLSL_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -uint16_t countbits(uint16_t); +constexpr uint countbits(uint16_t x) { + return __builtin_elementwise_popcount(x); +} _HLSL_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -uint16_t2 countbits(uint16_t2); +constexpr uint2 countbits(uint16_t2 x) { + return __builtin_elementwise_popcount(x); +} _HLSL_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -uint16_t3 countbits(uint16_t3); +constexpr uint3 countbits(uint16_t3 x) { + return __builtin_elementwise_popcount(x); +} _HLSL_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -uint16_t4 countbits(uint16_t4); +constexpr uint4 countbits(uint16_t4 x) { + return __builtin_elementwise_popcount(x); +} #endif -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int countbits(int); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int2 countbits(int2); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int3 countbits(int3); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int4 countbits(int4); - -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -uint countbits(uint); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -uint2 countbits(uint2); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -uint3 countbits(uint3); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -uint4 countbits(uint4); - -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int64_t countbits(int64_t); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int64_t2 countbits(int64_t2); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int64_t3 countbits(int64_t3); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int64_t4 countbits(int64_t4); - -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -uint64_t countbits(uint64_t); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -uint64_t2 countbits(uint64_t2); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -uint64_t3 countbits(uint64_t3); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -uint64_t4 countbits(uint64_t4); +constexpr uint countbits(int x) { + return __builtin_elementwise_popcount(x); +} +constexpr uint2 countbits(int2 x) { + return __builtin_elementwise_popcount(x); +} +constexpr uint3 countbits(int3 x) { + return __builtin_elementwise_popcount(x); +} +constexpr uint4 countbits(int4 x) { + return __builtin_elementwise_popcount(x); +} + +constexpr uint countbits(uint x) { + return __builtin_elementwise_popcount(x); +} +constexpr uint2 countbits(uint2 x) { + return __builtin_elementwise_popcount(x); +} +constexpr uint3 countbits(uint3 x) { + return __builtin_elementwise_popcount(x); +} +constexpr uint4 countbits(uint4 x) { + return __builtin_elementwise_popcount(x); +} + +constexpr uint countbits(int64_t x) { + return __builtin_elementwise_popcount(x); +} +constexpr uint2 countbits(int64_t2 x) { +
[clang] [llvm] [HLSL] Re-implement countbits with the correct return type (PR #113189)
@@ -705,66 +705,74 @@ float4 cosh(float4); #ifdef __HLSL_ENABLE_16_BIT _HLSL_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int16_t countbits(int16_t); spall wrote: When I asked Justin about this he pointed to this link: https://github.com/microsoft/DirectXShaderCompiler/blob/main/utils/hct/gen_intrin_main.txt#L114 and suggested it meant both signed and unsigned were supported. https://github.com/llvm/llvm-project/pull/113189 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Re-implement countbits with the correct return type (PR #113189)
https://github.com/spall updated https://github.com/llvm/llvm-project/pull/113189 >From f110f3167769d91dd87b260b30c2a61cc754b619 Mon Sep 17 00:00:00 2001 From: Sarah Spall Date: Wed, 16 Oct 2024 19:00:08 + Subject: [PATCH 1/2] implement countbits correctly --- clang/lib/Headers/hlsl/hlsl_intrinsics.h | 126 +++--- .../test/CodeGenHLSL/builtins/countbits.hlsl | 42 +++--- .../SemaHLSL/BuiltIns/countbits-errors.hlsl | 14 +- llvm/lib/Target/DirectX/DXIL.td | 5 +- llvm/lib/Target/DirectX/DXILOpLowering.cpp| 64 + llvm/test/CodeGen/DirectX/countbits.ll| 39 -- 6 files changed, 202 insertions(+), 88 deletions(-) diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index 30dce60b3ff702..2a612c3746076c 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -705,66 +705,90 @@ float4 cosh(float4); #ifdef __HLSL_ENABLE_16_BIT _HLSL_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int16_t countbits(int16_t); +constexpr uint countbits(int16_t x) { + return __builtin_elementwise_popcount(x); +} _HLSL_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int16_t2 countbits(int16_t2); +constexpr uint2 countbits(int16_t2 x) { + return __builtin_elementwise_popcount(x); +} _HLSL_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int16_t3 countbits(int16_t3); +constexpr uint3 countbits(int16_t3 x) { + return __builtin_elementwise_popcount(x); +} _HLSL_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int16_t4 countbits(int16_t4); +constexpr uint4 countbits(int16_t4 x) { + return __builtin_elementwise_popcount(x); +} _HLSL_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -uint16_t countbits(uint16_t); +constexpr uint countbits(uint16_t x) { + return __builtin_elementwise_popcount(x); +} _HLSL_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -uint16_t2 countbits(uint16_t2); +constexpr uint2 countbits(uint16_t2 x) { + return __builtin_elementwise_popcount(x); +} _HLSL_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -uint16_t3 countbits(uint16_t3); +constexpr uint3 countbits(uint16_t3 x) { + return __builtin_elementwise_popcount(x); +} _HLSL_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -uint16_t4 countbits(uint16_t4); +constexpr uint4 countbits(uint16_t4 x) { + return __builtin_elementwise_popcount(x); +} #endif -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int countbits(int); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int2 countbits(int2); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int3 countbits(int3); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int4 countbits(int4); - -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -uint countbits(uint); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -uint2 countbits(uint2); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -uint3 countbits(uint3); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -uint4 countbits(uint4); - -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int64_t countbits(int64_t); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int64_t2 countbits(int64_t2); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int64_t3 countbits(int64_t3); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int64_t4 countbits(int64_t4); - -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -uint64_t countbits(uint64_t); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -uint64_t2 countbits(uint64_t2); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -uint64_t3 countbits(uint64_t3); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -uint64_t4 countbits(uint64_t4); +constexpr uint countbits(int x) { + return __builtin_elementwise_popcount(x); +} +constexpr uint2 countbits(int2 x) { + return __builtin_elementwise_popcount(x); +} +constexpr uint3 countbits(int3 x) { + return __builtin_elementwise_popcount(x); +} +constexpr uint4 countbits(int4 x) { + return __builtin_elementwise_popcount(x); +} + +constexpr uint countbits(uint x) { + return __builtin_elementwise_popcount(x); +} +constexpr uint2 countbits(uint2 x) { + return __builtin_elementwise_popcount(x); +} +constexpr uint3 countbits(uint3 x) { + return __builtin_elementwise_popcount(x); +} +constexpr uint4 countbits(uint4 x) { + return __builtin_elementwise_popcount(x); +} + +constexpr uint countbits(int64_t x) { + return __builtin_elementwise_popcount(x); +} +constexpr uint2 countbits(int64_t2 x) { + return __builtin_elementwise_popcount(x); +} +constexpr uint3 countbits(int64_t3 x) { + return __builtin_elementwise_popcount(x); +} +constexpr uint4 countbits(int64_t4 x) { + return
[clang] [llvm] [HLSL] implement elementwise firstbithigh hlsl builtin (PR #111082)
spall wrote: > > > Despite all of this, DXC does indeed support 16- and 64-bit overloads, as > > > seen here: https://hlsl.godbolt.org/z/qbc17xz35 > > > Note that the return type of the operation is not overloaded - all of the > > > overloads of this function return uint. > > > > > > Why is the return type not overloaded? Isn't it overloaded for countbits > > which is a similar function. > > The return type for countbits is also not overloaded: > https://hlsl.godbolt.org/z/oGYhsjEGc - in fact none of the operations that > use the `unaryBits` operation class are overloaded on the return type. > > The code we're generating with clang for countbits right now actually just > looks like it's wrong. It doesn't match what DXC does at all: > https://hlsl.godbolt.org/z/K8n3j5o3K Addressed here: https://github.com/llvm/llvm-project/pull/113189 https://github.com/llvm/llvm-project/pull/111082 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Re-implement countbits with the correct return type (PR #113189)
@@ -461,6 +461,67 @@ class OpLowerer { }); } + [[nodiscard]] bool lowerCtpopToCBits(Function &F) { +IRBuilder<> &IRB = OpBuilder.getIRB(); +Type *Int32Ty = IRB.getInt32Ty(); + +return replaceFunction(F, [&](CallInst *CI) -> Error { + IRB.SetInsertPoint(CI); + SmallVector Args; + Args.append(CI->arg_begin(), CI->arg_end()); + + Type *RetTy = Int32Ty; + Type *FRT = F.getReturnType(); + if (FRT->isVectorTy()) { +VectorType *VT = cast(FRT); +RetTy = VectorType::get(RetTy, VT); + } + + Expected OpCall = OpBuilder.tryCreateOp( + dxil::OpCode::CBits, Args, CI->getName(), RetTy); + if (Error E = OpCall.takeError()) +return E; + + // If the result type is 32 bits we can do a direct replacement. + if (FRT->isIntOrIntVectorTy(32)) { +CI->replaceAllUsesWith(*OpCall); +CI->eraseFromParent(); +return Error::success(); + } + + unsigned CastOp; + if (FRT->isIntOrIntVectorTy(16)) +CastOp = Instruction::ZExt; spall wrote: The extension should only be on the return value which is always unsigned. Is this code wrong with that in mind? https://github.com/llvm/llvm-project/pull/113189 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] implement elementwise firstbithigh hlsl builtin (PR #111082)
https://github.com/spall updated https://github.com/llvm/llvm-project/pull/111082 >From 62af64102d96405d9a572a054ad4c2fa87ba8867 Mon Sep 17 00:00:00 2001 From: Sarah Spall Date: Mon, 23 Sep 2024 22:10:59 + Subject: [PATCH 1/6] implement firstbithigh hlsl builtin --- clang/include/clang/Basic/Builtins.td | 6 + clang/lib/CodeGen/CGBuiltin.cpp | 17 ++ clang/lib/CodeGen/CGHLSLRuntime.h | 2 + clang/lib/Headers/hlsl/hlsl_intrinsics.h | 72 + clang/lib/Sema/SemaHLSL.cpp | 18 +++ .../CodeGenHLSL/builtins/firstbithigh.hlsl| 153 ++ .../BuiltIns/firstbithigh-errors.hlsl | 28 llvm/include/llvm/IR/IntrinsicsDirectX.td | 2 + llvm/include/llvm/IR/IntrinsicsSPIRV.td | 2 + llvm/lib/Target/DirectX/DXIL.td | 24 +++ .../DirectX/DirectXTargetTransformInfo.cpp| 2 + .../Target/SPIRV/SPIRVInstructionSelector.cpp | 14 ++ llvm/test/CodeGen/DirectX/firstbithigh.ll | 91 +++ .../CodeGen/DirectX/firstbitshigh_error.ll| 10 ++ .../CodeGen/DirectX/firstbituhigh_error.ll| 10 ++ .../SPIRV/hlsl-intrinsics/firstbithigh.ll | 37 + 16 files changed, 488 insertions(+) create mode 100644 clang/test/CodeGenHLSL/builtins/firstbithigh.hlsl create mode 100644 clang/test/SemaHLSL/BuiltIns/firstbithigh-errors.hlsl create mode 100644 llvm/test/CodeGen/DirectX/firstbithigh.ll create mode 100644 llvm/test/CodeGen/DirectX/firstbitshigh_error.ll create mode 100644 llvm/test/CodeGen/DirectX/firstbituhigh_error.ll create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/firstbithigh.ll diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 382fb6b7a3c031..5c482eba1f4f49 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -4791,6 +4791,12 @@ def HLSLDotProduct : LangBuiltin<"HLSL_LANG"> { let Prototype = "void(...)"; } +def HLSLFirstBitHigh : LangBuiltin<"HLSL_LANG"> { + let Spellings = ["__builtin_hlsl_elementwise_firstbithigh"]; + let Attributes = [NoThrow, Const]; + let Prototype = "void(...)"; +} + def HLSLFrac : LangBuiltin<"HLSL_LANG"> { let Spellings = ["__builtin_hlsl_elementwise_frac"]; let Attributes = [NoThrow, Const]; diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index f6d7db2c204c12..bce44257077ebd 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -18639,6 +18639,14 @@ static Intrinsic::ID getDotProductIntrinsic(CGHLSLRuntime &RT, QualType QT) { return RT.getUDotIntrinsic(); } +Intrinsic::ID getFirstBitHighIntrinsic(CGHLSLRuntime &RT, QualType QT) { + if (QT->hasSignedIntegerRepresentation()) { +return RT.getFirstBitSHighIntrinsic(); + } + + return RT.getFirstBitUHighIntrinsic(); +} + Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, const CallExpr *E, ReturnValueSlot ReturnValue) { @@ -18728,6 +18736,15 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, getDotProductIntrinsic(CGM.getHLSLRuntime(), VecTy0->getElementType()), ArrayRef{Op0, Op1}, nullptr, "hlsl.dot"); } break; + case Builtin::BI__builtin_hlsl_elementwise_firstbithigh: { + +Value *X = EmitScalarExpr(E->getArg(0)); + +return Builder.CreateIntrinsic( + /*ReturnType=*/X->getType(), + getFirstBitHighIntrinsic(CGM.getHLSLRuntime(), E->getArg(0)->getType()), + ArrayRef{X}, nullptr, "hlsl.firstbithigh"); + } case Builtin::BI__builtin_hlsl_lerp: { Value *X = EmitScalarExpr(E->getArg(0)); Value *Y = EmitScalarExpr(E->getArg(1)); diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h index f7621ee20b1243..bbe25a1b50c4e0 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.h +++ b/clang/lib/CodeGen/CGHLSLRuntime.h @@ -91,6 +91,8 @@ class CGHLSLRuntime { GENERATE_HLSL_INTRINSIC_FUNCTION(UDot, udot) GENERATE_HLSL_INTRINSIC_FUNCTION(WaveIsFirstLane, wave_is_first_lane) GENERATE_HLSL_INTRINSIC_FUNCTION(WaveReadLaneAt, wave_readlane) + GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitUHigh, firstbituhigh) + GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitSHigh, firstbitshigh) //===--===// // End of reserved area for HLSL intrinsic getters. diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index 30dce60b3ff702..4b3a4f50ceb981 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -958,6 +958,78 @@ float3 exp2(float3); _HLSL_BUILTIN_ALIAS(__builtin_elementwise_exp2) float4 exp2(float4); +//===--===// +// firstbithigh builtins +//===
[clang] [HLSL] get inout/out ABI for array parameters working (PR #111047)
https://github.com/spall created https://github.com/llvm/llvm-project/pull/111047 Get inout/out parameters working for HLSL Arrays. Utilizes the fix from #109323, and corrects the assignment behavior slightly to allow for Non-LValues on the RHS. Closes #106917 >From c73ce3707e59242b8ccbb6757a290938c2d39e5e Mon Sep 17 00:00:00 2001 From: Sarah Spall Date: Tue, 17 Sep 2024 20:25:46 + Subject: [PATCH 1/4] theoretically fix issue --- clang/lib/Sema/SemaType.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index c44fc9c4194ca4..8c80ece635fbff 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -5675,6 +5675,9 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, assert(!T.isNull() && "T must not be null at the end of this function"); if (!AreDeclaratorChunksValid) return Context.getTrivialTypeSourceInfo(T); + + if (state.didParseHLSLParamMod() && !T->isConstantArrayType()) +T = S.HLSL().getInoutParameterType(T); return GetTypeSourceInfoForDeclarator(state, T, TInfo); } @@ -8562,7 +8565,6 @@ static void HandleHLSLParamModifierAttr(TypeProcessingState &State, return; if (Attr.getSemanticSpelling() == HLSLParamModifierAttr::Keyword_inout || Attr.getSemanticSpelling() == HLSLParamModifierAttr::Keyword_out) { -CurType = S.HLSL().getInoutParameterType(CurType); State.setParsedHLSLParamMod(true); } } >From 0f64ad26f2218a037694b01649a4ebd5e2bf766c Mon Sep 17 00:00:00 2001 From: Sarah Spall Date: Wed, 2 Oct 2024 21:34:02 + Subject: [PATCH 2/4] get inout working --- clang/include/clang/AST/ASTContext.h | 4 +++ clang/lib/AST/ASTContext.cpp | 10 +++ clang/lib/CodeGen/CGCall.cpp | 3 +- clang/lib/CodeGen/CGExpr.cpp | 7 +++-- clang/lib/Sema/SemaExprCXX.cpp | 13 +++-- clang/lib/Sema/SemaOverload.cpp | 43 6 files changed, 55 insertions(+), 25 deletions(-) diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index a4d36f2eacd5d1..bdd4d86c30d389 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -1471,6 +1471,10 @@ class ASTContext : public RefCountedBase { /// type to the decayed type. QualType getDecayedType(QualType Orig, QualType Decayed) const; + /// Return the uniqued reference to a constant array type from the + /// original array parameter type. + QualType getConstantArrayFromArrayParameterType(QualType Ty) const; + /// Return the uniqued reference to a specified array parameter type from the /// original array type. QualType getArrayParameterType(QualType Ty) const; diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 735def67f7840f..b49783176f79d8 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -3830,6 +3830,16 @@ QualType ASTContext::getDecayedType(QualType T) const { return getDecayedType(T, Decayed); } +QualType ASTContext::getConstantArrayFromArrayParameterType(QualType Ty) const { + if (Ty->isConstantArrayType() && !Ty->isArrayParameterType()) +return Ty; + assert(Ty->isArrayParameterType() && "Ty must be an array parameter type."); + const auto *ATy = cast(Ty); + return getConstantArrayType(ATy->getElementType(), ATy->getSize(), + ATy->getSizeExpr(), ATy->getSizeModifier(), + ATy->getIndexTypeQualifiers().getAsOpaqueValue()); +} + QualType ASTContext::getArrayParameterType(QualType Ty) const { if (Ty->isArrayParameterType()) return Ty; diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 4ae981e4013e9c..fe578cacc64de1 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -4690,7 +4690,8 @@ void CodeGenFunction::EmitCallArg(CallArgList &args, const Expr *E, return emitWritebackArg(*this, args, CRE); } - assert(type->isReferenceType() == E->isGLValue() && + assert(type->isArrayParameterType() || +(type->isReferenceType() == E->isGLValue()) && "reference binding to unmaterialized r-value!"); // Add writeback for HLSLOutParamExpr. diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 4c7cbf2aec..9f7ce71b30b498 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -5811,9 +5811,12 @@ LValue CodeGenFunction::EmitBinaryOperatorLValue(const BinaryOperator *E) { // This function implements trivial copy assignment for HLSL's // assignable constant arrays. LValue CodeGenFunction::EmitHLSLArrayAssignLValue(const BinaryOperator *E) { - LValue TrivialAssignmentRHS = EmitLValue(E->getRHS()); + // Don't emit an LValue for the RHS because it might not be an LValue LValue LHS = EmitLValue(E->getLHS()); - EmitAggregateAssign(LHS, TrivialAssignmentRHS, E->getLHS(
[clang] [HLSL] get inout/out ABI for array parameters working (PR #111047)
https://github.com/spall updated https://github.com/llvm/llvm-project/pull/111047 >From c73ce3707e59242b8ccbb6757a290938c2d39e5e Mon Sep 17 00:00:00 2001 From: Sarah Spall Date: Tue, 17 Sep 2024 20:25:46 + Subject: [PATCH 1/5] theoretically fix issue --- clang/lib/Sema/SemaType.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index c44fc9c4194ca4..8c80ece635fbff 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -5675,6 +5675,9 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, assert(!T.isNull() && "T must not be null at the end of this function"); if (!AreDeclaratorChunksValid) return Context.getTrivialTypeSourceInfo(T); + + if (state.didParseHLSLParamMod() && !T->isConstantArrayType()) +T = S.HLSL().getInoutParameterType(T); return GetTypeSourceInfoForDeclarator(state, T, TInfo); } @@ -8562,7 +8565,6 @@ static void HandleHLSLParamModifierAttr(TypeProcessingState &State, return; if (Attr.getSemanticSpelling() == HLSLParamModifierAttr::Keyword_inout || Attr.getSemanticSpelling() == HLSLParamModifierAttr::Keyword_out) { -CurType = S.HLSL().getInoutParameterType(CurType); State.setParsedHLSLParamMod(true); } } >From 0f64ad26f2218a037694b01649a4ebd5e2bf766c Mon Sep 17 00:00:00 2001 From: Sarah Spall Date: Wed, 2 Oct 2024 21:34:02 + Subject: [PATCH 2/5] get inout working --- clang/include/clang/AST/ASTContext.h | 4 +++ clang/lib/AST/ASTContext.cpp | 10 +++ clang/lib/CodeGen/CGCall.cpp | 3 +- clang/lib/CodeGen/CGExpr.cpp | 7 +++-- clang/lib/Sema/SemaExprCXX.cpp | 13 +++-- clang/lib/Sema/SemaOverload.cpp | 43 6 files changed, 55 insertions(+), 25 deletions(-) diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index a4d36f2eacd5d1..bdd4d86c30d389 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -1471,6 +1471,10 @@ class ASTContext : public RefCountedBase { /// type to the decayed type. QualType getDecayedType(QualType Orig, QualType Decayed) const; + /// Return the uniqued reference to a constant array type from the + /// original array parameter type. + QualType getConstantArrayFromArrayParameterType(QualType Ty) const; + /// Return the uniqued reference to a specified array parameter type from the /// original array type. QualType getArrayParameterType(QualType Ty) const; diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 735def67f7840f..b49783176f79d8 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -3830,6 +3830,16 @@ QualType ASTContext::getDecayedType(QualType T) const { return getDecayedType(T, Decayed); } +QualType ASTContext::getConstantArrayFromArrayParameterType(QualType Ty) const { + if (Ty->isConstantArrayType() && !Ty->isArrayParameterType()) +return Ty; + assert(Ty->isArrayParameterType() && "Ty must be an array parameter type."); + const auto *ATy = cast(Ty); + return getConstantArrayType(ATy->getElementType(), ATy->getSize(), + ATy->getSizeExpr(), ATy->getSizeModifier(), + ATy->getIndexTypeQualifiers().getAsOpaqueValue()); +} + QualType ASTContext::getArrayParameterType(QualType Ty) const { if (Ty->isArrayParameterType()) return Ty; diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 4ae981e4013e9c..fe578cacc64de1 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -4690,7 +4690,8 @@ void CodeGenFunction::EmitCallArg(CallArgList &args, const Expr *E, return emitWritebackArg(*this, args, CRE); } - assert(type->isReferenceType() == E->isGLValue() && + assert(type->isArrayParameterType() || +(type->isReferenceType() == E->isGLValue()) && "reference binding to unmaterialized r-value!"); // Add writeback for HLSLOutParamExpr. diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 4c7cbf2aec..9f7ce71b30b498 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -5811,9 +5811,12 @@ LValue CodeGenFunction::EmitBinaryOperatorLValue(const BinaryOperator *E) { // This function implements trivial copy assignment for HLSL's // assignable constant arrays. LValue CodeGenFunction::EmitHLSLArrayAssignLValue(const BinaryOperator *E) { - LValue TrivialAssignmentRHS = EmitLValue(E->getRHS()); + // Don't emit an LValue for the RHS because it might not be an LValue LValue LHS = EmitLValue(E->getLHS()); - EmitAggregateAssign(LHS, TrivialAssignmentRHS, E->getLHS()->getType()); + // In C assignment operator RHS is often an RValue. + // EmitAggregateAssign expects an LValue for the RHS so call the below + // function instead. + EmitInitiali
[clang] [llvm] [HLSL] implement elementwise firstbithigh hlsl builtin (PR #111082)
https://github.com/spall created https://github.com/llvm/llvm-project/pull/111082 Implements elementwise firstbithigh hlsl builtin. Implements firstbituhigh intrinsic for spirv and directx, which handles unsigned integers Implements firstbitshigh intrinsic for spirv and directx, which handles signed integers. Closes #99115 >From e9ed9f9a0415544781f8334b305eb3916fc0862c Mon Sep 17 00:00:00 2001 From: Sarah Spall Date: Mon, 23 Sep 2024 22:10:59 + Subject: [PATCH] implement firstbithigh hlsl builtin --- clang/include/clang/Basic/Builtins.td | 6 + clang/lib/CodeGen/CGBuiltin.cpp | 17 ++ clang/lib/CodeGen/CGHLSLRuntime.h | 2 + clang/lib/Headers/hlsl/hlsl_intrinsics.h | 72 + clang/lib/Sema/SemaHLSL.cpp | 18 +++ .../CodeGenHLSL/builtins/firstbithigh.hlsl| 153 ++ .../BuiltIns/firstbithigh-errors.hlsl | 28 llvm/include/llvm/IR/IntrinsicsDirectX.td | 2 + llvm/include/llvm/IR/IntrinsicsSPIRV.td | 2 + llvm/lib/Target/DirectX/DXIL.td | 24 +++ .../DirectX/DirectXTargetTransformInfo.cpp| 2 + .../Target/SPIRV/SPIRVInstructionSelector.cpp | 14 ++ llvm/test/CodeGen/DirectX/firstbithigh.ll | 91 +++ .../CodeGen/DirectX/firstbitshigh_error.ll| 10 ++ .../CodeGen/DirectX/firstbituhigh_error.ll| 10 ++ .../SPIRV/hlsl-intrinsics/firstbithigh.ll | 37 + 16 files changed, 488 insertions(+) create mode 100644 clang/test/CodeGenHLSL/builtins/firstbithigh.hlsl create mode 100644 clang/test/SemaHLSL/BuiltIns/firstbithigh-errors.hlsl create mode 100644 llvm/test/CodeGen/DirectX/firstbithigh.ll create mode 100644 llvm/test/CodeGen/DirectX/firstbitshigh_error.ll create mode 100644 llvm/test/CodeGen/DirectX/firstbituhigh_error.ll create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/firstbithigh.ll diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index a726a0ef4b4bd2..cc4630c281052d 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -4751,6 +4751,12 @@ def HLSLDotProduct : LangBuiltin<"HLSL_LANG"> { let Prototype = "void(...)"; } +def HLSLFirstBitHigh : LangBuiltin<"HLSL_LANG"> { + let Spellings = ["__builtin_hlsl_elementwise_firstbithigh"]; + let Attributes = [NoThrow, Const]; + let Prototype = "void(...)"; +} + def HLSLFrac : LangBuiltin<"HLSL_LANG"> { let Spellings = ["__builtin_hlsl_elementwise_frac"]; let Attributes = [NoThrow, Const]; diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 43700ea9dd3cfd..6033dcffb3a6da 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -18631,6 +18631,14 @@ static Intrinsic::ID getDotProductIntrinsic(CGHLSLRuntime &RT, QualType QT) { return RT.getUDotIntrinsic(); } +Intrinsic::ID getFirstBitHighIntrinsic(CGHLSLRuntime &RT, QualType QT) { + if (QT->hasSignedIntegerRepresentation()) { +return RT.getFirstBitSHighIntrinsic(); + } + + return RT.getFirstBitUHighIntrinsic(); +} + Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, const CallExpr *E, ReturnValueSlot ReturnValue) { @@ -18720,6 +18728,15 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, getDotProductIntrinsic(CGM.getHLSLRuntime(), VecTy0->getElementType()), ArrayRef{Op0, Op1}, nullptr, "hlsl.dot"); } break; + case Builtin::BI__builtin_hlsl_elementwise_firstbithigh: { + +Value *X = EmitScalarExpr(E->getArg(0)); + +return Builder.CreateIntrinsic( + /*ReturnType=*/X->getType(), + getFirstBitHighIntrinsic(CGM.getHLSLRuntime(), E->getArg(0)->getType()), + ArrayRef{X}, nullptr, "hlsl.firstbithigh"); + } case Builtin::BI__builtin_hlsl_lerp: { Value *X = EmitScalarExpr(E->getArg(0)); Value *Y = EmitScalarExpr(E->getArg(1)); diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h index 6722d2c7c50a2b..03ddef95800e1a 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.h +++ b/clang/lib/CodeGen/CGHLSLRuntime.h @@ -88,6 +88,8 @@ class CGHLSLRuntime { GENERATE_HLSL_INTRINSIC_FUNCTION(SDot, sdot) GENERATE_HLSL_INTRINSIC_FUNCTION(UDot, udot) GENERATE_HLSL_INTRINSIC_FUNCTION(WaveIsFirstLane, wave_is_first_lane) + GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitUHigh, firstbituhigh) + GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitSHigh, firstbitshigh) //===--===// // End of reserved area for HLSL intrinsic getters. diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index c3ecfc7c90d433..afb7bd33374111 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -928,6 +928,78 @@ float3 exp2(float3);
[clang] [llvm] [HLSL] implement elementwise firstbithigh hlsl builtin (PR #111082)
https://github.com/spall updated https://github.com/llvm/llvm-project/pull/111082 >From e9ed9f9a0415544781f8334b305eb3916fc0862c Mon Sep 17 00:00:00 2001 From: Sarah Spall Date: Mon, 23 Sep 2024 22:10:59 + Subject: [PATCH 1/2] implement firstbithigh hlsl builtin --- clang/include/clang/Basic/Builtins.td | 6 + clang/lib/CodeGen/CGBuiltin.cpp | 17 ++ clang/lib/CodeGen/CGHLSLRuntime.h | 2 + clang/lib/Headers/hlsl/hlsl_intrinsics.h | 72 + clang/lib/Sema/SemaHLSL.cpp | 18 +++ .../CodeGenHLSL/builtins/firstbithigh.hlsl| 153 ++ .../BuiltIns/firstbithigh-errors.hlsl | 28 llvm/include/llvm/IR/IntrinsicsDirectX.td | 2 + llvm/include/llvm/IR/IntrinsicsSPIRV.td | 2 + llvm/lib/Target/DirectX/DXIL.td | 24 +++ .../DirectX/DirectXTargetTransformInfo.cpp| 2 + .../Target/SPIRV/SPIRVInstructionSelector.cpp | 14 ++ llvm/test/CodeGen/DirectX/firstbithigh.ll | 91 +++ .../CodeGen/DirectX/firstbitshigh_error.ll| 10 ++ .../CodeGen/DirectX/firstbituhigh_error.ll| 10 ++ .../SPIRV/hlsl-intrinsics/firstbithigh.ll | 37 + 16 files changed, 488 insertions(+) create mode 100644 clang/test/CodeGenHLSL/builtins/firstbithigh.hlsl create mode 100644 clang/test/SemaHLSL/BuiltIns/firstbithigh-errors.hlsl create mode 100644 llvm/test/CodeGen/DirectX/firstbithigh.ll create mode 100644 llvm/test/CodeGen/DirectX/firstbitshigh_error.ll create mode 100644 llvm/test/CodeGen/DirectX/firstbituhigh_error.ll create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/firstbithigh.ll diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index a726a0ef4b4bd2..cc4630c281052d 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -4751,6 +4751,12 @@ def HLSLDotProduct : LangBuiltin<"HLSL_LANG"> { let Prototype = "void(...)"; } +def HLSLFirstBitHigh : LangBuiltin<"HLSL_LANG"> { + let Spellings = ["__builtin_hlsl_elementwise_firstbithigh"]; + let Attributes = [NoThrow, Const]; + let Prototype = "void(...)"; +} + def HLSLFrac : LangBuiltin<"HLSL_LANG"> { let Spellings = ["__builtin_hlsl_elementwise_frac"]; let Attributes = [NoThrow, Const]; diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 43700ea9dd3cfd..6033dcffb3a6da 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -18631,6 +18631,14 @@ static Intrinsic::ID getDotProductIntrinsic(CGHLSLRuntime &RT, QualType QT) { return RT.getUDotIntrinsic(); } +Intrinsic::ID getFirstBitHighIntrinsic(CGHLSLRuntime &RT, QualType QT) { + if (QT->hasSignedIntegerRepresentation()) { +return RT.getFirstBitSHighIntrinsic(); + } + + return RT.getFirstBitUHighIntrinsic(); +} + Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, const CallExpr *E, ReturnValueSlot ReturnValue) { @@ -18720,6 +18728,15 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, getDotProductIntrinsic(CGM.getHLSLRuntime(), VecTy0->getElementType()), ArrayRef{Op0, Op1}, nullptr, "hlsl.dot"); } break; + case Builtin::BI__builtin_hlsl_elementwise_firstbithigh: { + +Value *X = EmitScalarExpr(E->getArg(0)); + +return Builder.CreateIntrinsic( + /*ReturnType=*/X->getType(), + getFirstBitHighIntrinsic(CGM.getHLSLRuntime(), E->getArg(0)->getType()), + ArrayRef{X}, nullptr, "hlsl.firstbithigh"); + } case Builtin::BI__builtin_hlsl_lerp: { Value *X = EmitScalarExpr(E->getArg(0)); Value *Y = EmitScalarExpr(E->getArg(1)); diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h index 6722d2c7c50a2b..03ddef95800e1a 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.h +++ b/clang/lib/CodeGen/CGHLSLRuntime.h @@ -88,6 +88,8 @@ class CGHLSLRuntime { GENERATE_HLSL_INTRINSIC_FUNCTION(SDot, sdot) GENERATE_HLSL_INTRINSIC_FUNCTION(UDot, udot) GENERATE_HLSL_INTRINSIC_FUNCTION(WaveIsFirstLane, wave_is_first_lane) + GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitUHigh, firstbituhigh) + GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitSHigh, firstbitshigh) //===--===// // End of reserved area for HLSL intrinsic getters. diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index c3ecfc7c90d433..afb7bd33374111 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -928,6 +928,78 @@ float3 exp2(float3); _HLSL_BUILTIN_ALIAS(__builtin_elementwise_exp2) float4 exp2(float4); +//===--===// +// firstbithigh builtins +//===---
[clang] [llvm] [HLSL] implement elementwise firstbithigh hlsl builtin (PR #111082)
@@ -0,0 +1,37 @@ +; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %} + +; CHECK: OpMemoryModel Logical GLSL450 + +define noundef i32 @firstbituhigh_i32(i32 noundef %a) { +entry: +; CHECK: %[[#]] = OpExtInst %[[#]] %[[#]] FindUMsb %[[#]] + %elt.firstbituhigh = call i32 @llvm.spv.firstbituhigh.i32(i32 %a) + ret i32 %elt.firstbituhigh +} + +define noundef i16 @firstbituhigh_i16(i16 noundef %a) { +entry: +; CHECK: %[[#]] = OpExtInst %[[#]] %[[#]] FindUMsb %[[#]] + %elt.firstbituhigh = call i16 @llvm.spv.firstbituhigh.i16(i16 %a) spall wrote: this was removed since only 32 bit is supported. https://github.com/llvm/llvm-project/pull/111082 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] implement elementwise firstbithigh hlsl builtin (PR #111082)
https://github.com/spall edited https://github.com/llvm/llvm-project/pull/111082 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] implement elementwise firstbithigh hlsl builtin (PR #111082)
spall wrote: > It is not correct to limit firstbithigh to 32 bit integers. There are a > couple of reasons that might make one think that it is, but we do in fact > want/need to support int16 and int64 here. > > 1. The [HLSL > docs](https://learn.microsoft.com/en-us/windows/win32/direct3dhlsl/firstbithigh) > only mention integer. Unfortunately that's true for most of these functions, > as many of these docs were not updated as 64 and 16 bit types gained support > in the language. > If you click through the definition of Int it defines it to be 32 bits. > 2. DXC's SPIR-V implementation doesn't handle 16- and 64-bit for these > functions. As noted in [Incorrect SPIR-V generated when `firstbithigh` is > used on a `uint64_t` > microsoft/DirectXShaderCompiler#4702](https://github.com/microsoft/DirectXShaderCompiler/issues/4702) > we decided not to implement those overloads in DXC, but should reconsider > this for clang. > > > Despite all of this, DXC does indeed support 16- and 64-bit overloads, as > seen here: https://hlsl.godbolt.org/z/qbc17xz35 > > Note that the return type of the operation is not overloaded - all of the > overloads of this function return uint. https://github.com/microsoft/DirectXShaderCompiler/blob/main/docs/DXIL.rst#firstbithi FirstBitHi does explicitly mention only 32 bit integers. https://github.com/llvm/llvm-project/pull/111082 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] implement elementwise firstbithigh hlsl builtin (PR #111082)
@@ -808,6 +835,20 @@ bool SPIRVInstructionSelector::selectExtInst(Register ResVReg, return false; } +bool SPIRVInstructionSelector::selectNAryOpWithSrcs(Register ResVReg, +const SPIRVType *ResType, +MachineInstr &I, +std::vector Srcs, +unsigned Opcode) const { + auto MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Opcode)) + .addDef(ResVReg) + .addUse(GR.getSPIRVTypeID(ResType)); + for (Register SReg : Srcs) { +MIB.addUse(SReg); spall wrote: Should I do that as part of this PR? https://github.com/llvm/llvm-project/pull/111082 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] implement elementwise firstbithigh hlsl builtin (PR #111082)
@@ -424,7 +424,7 @@ Register SPIRVGlobalRegistry::getOrCreateCompositeOrNull( LLT LLTy = LLT::scalar(64); Register SpvVecConst = CurMF->getRegInfo().createGenericVirtualRegister(LLTy); -CurMF->getRegInfo().setRegClass(SpvVecConst, &SPIRV::iIDRegClass); +CurMF->getRegInfo().setRegClass(SpvVecConst, getRegClass(SpvType)); spall wrote: Happy to put it in its own PR if that is what people want. I just left it here since it is such a small change. https://github.com/llvm/llvm-project/pull/111082 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Re-implement countbits with the correct return type (PR #113189)
@@ -461,6 +461,67 @@ class OpLowerer { }); } + [[nodiscard]] bool lowerCtpopToCBits(Function &F) { +IRBuilder<> &IRB = OpBuilder.getIRB(); +Type *Int32Ty = IRB.getInt32Ty(); + +return replaceFunction(F, [&](CallInst *CI) -> Error { + IRB.SetInsertPoint(CI); + SmallVector Args; + Args.append(CI->arg_begin(), CI->arg_end()); + + Type *RetTy = Int32Ty; + Type *FRT = F.getReturnType(); + if (FRT->isVectorTy()) { +VectorType *VT = cast(FRT); +RetTy = VectorType::get(RetTy, VT); + } + + Expected OpCall = OpBuilder.tryCreateOp( + dxil::OpCode::CBits, Args, CI->getName(), RetTy); + if (Error E = OpCall.takeError()) +return E; + + // If the result type is 32 bits we can do a direct replacement. + if (FRT->isIntOrIntVectorTy(32)) { +CI->replaceAllUsesWith(*OpCall); +CI->eraseFromParent(); +return Error::success(); + } + + unsigned CastOp; + if (FRT->isIntOrIntVectorTy(16)) +CastOp = Instruction::ZExt; + else // must be 64 bits +CastOp = Instruction::Trunc; + + // It is correct to replace the ctpop with the dxil op and + // remove an existing cast iff the cast is the only usage of + // the ctpop spall wrote: This is true, I'll update the language. https://github.com/llvm/llvm-project/pull/113189 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [HLSL] get inout/out ABI for array parameters working (PR #111047)
@@ -4690,8 +4690,9 @@ void CodeGenFunction::EmitCallArg(CallArgList &args, const Expr *E, return emitWritebackArg(*this, args, CRE); } - assert(type->isReferenceType() == E->isGLValue() && - "reference binding to unmaterialized r-value!"); + assert(type->isArrayParameterType() || + (type->isReferenceType() == E->isGLValue()) && + "reference binding to unmaterialized r-value!"); spall wrote: I think failing the original assert means its an r-value, so its both an array parameter type and an r value? https://github.com/llvm/llvm-project/pull/111047 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Re-implement countbits with the correct return type (PR #113189)
https://github.com/spall updated https://github.com/llvm/llvm-project/pull/113189 >From 23d62026c8338e6ad92495cfcaa54ff1fa5d08f0 Mon Sep 17 00:00:00 2001 From: Sarah Spall Date: Wed, 16 Oct 2024 19:00:08 + Subject: [PATCH 1/5] implement countbits correctly --- clang/lib/Headers/hlsl/hlsl_intrinsics.h | 126 +++--- .../test/CodeGenHLSL/builtins/countbits.hlsl | 42 +++--- .../SemaHLSL/BuiltIns/countbits-errors.hlsl | 14 +- llvm/lib/Target/DirectX/DXIL.td | 5 +- llvm/lib/Target/DirectX/DXILOpLowering.cpp| 64 + llvm/test/CodeGen/DirectX/countbits.ll| 39 -- 6 files changed, 202 insertions(+), 88 deletions(-) diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index 8ade4b27f360fb..7936506a0461b6 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -723,66 +723,90 @@ float4 cosh(float4); #ifdef __HLSL_ENABLE_16_BIT _HLSL_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int16_t countbits(int16_t); +constexpr uint countbits(int16_t x) { + return __builtin_elementwise_popcount(x); +} _HLSL_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int16_t2 countbits(int16_t2); +constexpr uint2 countbits(int16_t2 x) { + return __builtin_elementwise_popcount(x); +} _HLSL_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int16_t3 countbits(int16_t3); +constexpr uint3 countbits(int16_t3 x) { + return __builtin_elementwise_popcount(x); +} _HLSL_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int16_t4 countbits(int16_t4); +constexpr uint4 countbits(int16_t4 x) { + return __builtin_elementwise_popcount(x); +} _HLSL_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -uint16_t countbits(uint16_t); +constexpr uint countbits(uint16_t x) { + return __builtin_elementwise_popcount(x); +} _HLSL_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -uint16_t2 countbits(uint16_t2); +constexpr uint2 countbits(uint16_t2 x) { + return __builtin_elementwise_popcount(x); +} _HLSL_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -uint16_t3 countbits(uint16_t3); +constexpr uint3 countbits(uint16_t3 x) { + return __builtin_elementwise_popcount(x); +} _HLSL_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -uint16_t4 countbits(uint16_t4); +constexpr uint4 countbits(uint16_t4 x) { + return __builtin_elementwise_popcount(x); +} #endif -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int countbits(int); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int2 countbits(int2); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int3 countbits(int3); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int4 countbits(int4); - -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -uint countbits(uint); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -uint2 countbits(uint2); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -uint3 countbits(uint3); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -uint4 countbits(uint4); - -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int64_t countbits(int64_t); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int64_t2 countbits(int64_t2); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int64_t3 countbits(int64_t3); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int64_t4 countbits(int64_t4); - -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -uint64_t countbits(uint64_t); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -uint64_t2 countbits(uint64_t2); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -uint64_t3 countbits(uint64_t3); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -uint64_t4 countbits(uint64_t4); +constexpr uint countbits(int x) { + return __builtin_elementwise_popcount(x); +} +constexpr uint2 countbits(int2 x) { + return __builtin_elementwise_popcount(x); +} +constexpr uint3 countbits(int3 x) { + return __builtin_elementwise_popcount(x); +} +constexpr uint4 countbits(int4 x) { + return __builtin_elementwise_popcount(x); +} + +constexpr uint countbits(uint x) { + return __builtin_elementwise_popcount(x); +} +constexpr uint2 countbits(uint2 x) { + return __builtin_elementwise_popcount(x); +} +constexpr uint3 countbits(uint3 x) { + return __builtin_elementwise_popcount(x); +} +constexpr uint4 countbits(uint4 x) { + return __builtin_elementwise_popcount(x); +} + +constexpr uint countbits(int64_t x) { + return __builtin_elementwise_popcount(x); +} +constexpr uint2 countbits(int64_t2 x) { + return __builtin_elementwise_popcount(x); +} +constexpr uint3 countbits(int64_t3 x) { + return __builtin_elementwise_popcount(x); +} +constexpr uint4 countbits(int64_t4 x) { + return
[clang] [llvm] [HLSL] implement elementwise firstbithigh hlsl builtin (PR #111082)
@@ -0,0 +1,107 @@ +; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %} + +; CHECK: OpMemoryModel Logical GLSL450 + +define noundef i32 @firstbituhigh_i32(i32 noundef %a) { spall wrote: Yes I saw I am working on fixing it. https://github.com/llvm/llvm-project/pull/111082 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Re-implement countbits with the correct return type (PR #113189)
https://github.com/spall closed https://github.com/llvm/llvm-project/pull/113189 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] implement elementwise firstbithigh hlsl builtin (PR #111082)
spall wrote: Waiting on #114482 https://github.com/llvm/llvm-project/pull/111082 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] implement elementwise firstbithigh hlsl builtin (PR #111082)
https://github.com/spall edited https://github.com/llvm/llvm-project/pull/111082 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] implement elementwise firstbithigh hlsl builtin (PR #111082)
@@ -449,6 +449,15 @@ Register SPIRVGlobalRegistry::getOrCreateCompositeOrNull( return Res; } +Register SPIRVGlobalRegistry::getOrCreateConstScalarOrVector( +uint64_t Val, MachineInstr &I, SPIRVType *SpvType, +const SPIRVInstrInfo &TII, bool ZeroAsNull) { + if (SpvType->getOpcode() == SPIRV::OpTypeVector) +return getOrCreateConstVector(Val, I, SpvType, TII, ZeroAsNull); + else +return getOrCreateConstInt(Val, I, SpvType, TII, ZeroAsNull); spall wrote: No, because the Val is a uint64_t so its assumed to be an int. Following how 'getOrCreateConstVectr' is written, someone would write an overload of this that takes a float if they wanted it for floats. https://github.com/llvm/llvm-project/pull/111082 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [HLSL] get inout/out ABI for array parameters working (PR #111047)
https://github.com/spall updated https://github.com/llvm/llvm-project/pull/111047 >From 0797f19cad4ca9cf605725de1ac838cccacda1fc Mon Sep 17 00:00:00 2001 From: Sarah Spall Date: Tue, 17 Sep 2024 20:25:46 + Subject: [PATCH 1/6] theoretically fix issue --- clang/lib/Sema/SemaType.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 5d043e6684573c..a7fc7b692f5db3 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -5675,6 +5675,9 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, assert(!T.isNull() && "T must not be null at the end of this function"); if (!AreDeclaratorChunksValid) return Context.getTrivialTypeSourceInfo(T); + + if (state.didParseHLSLParamMod() && !T->isConstantArrayType()) +T = S.HLSL().getInoutParameterType(T); return GetTypeSourceInfoForDeclarator(state, T, TInfo); } @@ -8562,7 +8565,6 @@ static void HandleHLSLParamModifierAttr(TypeProcessingState &State, return; if (Attr.getSemanticSpelling() == HLSLParamModifierAttr::Keyword_inout || Attr.getSemanticSpelling() == HLSLParamModifierAttr::Keyword_out) { -CurType = S.HLSL().getInoutParameterType(CurType); State.setParsedHLSLParamMod(true); } } >From 7f9c7e0c249771c4e6fc7b09e2788f1000cb31b0 Mon Sep 17 00:00:00 2001 From: Sarah Spall Date: Wed, 2 Oct 2024 21:34:02 + Subject: [PATCH 2/6] get inout working --- clang/include/clang/AST/ASTContext.h | 4 +++ clang/lib/AST/ASTContext.cpp | 10 +++ clang/lib/CodeGen/CGCall.cpp | 3 +- clang/lib/CodeGen/CGExpr.cpp | 7 +++-- clang/lib/Sema/SemaExprCXX.cpp | 13 +++-- clang/lib/Sema/SemaOverload.cpp | 43 6 files changed, 55 insertions(+), 25 deletions(-) diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index a4d36f2eacd5d1..bdd4d86c30d389 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -1471,6 +1471,10 @@ class ASTContext : public RefCountedBase { /// type to the decayed type. QualType getDecayedType(QualType Orig, QualType Decayed) const; + /// Return the uniqued reference to a constant array type from the + /// original array parameter type. + QualType getConstantArrayFromArrayParameterType(QualType Ty) const; + /// Return the uniqued reference to a specified array parameter type from the /// original array type. QualType getArrayParameterType(QualType Ty) const; diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 69892bda42b256..8a21d8c5eec779 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -3839,6 +3839,16 @@ QualType ASTContext::getDecayedType(QualType T) const { return getDecayedType(T, Decayed); } +QualType ASTContext::getConstantArrayFromArrayParameterType(QualType Ty) const { + if (Ty->isConstantArrayType() && !Ty->isArrayParameterType()) +return Ty; + assert(Ty->isArrayParameterType() && "Ty must be an array parameter type."); + const auto *ATy = cast(Ty); + return getConstantArrayType(ATy->getElementType(), ATy->getSize(), + ATy->getSizeExpr(), ATy->getSizeModifier(), + ATy->getIndexTypeQualifiers().getAsOpaqueValue()); +} + QualType ASTContext::getArrayParameterType(QualType Ty) const { if (Ty->isArrayParameterType()) return Ty; diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 8f4f5d3ed81601..0206d2c1360d47 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -4726,7 +4726,8 @@ void CodeGenFunction::EmitCallArg(CallArgList &args, const Expr *E, return emitWritebackArg(*this, args, CRE); } - assert(type->isReferenceType() == E->isGLValue() && + assert(type->isArrayParameterType() || +(type->isReferenceType() == E->isGLValue()) && "reference binding to unmaterialized r-value!"); // Add writeback for HLSLOutParamExpr. diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index e90e8da3e9f1ea..a2a4c8d819581e 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -5821,9 +5821,12 @@ LValue CodeGenFunction::EmitBinaryOperatorLValue(const BinaryOperator *E) { // This function implements trivial copy assignment for HLSL's // assignable constant arrays. LValue CodeGenFunction::EmitHLSLArrayAssignLValue(const BinaryOperator *E) { - LValue TrivialAssignmentRHS = EmitLValue(E->getRHS()); + // Don't emit an LValue for the RHS because it might not be an LValue LValue LHS = EmitLValue(E->getLHS()); - EmitAggregateAssign(LHS, TrivialAssignmentRHS, E->getLHS()->getType()); + // In C assignment operator RHS is often an RValue. + // EmitAggregateAssign expects an LValue for the RHS so call the below + // function instead. + EmitInitiali
[clang] [llvm] [HLSL] implement elementwise firstbithigh hlsl builtin (PR #111082)
@@ -37,13 +39,12 @@ define noundef i32 @firstbituhigh_i64(i64 noundef %a) { entry: ; CHECK: [[O:%.*]] = OpBitcast %[[#]] %[[#]] ; CHECK: [[N:%.*]] = OpExtInst %[[#]] %[[#]] FindUMsb [[O]] -; CHECK: [[M:%.*]] = OpVectorShuffle %[[#]] [[N]] [[N]] 0 -; CHECK: [[L:%.*]] = OpVectorShuffle %[[#]] [[N]] [[N]] 1 +; CHECK: [[M:%.*]] = OpVectorExtractDynamic %[[#]] [[N]] [[Z]] +; CHECK: [[L:%.*]] = OpVectorExtractDynamic %[[#]] [[N]] [[X]] spall wrote: OpVectorShuffle requires the result type to be a vector. In the case we have a scalar i64, that would result in a vector of length 1 which is not supported in SPIRV. So, instead in the scalar case we do a OpVectorExtractDynamic. https://github.com/llvm/llvm-project/pull/111082 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] implement elementwise firstbithigh hlsl builtin (PR #111082)
@@ -2717,82 +2717,82 @@ bool SPIRVInstructionSelector::selectFirstBitHigh64(Register ResVReg, Register FBHReg = MRI->createVirtualRegister(GR.getRegClass(postCastT)); Result &= selectFirstBitHigh32(FBHReg, postCastT, I, bitcastReg, IsSigned); - // 3. check if result of each top 32 bits is == -1 - // split result vector into vector of high bits and vector of low bits - // get high bits - // if ResType is a scalar we need a vector anyways because our code - // operates on vectors, even vectors of length one. - SPIRVType *VResType = ResType; + // 3. split result vector into high bits and low bits + Register HighReg = MRI->createVirtualRegister(GR.getRegClass(ResType)); + Register LowReg = MRI->createVirtualRegister(GR.getRegClass(ResType)); + + bool ZeroAsNull = STI.isOpenCLEnv(); bool isScalarRes = ResType->getOpcode() != SPIRV::OpTypeVector; - if (isScalarRes) -VResType = GR.getOrCreateSPIRVVectorType(ResType, count, MIRBuilder); - // count should be one. + if (isScalarRes) { +// if scalar do a vector extract +Result &= selectNAryOpWithSrcs( +HighReg, ResType, I, +{FBHReg, GR.getOrCreateConstInt(0, I, ResType, TII, ZeroAsNull)}, +SPIRV::OpVectorExtractDynamic); +Result &= selectNAryOpWithSrcs( +LowReg, ResType, I, +{FBHReg, GR.getOrCreateConstInt(1, I, ResType, TII, ZeroAsNull)}, +SPIRV::OpVectorExtractDynamic); + } else { // vector case do a shufflevector +auto MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), + TII.get(SPIRV::OpVectorShuffle)) + .addDef(HighReg) + .addUse(GR.getSPIRVTypeID(ResType)) + .addUse(FBHReg) + .addUse(FBHReg); +// ^^ this vector will not be selected from; could be empty +unsigned j; +for (j = 0; j < count * 2; j += 2) { + MIB.addImm(j); +} +Result &= MIB.constrainAllUses(TII, TRI, RBI); + +// get low bits +MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), + TII.get(SPIRV::OpVectorShuffle)) + .addDef(LowReg) + .addUse(GR.getSPIRVTypeID(ResType)) + .addUse(FBHReg) + .addUse(FBHReg); +// ^^ this vector will not be selected from; could be empty +for (j = 1; j < count * 2; j += 2) { + MIB.addImm(j); +} +Result &= MIB.constrainAllUses(TII, TRI, RBI); + } + + // 4. check if result of each top 32 bits is == -1 + SPIRVType *BoolType = GR.getOrCreateSPIRVBoolType(I, TII); + if (!isScalarRes) +BoolType = GR.getOrCreateSPIRVVectorType(BoolType, count, MIRBuilder); - Register HighReg = MRI->createVirtualRegister(GR.getRegClass(VResType)); - auto MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), - TII.get(SPIRV::OpVectorShuffle)) - .addDef(HighReg) - .addUse(GR.getSPIRVTypeID(VResType)) - .addUse(FBHReg) - .addUse(FBHReg); - // ^^ this vector will not be selected from; could be empty - unsigned j; - for (j = 0; j < count * 2; j += 2) { -MIB.addImm(j); - } - Result &= MIB.constrainAllUses(TII, TRI, RBI); - - // get low bits - Register LowReg = MRI->createVirtualRegister(GR.getRegClass(VResType)); - MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), -TII.get(SPIRV::OpVectorShuffle)) -.addDef(LowReg) -.addUse(GR.getSPIRVTypeID(VResType)) -.addUse(FBHReg) -.addUse(FBHReg); - // ^^ this vector will not be selected from; could be empty - for (j = 1; j < count * 2; j += 2) { -MIB.addImm(j); - } - Result &= MIB.constrainAllUses(TII, TRI, RBI); - - SPIRVType *BoolType = GR.getOrCreateSPIRVVectorType( - GR.getOrCreateSPIRVBoolType(I, TII), count, MIRBuilder); // check if the high bits are == -1; - Register NegOneReg = GR.getOrCreateConstVector(-1, I, VResType, TII); + Register NegOneReg = + GR.getOrCreateConstScalarOrVector(-1, I, ResType, TII, ZeroAsNull); spall wrote: Sure If I do that I can probably delete the helper function I added in SPIRVGlobalRegistry. I thought this style would be less ugly than a big block. https://github.com/llvm/llvm-project/pull/111082 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [HLSL] get inout/out ABI for array parameters working (PR #111047)
https://github.com/spall updated https://github.com/llvm/llvm-project/pull/111047 >From 0797f19cad4ca9cf605725de1ac838cccacda1fc Mon Sep 17 00:00:00 2001 From: Sarah Spall Date: Tue, 17 Sep 2024 20:25:46 + Subject: [PATCH 1/6] theoretically fix issue --- clang/lib/Sema/SemaType.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 5d043e6684573c..a7fc7b692f5db3 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -5675,6 +5675,9 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, assert(!T.isNull() && "T must not be null at the end of this function"); if (!AreDeclaratorChunksValid) return Context.getTrivialTypeSourceInfo(T); + + if (state.didParseHLSLParamMod() && !T->isConstantArrayType()) +T = S.HLSL().getInoutParameterType(T); return GetTypeSourceInfoForDeclarator(state, T, TInfo); } @@ -8562,7 +8565,6 @@ static void HandleHLSLParamModifierAttr(TypeProcessingState &State, return; if (Attr.getSemanticSpelling() == HLSLParamModifierAttr::Keyword_inout || Attr.getSemanticSpelling() == HLSLParamModifierAttr::Keyword_out) { -CurType = S.HLSL().getInoutParameterType(CurType); State.setParsedHLSLParamMod(true); } } >From 7f9c7e0c249771c4e6fc7b09e2788f1000cb31b0 Mon Sep 17 00:00:00 2001 From: Sarah Spall Date: Wed, 2 Oct 2024 21:34:02 + Subject: [PATCH 2/6] get inout working --- clang/include/clang/AST/ASTContext.h | 4 +++ clang/lib/AST/ASTContext.cpp | 10 +++ clang/lib/CodeGen/CGCall.cpp | 3 +- clang/lib/CodeGen/CGExpr.cpp | 7 +++-- clang/lib/Sema/SemaExprCXX.cpp | 13 +++-- clang/lib/Sema/SemaOverload.cpp | 43 6 files changed, 55 insertions(+), 25 deletions(-) diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index a4d36f2eacd5d1..bdd4d86c30d389 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -1471,6 +1471,10 @@ class ASTContext : public RefCountedBase { /// type to the decayed type. QualType getDecayedType(QualType Orig, QualType Decayed) const; + /// Return the uniqued reference to a constant array type from the + /// original array parameter type. + QualType getConstantArrayFromArrayParameterType(QualType Ty) const; + /// Return the uniqued reference to a specified array parameter type from the /// original array type. QualType getArrayParameterType(QualType Ty) const; diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 69892bda42b256..8a21d8c5eec779 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -3839,6 +3839,16 @@ QualType ASTContext::getDecayedType(QualType T) const { return getDecayedType(T, Decayed); } +QualType ASTContext::getConstantArrayFromArrayParameterType(QualType Ty) const { + if (Ty->isConstantArrayType() && !Ty->isArrayParameterType()) +return Ty; + assert(Ty->isArrayParameterType() && "Ty must be an array parameter type."); + const auto *ATy = cast(Ty); + return getConstantArrayType(ATy->getElementType(), ATy->getSize(), + ATy->getSizeExpr(), ATy->getSizeModifier(), + ATy->getIndexTypeQualifiers().getAsOpaqueValue()); +} + QualType ASTContext::getArrayParameterType(QualType Ty) const { if (Ty->isArrayParameterType()) return Ty; diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 8f4f5d3ed81601..0206d2c1360d47 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -4726,7 +4726,8 @@ void CodeGenFunction::EmitCallArg(CallArgList &args, const Expr *E, return emitWritebackArg(*this, args, CRE); } - assert(type->isReferenceType() == E->isGLValue() && + assert(type->isArrayParameterType() || +(type->isReferenceType() == E->isGLValue()) && "reference binding to unmaterialized r-value!"); // Add writeback for HLSLOutParamExpr. diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index e90e8da3e9f1ea..a2a4c8d819581e 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -5821,9 +5821,12 @@ LValue CodeGenFunction::EmitBinaryOperatorLValue(const BinaryOperator *E) { // This function implements trivial copy assignment for HLSL's // assignable constant arrays. LValue CodeGenFunction::EmitHLSLArrayAssignLValue(const BinaryOperator *E) { - LValue TrivialAssignmentRHS = EmitLValue(E->getRHS()); + // Don't emit an LValue for the RHS because it might not be an LValue LValue LHS = EmitLValue(E->getLHS()); - EmitAggregateAssign(LHS, TrivialAssignmentRHS, E->getLHS()->getType()); + // In C assignment operator RHS is often an RValue. + // EmitAggregateAssign expects an LValue for the RHS so call the below + // function instead. + EmitInitiali
[clang] [llvm] [HLSL][SPIRV][DXIL] Implement `WaveActiveSum` intrinsic (PR #112400)
@@ -85,6 +85,8 @@ def int_dx_umad : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLV def int_dx_normalize : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty], [IntrNoMem]>; def int_dx_rsqrt : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]>; def int_dx_wave_getlaneindex : DefaultAttrsIntrinsic<[llvm_i32_ty], [], [IntrConvergent, IntrNoMem]>; +def int_dx_wave_active_sum : DefaultAttrsIntrinsic<[llvm_any_ty], [LLVMMatchType<0>], [IntrConvergent, IntrNoMem]>; spall wrote: I think it would be good for consistency reasons to rename this to int_dx_wave_active_ssum https://github.com/llvm/llvm-project/pull/112400 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL][SPIRV][DXIL] Implement `WaveActiveSum` intrinsic (PR #112400)
https://github.com/spall deleted https://github.com/llvm/llvm-project/pull/112400 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL][SPIRV][DXIL] Implement `WaveActiveSum` intrinsic (PR #112400)
@@ -85,6 +85,8 @@ def int_dx_umad : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLV def int_dx_normalize : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty], [IntrNoMem]>; def int_dx_rsqrt : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]>; def int_dx_wave_getlaneindex : DefaultAttrsIntrinsic<[llvm_i32_ty], [], [IntrConvergent, IntrNoMem]>; +def int_dx_wave_active_sum : DefaultAttrsIntrinsic<[llvm_any_ty], [LLVMMatchType<0>], [IntrConvergent, IntrNoMem]>; spall wrote: Is there a difference between float and signed? https://github.com/llvm/llvm-project/pull/112400 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Re-implement countbits with the correct return type (PR #113189)
@@ -461,6 +461,67 @@ class OpLowerer { }); } + [[nodiscard]] bool lowerCtpopToCBits(Function &F) { +IRBuilder<> &IRB = OpBuilder.getIRB(); +Type *Int32Ty = IRB.getInt32Ty(); + +return replaceFunction(F, [&](CallInst *CI) -> Error { + IRB.SetInsertPoint(CI); + SmallVector Args; + Args.append(CI->arg_begin(), CI->arg_end()); + + Type *RetTy = Int32Ty; + Type *FRT = F.getReturnType(); + if (FRT->isVectorTy()) { +VectorType *VT = cast(FRT); +RetTy = VectorType::get(RetTy, VT); + } + + Expected OpCall = OpBuilder.tryCreateOp( + dxil::OpCode::CBits, Args, CI->getName(), RetTy); + if (Error E = OpCall.takeError()) +return E; + + // If the result type is 32 bits we can do a direct replacement. + if (FRT->isIntOrIntVectorTy(32)) { +CI->replaceAllUsesWith(*OpCall); +CI->eraseFromParent(); +return Error::success(); + } + + unsigned CastOp; + if (FRT->isIntOrIntVectorTy(16)) +CastOp = Instruction::ZExt; + else // must be 64 bits +CastOp = Instruction::Trunc; + + // It is correct to replace the ctpop with the dxil op and + // remove an existing cast iff the cast is the only usage of + // the ctpop spall wrote: I actually re-wrote this to be much less conservative. https://github.com/llvm/llvm-project/pull/113189 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [HLSL] get inout/out ABI for array parameters working (PR #111047)
https://github.com/spall updated https://github.com/llvm/llvm-project/pull/111047 >From 119def060924f13bd1fe07f6d73ce27a1b52ea12 Mon Sep 17 00:00:00 2001 From: Sarah Spall Date: Tue, 17 Sep 2024 20:25:46 + Subject: [PATCH 1/7] theoretically fix issue --- clang/lib/Sema/SemaType.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index e526a11973975d..4874a4902a5cc6 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -5675,6 +5675,9 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, assert(!T.isNull() && "T must not be null at the end of this function"); if (!AreDeclaratorChunksValid) return Context.getTrivialTypeSourceInfo(T); + + if (state.didParseHLSLParamMod() && !T->isConstantArrayType()) +T = S.HLSL().getInoutParameterType(T); return GetTypeSourceInfoForDeclarator(state, T, TInfo); } @@ -8616,7 +8619,6 @@ static void HandleHLSLParamModifierAttr(TypeProcessingState &State, return; if (Attr.getSemanticSpelling() == HLSLParamModifierAttr::Keyword_inout || Attr.getSemanticSpelling() == HLSLParamModifierAttr::Keyword_out) { -CurType = S.HLSL().getInoutParameterType(CurType); State.setParsedHLSLParamMod(true); } } >From 3231a7b7327b6550291dfbeeec5a1907a7473e7f Mon Sep 17 00:00:00 2001 From: Sarah Spall Date: Wed, 2 Oct 2024 21:34:02 + Subject: [PATCH 2/7] get inout working --- clang/include/clang/AST/ASTContext.h | 4 +++ clang/lib/AST/ASTContext.cpp | 10 +++ clang/lib/CodeGen/CGCall.cpp | 3 +- clang/lib/CodeGen/CGExpr.cpp | 7 +++-- clang/lib/Sema/SemaExprCXX.cpp | 13 +++-- clang/lib/Sema/SemaOverload.cpp | 43 6 files changed, 55 insertions(+), 25 deletions(-) diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 89fcb6789d880a..e9bacf8d7391c4 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -1480,6 +1480,10 @@ class ASTContext : public RefCountedBase { /// type to the decayed type. QualType getDecayedType(QualType Orig, QualType Decayed) const; + /// Return the uniqued reference to a constant array type from the + /// original array parameter type. + QualType getConstantArrayFromArrayParameterType(QualType Ty) const; + /// Return the uniqued reference to a specified array parameter type from the /// original array type. QualType getArrayParameterType(QualType Ty) const; diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 09d159e5c3efd6..202d17d3999658 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -3852,6 +3852,16 @@ QualType ASTContext::getDecayedType(QualType T) const { return getDecayedType(T, Decayed); } +QualType ASTContext::getConstantArrayFromArrayParameterType(QualType Ty) const { + if (Ty->isConstantArrayType() && !Ty->isArrayParameterType()) +return Ty; + assert(Ty->isArrayParameterType() && "Ty must be an array parameter type."); + const auto *ATy = cast(Ty); + return getConstantArrayType(ATy->getElementType(), ATy->getSize(), + ATy->getSizeExpr(), ATy->getSizeModifier(), + ATy->getIndexTypeQualifiers().getAsOpaqueValue()); +} + QualType ASTContext::getArrayParameterType(QualType Ty) const { if (Ty->isArrayParameterType()) return Ty; diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 8f4f5d3ed81601..0206d2c1360d47 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -4726,7 +4726,8 @@ void CodeGenFunction::EmitCallArg(CallArgList &args, const Expr *E, return emitWritebackArg(*this, args, CRE); } - assert(type->isReferenceType() == E->isGLValue() && + assert(type->isArrayParameterType() || +(type->isReferenceType() == E->isGLValue()) && "reference binding to unmaterialized r-value!"); // Add writeback for HLSLOutParamExpr. diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 096f4c4f550435..fcab838be40f2b 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -5830,9 +5830,12 @@ LValue CodeGenFunction::EmitBinaryOperatorLValue(const BinaryOperator *E) { // This function implements trivial copy assignment for HLSL's // assignable constant arrays. LValue CodeGenFunction::EmitHLSLArrayAssignLValue(const BinaryOperator *E) { - LValue TrivialAssignmentRHS = EmitLValue(E->getRHS()); + // Don't emit an LValue for the RHS because it might not be an LValue LValue LHS = EmitLValue(E->getLHS()); - EmitAggregateAssign(LHS, TrivialAssignmentRHS, E->getLHS()->getType()); + // In C assignment operator RHS is often an RValue. + // EmitAggregateAssign expects an LValue for the RHS so call the below + // function instead. + EmitInitiali
[clang] [llvm] [HLSL] implement elementwise firstbithigh hlsl builtin (PR #111082)
https://github.com/spall updated https://github.com/llvm/llvm-project/pull/111082 >From 6239941c302f616f87ed652151e828a8eae1054c Mon Sep 17 00:00:00 2001 From: Sarah Spall Date: Mon, 23 Sep 2024 22:10:59 + Subject: [PATCH 1/7] implement firstbithigh hlsl builtin --- clang/include/clang/Basic/Builtins.td | 6 + clang/lib/CodeGen/CGBuiltin.cpp | 17 ++ clang/lib/CodeGen/CGHLSLRuntime.h | 2 + clang/lib/Headers/hlsl/hlsl_intrinsics.h | 72 + clang/lib/Sema/SemaHLSL.cpp | 18 +++ .../CodeGenHLSL/builtins/firstbithigh.hlsl| 153 ++ .../BuiltIns/firstbithigh-errors.hlsl | 28 llvm/include/llvm/IR/IntrinsicsDirectX.td | 2 + llvm/include/llvm/IR/IntrinsicsSPIRV.td | 2 + llvm/lib/Target/DirectX/DXIL.td | 24 +++ .../DirectX/DirectXTargetTransformInfo.cpp| 2 + .../Target/SPIRV/SPIRVInstructionSelector.cpp | 14 ++ llvm/test/CodeGen/DirectX/firstbithigh.ll | 91 +++ .../CodeGen/DirectX/firstbitshigh_error.ll| 10 ++ .../CodeGen/DirectX/firstbituhigh_error.ll| 10 ++ .../SPIRV/hlsl-intrinsics/firstbithigh.ll | 37 + 16 files changed, 488 insertions(+) create mode 100644 clang/test/CodeGenHLSL/builtins/firstbithigh.hlsl create mode 100644 clang/test/SemaHLSL/BuiltIns/firstbithigh-errors.hlsl create mode 100644 llvm/test/CodeGen/DirectX/firstbithigh.ll create mode 100644 llvm/test/CodeGen/DirectX/firstbitshigh_error.ll create mode 100644 llvm/test/CodeGen/DirectX/firstbituhigh_error.ll create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/firstbithigh.ll diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 90475a361bb8f8..d294f680bb244d 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -4792,6 +4792,12 @@ def HLSLDotProduct : LangBuiltin<"HLSL_LANG"> { let Prototype = "void(...)"; } +def HLSLFirstBitHigh : LangBuiltin<"HLSL_LANG"> { + let Spellings = ["__builtin_hlsl_elementwise_firstbithigh"]; + let Attributes = [NoThrow, Const]; + let Prototype = "void(...)"; +} + def HLSLFrac : LangBuiltin<"HLSL_LANG"> { let Spellings = ["__builtin_hlsl_elementwise_frac"]; let Attributes = [NoThrow, Const]; diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 3f28b7f26c36fe..51fc0245fd5517 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -18641,6 +18641,14 @@ static Intrinsic::ID getDotProductIntrinsic(CGHLSLRuntime &RT, QualType QT) { return RT.getUDotIntrinsic(); } +Intrinsic::ID getFirstBitHighIntrinsic(CGHLSLRuntime &RT, QualType QT) { + if (QT->hasSignedIntegerRepresentation()) { +return RT.getFirstBitSHighIntrinsic(); + } + + return RT.getFirstBitUHighIntrinsic(); +} + Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, const CallExpr *E, ReturnValueSlot ReturnValue) { @@ -18730,6 +18738,15 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, getDotProductIntrinsic(CGM.getHLSLRuntime(), VecTy0->getElementType()), ArrayRef{Op0, Op1}, nullptr, "hlsl.dot"); } break; + case Builtin::BI__builtin_hlsl_elementwise_firstbithigh: { + +Value *X = EmitScalarExpr(E->getArg(0)); + +return Builder.CreateIntrinsic( + /*ReturnType=*/X->getType(), + getFirstBitHighIntrinsic(CGM.getHLSLRuntime(), E->getArg(0)->getType()), + ArrayRef{X}, nullptr, "hlsl.firstbithigh"); + } case Builtin::BI__builtin_hlsl_lerp: { Value *X = EmitScalarExpr(E->getArg(0)); Value *Y = EmitScalarExpr(E->getArg(1)); diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h index ff7df41b5c62e7..4e37123e3f110a 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.h +++ b/clang/lib/CodeGen/CGHLSLRuntime.h @@ -91,6 +91,8 @@ class CGHLSLRuntime { GENERATE_HLSL_INTRINSIC_FUNCTION(UDot, udot) GENERATE_HLSL_INTRINSIC_FUNCTION(WaveIsFirstLane, wave_is_first_lane) GENERATE_HLSL_INTRINSIC_FUNCTION(WaveReadLaneAt, wave_readlane) + GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitUHigh, firstbituhigh) + GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitSHigh, firstbitshigh) GENERATE_HLSL_INTRINSIC_FUNCTION(CreateHandleFromBinding, handle_fromBinding) diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index 30dce60b3ff702..4b3a4f50ceb981 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -958,6 +958,78 @@ float3 exp2(float3); _HLSL_BUILTIN_ALIAS(__builtin_elementwise_exp2) float4 exp2(float4); +//===--===// +// firstbithigh builtins +//===--===// + +/// \fn T firs
[clang] [llvm] [HLSL] implement elementwise firstbithigh hlsl builtin (PR #111082)
https://github.com/spall updated https://github.com/llvm/llvm-project/pull/111082 >From 6239941c302f616f87ed652151e828a8eae1054c Mon Sep 17 00:00:00 2001 From: Sarah Spall Date: Mon, 23 Sep 2024 22:10:59 + Subject: [PATCH 1/8] implement firstbithigh hlsl builtin --- clang/include/clang/Basic/Builtins.td | 6 + clang/lib/CodeGen/CGBuiltin.cpp | 17 ++ clang/lib/CodeGen/CGHLSLRuntime.h | 2 + clang/lib/Headers/hlsl/hlsl_intrinsics.h | 72 + clang/lib/Sema/SemaHLSL.cpp | 18 +++ .../CodeGenHLSL/builtins/firstbithigh.hlsl| 153 ++ .../BuiltIns/firstbithigh-errors.hlsl | 28 llvm/include/llvm/IR/IntrinsicsDirectX.td | 2 + llvm/include/llvm/IR/IntrinsicsSPIRV.td | 2 + llvm/lib/Target/DirectX/DXIL.td | 24 +++ .../DirectX/DirectXTargetTransformInfo.cpp| 2 + .../Target/SPIRV/SPIRVInstructionSelector.cpp | 14 ++ llvm/test/CodeGen/DirectX/firstbithigh.ll | 91 +++ .../CodeGen/DirectX/firstbitshigh_error.ll| 10 ++ .../CodeGen/DirectX/firstbituhigh_error.ll| 10 ++ .../SPIRV/hlsl-intrinsics/firstbithigh.ll | 37 + 16 files changed, 488 insertions(+) create mode 100644 clang/test/CodeGenHLSL/builtins/firstbithigh.hlsl create mode 100644 clang/test/SemaHLSL/BuiltIns/firstbithigh-errors.hlsl create mode 100644 llvm/test/CodeGen/DirectX/firstbithigh.ll create mode 100644 llvm/test/CodeGen/DirectX/firstbitshigh_error.ll create mode 100644 llvm/test/CodeGen/DirectX/firstbituhigh_error.ll create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/firstbithigh.ll diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 90475a361bb8f8..d294f680bb244d 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -4792,6 +4792,12 @@ def HLSLDotProduct : LangBuiltin<"HLSL_LANG"> { let Prototype = "void(...)"; } +def HLSLFirstBitHigh : LangBuiltin<"HLSL_LANG"> { + let Spellings = ["__builtin_hlsl_elementwise_firstbithigh"]; + let Attributes = [NoThrow, Const]; + let Prototype = "void(...)"; +} + def HLSLFrac : LangBuiltin<"HLSL_LANG"> { let Spellings = ["__builtin_hlsl_elementwise_frac"]; let Attributes = [NoThrow, Const]; diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 3f28b7f26c36fe..51fc0245fd5517 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -18641,6 +18641,14 @@ static Intrinsic::ID getDotProductIntrinsic(CGHLSLRuntime &RT, QualType QT) { return RT.getUDotIntrinsic(); } +Intrinsic::ID getFirstBitHighIntrinsic(CGHLSLRuntime &RT, QualType QT) { + if (QT->hasSignedIntegerRepresentation()) { +return RT.getFirstBitSHighIntrinsic(); + } + + return RT.getFirstBitUHighIntrinsic(); +} + Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, const CallExpr *E, ReturnValueSlot ReturnValue) { @@ -18730,6 +18738,15 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, getDotProductIntrinsic(CGM.getHLSLRuntime(), VecTy0->getElementType()), ArrayRef{Op0, Op1}, nullptr, "hlsl.dot"); } break; + case Builtin::BI__builtin_hlsl_elementwise_firstbithigh: { + +Value *X = EmitScalarExpr(E->getArg(0)); + +return Builder.CreateIntrinsic( + /*ReturnType=*/X->getType(), + getFirstBitHighIntrinsic(CGM.getHLSLRuntime(), E->getArg(0)->getType()), + ArrayRef{X}, nullptr, "hlsl.firstbithigh"); + } case Builtin::BI__builtin_hlsl_lerp: { Value *X = EmitScalarExpr(E->getArg(0)); Value *Y = EmitScalarExpr(E->getArg(1)); diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h index ff7df41b5c62e7..4e37123e3f110a 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.h +++ b/clang/lib/CodeGen/CGHLSLRuntime.h @@ -91,6 +91,8 @@ class CGHLSLRuntime { GENERATE_HLSL_INTRINSIC_FUNCTION(UDot, udot) GENERATE_HLSL_INTRINSIC_FUNCTION(WaveIsFirstLane, wave_is_first_lane) GENERATE_HLSL_INTRINSIC_FUNCTION(WaveReadLaneAt, wave_readlane) + GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitUHigh, firstbituhigh) + GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitSHigh, firstbitshigh) GENERATE_HLSL_INTRINSIC_FUNCTION(CreateHandleFromBinding, handle_fromBinding) diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index 30dce60b3ff702..4b3a4f50ceb981 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -958,6 +958,78 @@ float3 exp2(float3); _HLSL_BUILTIN_ALIAS(__builtin_elementwise_exp2) float4 exp2(float4); +//===--===// +// firstbithigh builtins +//===--===// + +/// \fn T firs
[clang] [llvm] [HLSL] implement elementwise firstbithigh hlsl builtin (PR #111082)
@@ -424,7 +424,7 @@ Register SPIRVGlobalRegistry::getOrCreateCompositeOrNull( LLT LLTy = LLT::scalar(64); Register SpvVecConst = CurMF->getRegInfo().createGenericVirtualRegister(LLTy); -CurMF->getRegInfo().setRegClass(SpvVecConst, &SPIRV::iIDRegClass); +CurMF->getRegInfo().setRegClass(SpvVecConst, getRegClass(SpvType)); spall wrote: I created issue #113486 and mentioned it in this PR. https://github.com/llvm/llvm-project/pull/111082 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] implement elementwise firstbithigh hlsl builtin (PR #111082)
@@ -2626,6 +2671,148 @@ Register SPIRVInstructionSelector::buildPointerToResource( MIRBuilder); } +bool SPIRVInstructionSelector::selectFirstBitHigh16(Register ResVReg, +const SPIRVType *ResType, +MachineInstr &I, +bool IsSigned) const { + unsigned Opcode = IsSigned ? SPIRV::OpSConvert : SPIRV::OpUConvert; + // zero or sign extend + Register ExtReg = MRI->createVirtualRegister(GR.getRegClass(ResType)); + bool Result = + selectUnOpWithSrc(ExtReg, ResType, I, I.getOperand(2).getReg(), Opcode); + return Result & selectFirstBitHigh32(ResVReg, ResType, I, ExtReg, IsSigned); +} + +bool SPIRVInstructionSelector::selectFirstBitHigh32(Register ResVReg, +const SPIRVType *ResType, +MachineInstr &I, +Register SrcReg, +bool IsSigned) const { + unsigned Opcode = IsSigned ? GL::FindSMsb : GL::FindUMsb; + return BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRV::OpExtInst)) + .addDef(ResVReg) + .addUse(GR.getSPIRVTypeID(ResType)) + .addImm(static_cast(SPIRV::InstructionSet::GLSL_std_450)) + .addImm(Opcode) + .addUse(SrcReg) + .constrainAllUses(TII, TRI, RBI); +} + +bool SPIRVInstructionSelector::selectFirstBitHigh64(Register ResVReg, +const SPIRVType *ResType, +MachineInstr &I, +bool IsSigned) const { + Register OpReg = I.getOperand(2).getReg(); + // 1. split our int64 into 2 pieces using a bitcast + unsigned count = GR.getScalarOrVectorComponentCount(ResType); + SPIRVType *baseType = GR.retrieveScalarOrVectorIntType(ResType); + MachineIRBuilder MIRBuilder(I); + SPIRVType *postCastT = + GR.getOrCreateSPIRVVectorType(baseType, 2 * count, MIRBuilder); + Register bitcastReg = MRI->createVirtualRegister(GR.getRegClass(postCastT)); + bool Result = + selectUnOpWithSrc(bitcastReg, postCastT, I, OpReg, SPIRV::OpBitcast); + + // 2. call firstbithigh + Register FBHReg = MRI->createVirtualRegister(GR.getRegClass(postCastT)); + Result &= selectFirstBitHigh32(FBHReg, postCastT, I, bitcastReg, IsSigned); + + // 3. check if result of each top 32 bits is == -1 + // split result vector into vector of high bits and vector of low bits + // get high bits + // if ResType is a scalar we need a vector anyways because our code + // operates on vectors, even vectors of length one. + SPIRVType *VResType = ResType; + bool isScalarRes = ResType->getOpcode() != SPIRV::OpTypeVector; + if (isScalarRes) +VResType = GR.getOrCreateSPIRVVectorType(ResType, count, MIRBuilder); + // count should be one. + + Register HighReg = MRI->createVirtualRegister(GR.getRegClass(VResType)); + auto MIB = + BuildMI(*I.getParent(), I, I.getDebugLoc(), + TII.get(SPIRV::OpVectorShuffle)) + .addDef(HighReg) + .addUse(GR.getSPIRVTypeID(VResType)) + .addUse(FBHReg) + .addUse( + FBHReg); // this vector will not be selected from; could be empty + unsigned i; + for (i = 0; i < count * 2; i += 2) { +MIB.addImm(i); + } spall wrote: It is actually re-used in the for-loop below this one. I will rename one of them. https://github.com/llvm/llvm-project/pull/111082 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] implement elementwise firstbithigh hlsl builtin (PR #111082)
https://github.com/spall edited https://github.com/llvm/llvm-project/pull/111082 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Re-implement countbits with the correct return type (PR #113189)
https://github.com/spall updated https://github.com/llvm/llvm-project/pull/113189 >From 12cac48dcc10ef9c5fccba2c22911f420298b98b Mon Sep 17 00:00:00 2001 From: Sarah Spall Date: Wed, 16 Oct 2024 19:00:08 + Subject: [PATCH 1/3] implement countbits correctly --- clang/lib/Headers/hlsl/hlsl_intrinsics.h | 126 +++--- .../test/CodeGenHLSL/builtins/countbits.hlsl | 42 +++--- .../SemaHLSL/BuiltIns/countbits-errors.hlsl | 14 +- llvm/lib/Target/DirectX/DXIL.td | 5 +- llvm/lib/Target/DirectX/DXILOpLowering.cpp| 64 + llvm/test/CodeGen/DirectX/countbits.ll| 39 -- 6 files changed, 202 insertions(+), 88 deletions(-) diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index 30dce60b3ff702..2a612c3746076c 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -705,66 +705,90 @@ float4 cosh(float4); #ifdef __HLSL_ENABLE_16_BIT _HLSL_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int16_t countbits(int16_t); +constexpr uint countbits(int16_t x) { + return __builtin_elementwise_popcount(x); +} _HLSL_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int16_t2 countbits(int16_t2); +constexpr uint2 countbits(int16_t2 x) { + return __builtin_elementwise_popcount(x); +} _HLSL_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int16_t3 countbits(int16_t3); +constexpr uint3 countbits(int16_t3 x) { + return __builtin_elementwise_popcount(x); +} _HLSL_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int16_t4 countbits(int16_t4); +constexpr uint4 countbits(int16_t4 x) { + return __builtin_elementwise_popcount(x); +} _HLSL_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -uint16_t countbits(uint16_t); +constexpr uint countbits(uint16_t x) { + return __builtin_elementwise_popcount(x); +} _HLSL_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -uint16_t2 countbits(uint16_t2); +constexpr uint2 countbits(uint16_t2 x) { + return __builtin_elementwise_popcount(x); +} _HLSL_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -uint16_t3 countbits(uint16_t3); +constexpr uint3 countbits(uint16_t3 x) { + return __builtin_elementwise_popcount(x); +} _HLSL_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -uint16_t4 countbits(uint16_t4); +constexpr uint4 countbits(uint16_t4 x) { + return __builtin_elementwise_popcount(x); +} #endif -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int countbits(int); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int2 countbits(int2); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int3 countbits(int3); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int4 countbits(int4); - -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -uint countbits(uint); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -uint2 countbits(uint2); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -uint3 countbits(uint3); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -uint4 countbits(uint4); - -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int64_t countbits(int64_t); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int64_t2 countbits(int64_t2); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int64_t3 countbits(int64_t3); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int64_t4 countbits(int64_t4); - -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -uint64_t countbits(uint64_t); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -uint64_t2 countbits(uint64_t2); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -uint64_t3 countbits(uint64_t3); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -uint64_t4 countbits(uint64_t4); +constexpr uint countbits(int x) { + return __builtin_elementwise_popcount(x); +} +constexpr uint2 countbits(int2 x) { + return __builtin_elementwise_popcount(x); +} +constexpr uint3 countbits(int3 x) { + return __builtin_elementwise_popcount(x); +} +constexpr uint4 countbits(int4 x) { + return __builtin_elementwise_popcount(x); +} + +constexpr uint countbits(uint x) { + return __builtin_elementwise_popcount(x); +} +constexpr uint2 countbits(uint2 x) { + return __builtin_elementwise_popcount(x); +} +constexpr uint3 countbits(uint3 x) { + return __builtin_elementwise_popcount(x); +} +constexpr uint4 countbits(uint4 x) { + return __builtin_elementwise_popcount(x); +} + +constexpr uint countbits(int64_t x) { + return __builtin_elementwise_popcount(x); +} +constexpr uint2 countbits(int64_t2 x) { + return __builtin_elementwise_popcount(x); +} +constexpr uint3 countbits(int64_t3 x) { + return __builtin_elementwise_popcount(x); +} +constexpr uint4 countbits(int64_t4 x) { + return
[clang] [HLSL] get inout/out ABI for array parameters working (PR #111047)
@@ -4690,8 +4690,9 @@ void CodeGenFunction::EmitCallArg(CallArgList &args, const Expr *E, return emitWritebackArg(*this, args, CRE); } - assert(type->isReferenceType() == E->isGLValue() && - "reference binding to unmaterialized r-value!"); + assert(type->isArrayParameterType() || + (type->isReferenceType() == E->isGLValue()) && + "reference binding to unmaterialized r-value!"); spall wrote: I think that its an LValue if its an HLSLArgOutExpr, so I did move the assert below. https://github.com/llvm/llvm-project/pull/111047 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [HLSL] Array by-value assignment (PR #109323)
@@ -0,0 +1,50 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s --enable-var-scope + +// CHECK-LABEL: define void {{.*}}arr_assign1 +// CHECK: [[Arr:%.*]] = alloca [2 x i32], align 4 +// CHECK: [[Arr2:%.*]] = alloca [2 x i32], align 4 +// CHECK: [[Tmp:%.*]] = alloca [2 x i32], align 4 +// CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Arr]], ptr align 4 {{@.*}}, i32 8, i1 false) +// CHECK: call void @llvm.memset.p0.i32(ptr align 4 [[Arr2]], i8 0, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Arr]], ptr align 4 [[Arr2]], i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Tmp]], ptr align 4 [[Arr]], i32 8, i1 false) spall wrote: Yes, and that would enable Arr = Arr2 = Arr3 = Arr4 and so on. Is it not an rvalue? https://github.com/llvm/llvm-project/pull/109323 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [HLSL] Array by-value assignment (PR #109323)
@@ -0,0 +1,50 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s --enable-var-scope + +// CHECK-LABEL: define void {{.*}}arr_assign1 +// CHECK: [[Arr:%.*]] = alloca [2 x i32], align 4 +// CHECK: [[Arr2:%.*]] = alloca [2 x i32], align 4 +// CHECK: [[Tmp:%.*]] = alloca [2 x i32], align 4 +// CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Arr]], ptr align 4 {{@.*}}, i32 8, i1 false) +// CHECK: call void @llvm.memset.p0.i32(ptr align 4 [[Arr2]], i8 0, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Arr]], ptr align 4 [[Arr2]], i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Tmp]], ptr align 4 [[Arr]], i32 8, i1 false) spall wrote: I believe the Tmp exists so 'A = B =C' is possible. https://github.com/llvm/llvm-project/pull/109323 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [HLSL] Array by-value assignment (PR #109323)
@@ -0,0 +1,50 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s --enable-var-scope + +// CHECK-LABEL: define void {{.*}}arr_assign1 +// CHECK: [[Arr:%.*]] = alloca [2 x i32], align 4 +// CHECK: [[Arr2:%.*]] = alloca [2 x i32], align 4 +// CHECK: [[Tmp:%.*]] = alloca [2 x i32], align 4 +// CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Arr]], ptr align 4 {{@.*}}, i32 8, i1 false) +// CHECK: call void @llvm.memset.p0.i32(ptr align 4 [[Arr2]], i8 0, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Arr]], ptr align 4 [[Arr2]], i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Tmp]], ptr align 4 [[Arr]], i32 8, i1 false) spall wrote: Is this a bug? I thought that was the correct behavior. https://github.com/llvm/llvm-project/pull/109323 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [HLSL] Implementation of the elementwise fmod builtin (PR #108849)
https://github.com/spall approved this pull request. https://github.com/llvm/llvm-project/pull/108849 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [HLSL][clang] Add elementwise builtin for atan2 (p3) (PR #110187)
https://github.com/spall approved this pull request. Code LGTM; didn't look at the tests too closely. https://github.com/llvm/llvm-project/pull/110187 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [HLSL] Array by-value assignment (PR #109323)
https://github.com/spall updated https://github.com/llvm/llvm-project/pull/109323 >From f4d72ce6faca5498f184069b7c5d22841a449e74 Mon Sep 17 00:00:00 2001 From: Sarah Spall Date: Wed, 18 Sep 2024 22:19:07 + Subject: [PATCH 1/3] enable array by value assignment --- clang/include/clang/AST/CanonicalType.h | 1 + clang/lib/AST/ExprClassification.cpp| 3 ++- clang/lib/Sema/SemaOverload.cpp | 11 --- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/clang/include/clang/AST/CanonicalType.h b/clang/include/clang/AST/CanonicalType.h index dde08f0394c98d..6102eb01793530 100644 --- a/clang/include/clang/AST/CanonicalType.h +++ b/clang/include/clang/AST/CanonicalType.h @@ -299,6 +299,7 @@ class CanProxyBase { LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isDependentType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isOverloadableType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isArrayType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isConstantArrayType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasPointerRepresentation) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasObjCPointerRepresentation) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasIntegerRepresentation) diff --git a/clang/lib/AST/ExprClassification.cpp b/clang/lib/AST/ExprClassification.cpp index 5dde923312698f..9d97633309ada2 100644 --- a/clang/lib/AST/ExprClassification.cpp +++ b/clang/lib/AST/ExprClassification.cpp @@ -704,7 +704,8 @@ static Cl::ModifiableType IsModifiable(ASTContext &Ctx, const Expr *E, return Cl::CM_ConstAddrSpace; // Arrays are not modifiable, only their elements are. - if (CT->isArrayType()) + if (CT->isArrayType() && + !(Ctx.getLangOpts().HLSL && CT->isConstantArrayType())) return Cl::CM_ArrayType; // Incomplete types are not modifiable. if (CT->isIncompleteType()) diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 0c1e054f7c30a4..2cde8131108fbe 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -2232,16 +2232,21 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, // just strip the qualifiers because they don't matter. FromType = FromType.getUnqualifiedType(); } else if (S.getLangOpts().HLSL && FromType->isConstantArrayType() && - ToType->isArrayParameterType()) { + ToType->isConstantArrayType()) { // HLSL constant array parameters do not decay, so if the argument is a // constant array and the parameter is an ArrayParameterType we have special // handling here. -FromType = S.Context.getArrayParameterType(FromType); +if (ToType->isArrayParameterType()) { + FromType = S.Context.getArrayParameterType(FromType); + SCS.First = ICK_HLSL_Array_RValue; +} else { + SCS.First = ICK_Identity; +} + if (S.Context.getCanonicalType(FromType) != S.Context.getCanonicalType(ToType)) return false; -SCS.First = ICK_HLSL_Array_RValue; SCS.setAllToTypes(ToType); return true; } else if (FromType->isArrayType()) { >From 76c7a7d2be4427b7660773566f203ba56ec573b2 Mon Sep 17 00:00:00 2001 From: Sarah Spall Date: Thu, 19 Sep 2024 19:33:39 + Subject: [PATCH 2/3] test assignable arrays --- clang/test/AST/HLSL/ArrayAssignable.hlsl | 80 +++ clang/test/CodeGenHLSL/ArrayAssignable.hlsl | 50 .../test/SemaHLSL/ArrayAssignable_errors.hlsl | 29 +++ 3 files changed, 159 insertions(+) create mode 100644 clang/test/AST/HLSL/ArrayAssignable.hlsl create mode 100644 clang/test/CodeGenHLSL/ArrayAssignable.hlsl create mode 100644 clang/test/SemaHLSL/ArrayAssignable_errors.hlsl diff --git a/clang/test/AST/HLSL/ArrayAssignable.hlsl b/clang/test/AST/HLSL/ArrayAssignable.hlsl new file mode 100644 index 00..52c9918aa85334 --- /dev/null +++ b/clang/test/AST/HLSL/ArrayAssignable.hlsl @@ -0,0 +1,80 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump %s | FileCheck %s + +// CHECK-LABEL: arr_assign1 +// CHECK: CompoundStmt 0x{{[0-9a-f]+}} {{.*}} +// CHECK: DeclStmt 0x{{[0-9a-f]+}} {{.*}} +// CHECK: VarDecl [[A:0x[0-9a-f]+]] {{.*}} col:7 used Arr 'int[2]' cinit +// CHECK: InitListExpr 0x{{[0-9a-f]+}} {{.*}} 'int[2]' +// CHECK: IntegerLiteral 0x{{[0-9a-f]+}} {{.*}} 'int' 0 +// CHECK: IntegerLiteral 0x{{[0-9a-f]+}} {{.*}} 'int' 1 +// CHECK: DeclStmt 0x{{[0-9a-f]+}} {{.*}} +// CHECK: VarDecl [[B:0x[0-9a-f]+]] {{.*}} col:7 used Arr2 'int[2]' cinit +// CHECK: InitListExpr 0x{{[0-9a-f]+}} {{.*}} 'int[2]' +// CHECK: IntegerLiteral 0x{{[0-9a-f]+}} {{.*}} 'int' 0 +// CHECK: IntegerLiteral 0x{{[0-9a-f]+}} {{.*}} 'int' 0 +// CHECK: BinaryOperator 0x{{[0-9a-f]+}} {{.*}} 'int[2]' lvalue '=' +// CHECK: DeclRefExpr 0x{{[0-9a-f]+}} {{.*}} 'int[2]' lvalue Var [[A]] 'Arr' 'int[2]' +// CHECK: DeclRefExpr 0x{{[0-9a-f]+}} {{.*}} 'int[2]' lvalue Var [[B]] 'Arr2' 'int[2]' +void arr_assign1() { + int Arr[2] = {0, 1}; + in
[clang] [HLSL] Array by-value assignment (PR #109323)
https://github.com/spall created https://github.com/llvm/llvm-project/pull/109323 Make Constant Arrays in HLSL assignable. Closes #109043 >From b24aed9771a415a4dc896c48cfc0481574a0773c Mon Sep 17 00:00:00 2001 From: Sarah Spall Date: Wed, 18 Sep 2024 22:19:07 + Subject: [PATCH 1/2] enable array by value assignment --- clang/include/clang/AST/CanonicalType.h | 1 + clang/lib/AST/ExprClassification.cpp| 3 ++- clang/lib/Sema/SemaOverload.cpp | 11 --- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/clang/include/clang/AST/CanonicalType.h b/clang/include/clang/AST/CanonicalType.h index dde08f0394c98d..6102eb01793530 100644 --- a/clang/include/clang/AST/CanonicalType.h +++ b/clang/include/clang/AST/CanonicalType.h @@ -299,6 +299,7 @@ class CanProxyBase { LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isDependentType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isOverloadableType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isArrayType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isConstantArrayType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasPointerRepresentation) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasObjCPointerRepresentation) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasIntegerRepresentation) diff --git a/clang/lib/AST/ExprClassification.cpp b/clang/lib/AST/ExprClassification.cpp index 5dde923312698f..9d97633309ada2 100644 --- a/clang/lib/AST/ExprClassification.cpp +++ b/clang/lib/AST/ExprClassification.cpp @@ -704,7 +704,8 @@ static Cl::ModifiableType IsModifiable(ASTContext &Ctx, const Expr *E, return Cl::CM_ConstAddrSpace; // Arrays are not modifiable, only their elements are. - if (CT->isArrayType()) + if (CT->isArrayType() && + !(Ctx.getLangOpts().HLSL && CT->isConstantArrayType())) return Cl::CM_ArrayType; // Incomplete types are not modifiable. if (CT->isIncompleteType()) diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index d304f322aced64..ce503f9c69b411 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -2232,16 +2232,21 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, // just strip the qualifiers because they don't matter. FromType = FromType.getUnqualifiedType(); } else if (S.getLangOpts().HLSL && FromType->isConstantArrayType() && - ToType->isArrayParameterType()) { + ToType->isConstantArrayType()) { // HLSL constant array parameters do not decay, so if the argument is a // constant array and the parameter is an ArrayParameterType we have special // handling here. -FromType = S.Context.getArrayParameterType(FromType); +if (ToType->isArrayParameterType()) { + FromType = S.Context.getArrayParameterType(FromType); + SCS.First = ICK_HLSL_Array_RValue; +} else { + SCS.First = ICK_Identity; +} + if (S.Context.getCanonicalType(FromType) != S.Context.getCanonicalType(ToType)) return false; -SCS.First = ICK_HLSL_Array_RValue; SCS.setAllToTypes(ToType); return true; } else if (FromType->isArrayType()) { >From a81247d0992a3fb2376a9b3dc60e5fbfd782ffbf Mon Sep 17 00:00:00 2001 From: Sarah Spall Date: Thu, 19 Sep 2024 19:33:39 + Subject: [PATCH 2/2] test assignable arrays --- clang/test/AST/HLSL/ArrayAssignable.hlsl | 80 +++ clang/test/CodeGenHLSL/ArrayAssignable.hlsl | 50 .../test/SemaHLSL/ArrayAssignable_errors.hlsl | 29 +++ 3 files changed, 159 insertions(+) create mode 100644 clang/test/AST/HLSL/ArrayAssignable.hlsl create mode 100644 clang/test/CodeGenHLSL/ArrayAssignable.hlsl create mode 100644 clang/test/SemaHLSL/ArrayAssignable_errors.hlsl diff --git a/clang/test/AST/HLSL/ArrayAssignable.hlsl b/clang/test/AST/HLSL/ArrayAssignable.hlsl new file mode 100644 index 00..52c9918aa85334 --- /dev/null +++ b/clang/test/AST/HLSL/ArrayAssignable.hlsl @@ -0,0 +1,80 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump %s | FileCheck %s + +// CHECK-LABEL: arr_assign1 +// CHECK: CompoundStmt 0x{{[0-9a-f]+}} {{.*}} +// CHECK: DeclStmt 0x{{[0-9a-f]+}} {{.*}} +// CHECK: VarDecl [[A:0x[0-9a-f]+]] {{.*}} col:7 used Arr 'int[2]' cinit +// CHECK: InitListExpr 0x{{[0-9a-f]+}} {{.*}} 'int[2]' +// CHECK: IntegerLiteral 0x{{[0-9a-f]+}} {{.*}} 'int' 0 +// CHECK: IntegerLiteral 0x{{[0-9a-f]+}} {{.*}} 'int' 1 +// CHECK: DeclStmt 0x{{[0-9a-f]+}} {{.*}} +// CHECK: VarDecl [[B:0x[0-9a-f]+]] {{.*}} col:7 used Arr2 'int[2]' cinit +// CHECK: InitListExpr 0x{{[0-9a-f]+}} {{.*}} 'int[2]' +// CHECK: IntegerLiteral 0x{{[0-9a-f]+}} {{.*}} 'int' 0 +// CHECK: IntegerLiteral 0x{{[0-9a-f]+}} {{.*}} 'int' 0 +// CHECK: BinaryOperator 0x{{[0-9a-f]+}} {{.*}} 'int[2]' lvalue '=' +// CHECK: DeclRefExpr 0x{{[0-9a-f]+}} {{.*}} 'int[2]' lvalue Var [[A]] 'Arr' 'int[2]' +// CHECK: DeclRefExpr 0x{{[0-9a-f]+}} {{.*}} 'int[2]' lvalue Var [[B]] 'Arr2' '
[clang] [llvm] adding clang codegen (PR #109331)
@@ -18824,6 +18824,40 @@ case Builtin::BI__builtin_hlsl_elementwise_isinf: { retType, CGM.getHLSLRuntime().getSignIntrinsic(), ArrayRef{Op0}, nullptr, "hlsl.sign"); } + // This should only be called when targeting DXIL + case Builtin::BI__builtin_hlsl_asuint_splitdouble: { + +assert((E->getArg(0)->getType()->isDoubleType() || spall wrote: Shouldn't this assert use && here instead of || because all of those need to be true? As it is now if any of them are true the assert won't be triggered, and the code should assert if any one of them are false. https://github.com/llvm/llvm-project/pull/109331 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Implement elementwise popcount (PR #108121)
https://github.com/spall closed https://github.com/llvm/llvm-project/pull/108121 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [HLSL] Array by-value assignment (PR #109323)
https://github.com/spall closed https://github.com/llvm/llvm-project/pull/109323 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [HLSL] Implementation of the fmod intrinsic (PR #108849)
spall wrote: This code only runs if the language option is HLSL right? https://github.com/llvm/llvm-project/pull/108849 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [HLSL] Implementation of the fmod intrinsic (PR #108849)
spall wrote: If this builtin is for clang and not just HLSL should the semantics checking be in this file and not 'SemaChecking'? https://github.com/llvm/llvm-project/pull/108849 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [HLSL] Implementation of the fmod intrinsic (PR #108849)
spall wrote: Glad to approve after this gets updated then! https://github.com/llvm/llvm-project/pull/108849 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [DXIL][SPIRV] Lower `WaveActiveCountBits` intrinsic (PR #113382)
https://github.com/spall approved this pull request. https://github.com/llvm/llvm-project/pull/113382 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [DXIL][SPIRV] Lower `WaveActiveCountBits` intrinsic (PR #113382)
@@ -1762,6 +1765,37 @@ bool SPIRVInstructionSelector::selectSign(Register ResVReg, return Result; } +bool SPIRVInstructionSelector::selectWaveActiveCountBits( +Register ResVReg, const SPIRVType *ResType, MachineInstr &I) const { + assert(I.getNumOperands() == 3); + assert(I.getOperand(2).isReg()); + MachineBasicBlock &BB = *I.getParent(); + + Register BallotReg = MRI->createVirtualRegister(&SPIRV::IDRegClass); spall wrote: Is SPIRV::IDRegClass just a register class for all types? Because there are others like SPIRV::vIDRegClass, which is for vectors. https://github.com/llvm/llvm-project/pull/113382 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] implement elementwise firstbithigh hlsl builtin (PR #111082)
https://github.com/spall edited https://github.com/llvm/llvm-project/pull/111082 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Re-implement countbits with the correct return type (PR #113189)
https://github.com/spall updated https://github.com/llvm/llvm-project/pull/113189 >From 12cac48dcc10ef9c5fccba2c22911f420298b98b Mon Sep 17 00:00:00 2001 From: Sarah Spall Date: Wed, 16 Oct 2024 19:00:08 + Subject: [PATCH 1/4] implement countbits correctly --- clang/lib/Headers/hlsl/hlsl_intrinsics.h | 126 +++--- .../test/CodeGenHLSL/builtins/countbits.hlsl | 42 +++--- .../SemaHLSL/BuiltIns/countbits-errors.hlsl | 14 +- llvm/lib/Target/DirectX/DXIL.td | 5 +- llvm/lib/Target/DirectX/DXILOpLowering.cpp| 64 + llvm/test/CodeGen/DirectX/countbits.ll| 39 -- 6 files changed, 202 insertions(+), 88 deletions(-) diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index 30dce60b3ff702..2a612c3746076c 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -705,66 +705,90 @@ float4 cosh(float4); #ifdef __HLSL_ENABLE_16_BIT _HLSL_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int16_t countbits(int16_t); +constexpr uint countbits(int16_t x) { + return __builtin_elementwise_popcount(x); +} _HLSL_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int16_t2 countbits(int16_t2); +constexpr uint2 countbits(int16_t2 x) { + return __builtin_elementwise_popcount(x); +} _HLSL_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int16_t3 countbits(int16_t3); +constexpr uint3 countbits(int16_t3 x) { + return __builtin_elementwise_popcount(x); +} _HLSL_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int16_t4 countbits(int16_t4); +constexpr uint4 countbits(int16_t4 x) { + return __builtin_elementwise_popcount(x); +} _HLSL_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -uint16_t countbits(uint16_t); +constexpr uint countbits(uint16_t x) { + return __builtin_elementwise_popcount(x); +} _HLSL_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -uint16_t2 countbits(uint16_t2); +constexpr uint2 countbits(uint16_t2 x) { + return __builtin_elementwise_popcount(x); +} _HLSL_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -uint16_t3 countbits(uint16_t3); +constexpr uint3 countbits(uint16_t3 x) { + return __builtin_elementwise_popcount(x); +} _HLSL_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -uint16_t4 countbits(uint16_t4); +constexpr uint4 countbits(uint16_t4 x) { + return __builtin_elementwise_popcount(x); +} #endif -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int countbits(int); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int2 countbits(int2); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int3 countbits(int3); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int4 countbits(int4); - -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -uint countbits(uint); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -uint2 countbits(uint2); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -uint3 countbits(uint3); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -uint4 countbits(uint4); - -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int64_t countbits(int64_t); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int64_t2 countbits(int64_t2); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int64_t3 countbits(int64_t3); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -int64_t4 countbits(int64_t4); - -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -uint64_t countbits(uint64_t); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -uint64_t2 countbits(uint64_t2); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -uint64_t3 countbits(uint64_t3); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) -uint64_t4 countbits(uint64_t4); +constexpr uint countbits(int x) { + return __builtin_elementwise_popcount(x); +} +constexpr uint2 countbits(int2 x) { + return __builtin_elementwise_popcount(x); +} +constexpr uint3 countbits(int3 x) { + return __builtin_elementwise_popcount(x); +} +constexpr uint4 countbits(int4 x) { + return __builtin_elementwise_popcount(x); +} + +constexpr uint countbits(uint x) { + return __builtin_elementwise_popcount(x); +} +constexpr uint2 countbits(uint2 x) { + return __builtin_elementwise_popcount(x); +} +constexpr uint3 countbits(uint3 x) { + return __builtin_elementwise_popcount(x); +} +constexpr uint4 countbits(uint4 x) { + return __builtin_elementwise_popcount(x); +} + +constexpr uint countbits(int64_t x) { + return __builtin_elementwise_popcount(x); +} +constexpr uint2 countbits(int64_t2 x) { + return __builtin_elementwise_popcount(x); +} +constexpr uint3 countbits(int64_t3 x) { + return __builtin_elementwise_popcount(x); +} +constexpr uint4 countbits(int64_t4 x) { + return
[clang] [llvm] [HLSL] implement elementwise firstbithigh hlsl builtin (PR #111082)
https://github.com/spall closed https://github.com/llvm/llvm-project/pull/111082 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL][DXIL] Implement `asdouble` intrinsic (PR #114847)
https://github.com/spall approved this pull request. LGTM https://github.com/llvm/llvm-project/pull/114847 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Implement elementwise popcount (PR #108121)
https://github.com/spall updated https://github.com/llvm/llvm-project/pull/108121 >From ebb4078d485559f70d79d3b10dc9f4ce401a3261 Mon Sep 17 00:00:00 2001 From: Sarah Spall Date: Fri, 6 Sep 2024 21:03:05 + Subject: [PATCH 1/3] implement elementwise popcount to implement countbits --- clang/docs/LanguageExtensions.rst | 1 + clang/include/clang/Basic/Builtins.td | 6 ++ clang/lib/CodeGen/CGBuiltin.cpp | 3 + clang/lib/Headers/hlsl/hlsl_intrinsics.h | 71 +++ clang/lib/Sema/SemaChecking.cpp | 2 +- clang/lib/Sema/SemaHLSL.cpp | 8 +++ .../test/CodeGen/builtins-elementwise-math.c | 37 ++ clang/test/Sema/builtins-elementwise-math.c | 21 ++ .../SemaCXX/builtins-elementwise-math.cpp | 8 +++ llvm/lib/Target/DirectX/DXIL.td | 11 +++ llvm/test/CodeGen/DirectX/countbits.ll| 31 llvm/test/CodeGen/DirectX/countbits_error.ll | 10 +++ .../SPIRV/hlsl-intrinsics/countbits.ll| 21 ++ 13 files changed, 229 insertions(+), 1 deletion(-) create mode 100644 llvm/test/CodeGen/DirectX/countbits.ll create mode 100644 llvm/test/CodeGen/DirectX/countbits_error.ll create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/countbits.ll diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index c08697282cbfe8..f62f90fb9650a9 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -667,6 +667,7 @@ Unless specified otherwise operation(±0) = ±0 and operation(±infinity) = ±in T __builtin_elementwise_log(T x)return the natural logarithm of x floating point types T __builtin_elementwise_log2(T x) return the base 2 logarithm of x floating point types T __builtin_elementwise_log10(T x) return the base 10 logarithm of x floating point types + T __builtin_elementwise_popcount(T x) return the number of 1 bits in x integer types T __builtin_elementwise_pow(T x, T y) return x raised to the power of y floating point types T __builtin_elementwise_bitreverse(T x) return the integer represented after reversing the bits of x integer types T __builtin_elementwise_exp(T x)returns the base-e exponential, e^x, of the specified value floating point types diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 6cf03d27055cd9..8c5d7ad763bf97 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -1322,6 +1322,12 @@ def ElementwiseLog10 : Builtin { let Prototype = "void(...)"; } +def ElementwisePopcount : Builtin { + let Spellings = ["__builtin_elementwise_popcount"]; + let Attributes = [NoThrow, Const, CustomTypeChecking]; + let Prototype = "void(...)"; +} + def ElementwisePow : Builtin { let Spellings = ["__builtin_elementwise_pow"]; let Attributes = [NoThrow, Const, CustomTypeChecking]; diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index a52e880a764252..df2b8b5595e8b3 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -3834,6 +3834,9 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__builtin_elementwise_floor: return RValue::get(emitBuiltinWithOneOverloadedType<1>( *this, E, llvm::Intrinsic::floor, "elt.floor")); + case Builtin::BI__builtin_elementwise_popcount: +return RValue::get(emitBuiltinWithOneOverloadedType<1>( + *this, E, llvm::Intrinsic::ctpop, "elt.ctpop")); case Builtin::BI__builtin_elementwise_roundeven: return RValue::get(emitBuiltinWithOneOverloadedType<1>( *this, E, llvm::Intrinsic::roundeven, "elt.roundeven")); diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index 6a50d50ebd3479..6cd6a2caf19994 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -650,6 +650,77 @@ float3 cosh(float3); _HLSL_BUILTIN_ALIAS(__builtin_elementwise_cosh) float4 cosh(float4); +//===--===// +// count bits builtins +//===--===// + +/// \fn T countbits(T Val) +/// \brief Return the number of bits (per component) set in the input integer. +/// \param Val The input value. + +#ifdef __HLSL_ENABLE_16_BIT +_HLSL_AVAILABILITY(shadermodel, 6.2) +_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) +int16_t countbits(int16_t); +_HLSL_AVAILABILITY(shadermodel, 6.2) +_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount) +int16_t2 countbits(int16_t2); +_HLSL_AVAILABILITY(shadermodel, 6.2) +_HLSL_BUILTIN_ALIAS(
[clang] Implement HLSL Flat casting (excluding splat cases) (PR #118842)
spall wrote: I'm going to change the name of the Cast to HLSLFlatCast. https://github.com/llvm/llvm-project/pull/118842 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Implement HLSL Flat casting (excluding splat cases) (PR #118842)
https://github.com/spall created https://github.com/llvm/llvm-project/pull/118842 Implement HLSL Flat casting excluding splat cases Partly closes #100609 and #100619 >From 2e932a57ccb992b856b58bec4c30c6b64f24f711 Mon Sep 17 00:00:00 2001 From: Sarah Spall Date: Thu, 28 Nov 2024 16:23:57 + Subject: [PATCH 1/4] Flat casts WIP --- clang/include/clang/AST/OperationKinds.def| 3 + clang/include/clang/Sema/SemaHLSL.h | 2 + clang/lib/AST/Expr.cpp| 1 + clang/lib/AST/ExprConstant.cpp| 1 + clang/lib/CodeGen/CGExpr.cpp | 84 ++ clang/lib/CodeGen/CGExprAgg.cpp | 83 +- clang/lib/CodeGen/CGExprComplex.cpp | 1 + clang/lib/CodeGen/CGExprConstant.cpp | 1 + clang/lib/CodeGen/CGExprScalar.cpp| 39 + clang/lib/CodeGen/CodeGenFunction.h | 7 + clang/lib/Edit/RewriteObjCFoundationAPI.cpp | 1 + clang/lib/Sema/Sema.cpp | 1 + clang/lib/Sema/SemaCast.cpp | 20 ++- clang/lib/Sema/SemaHLSL.cpp | 143 ++ clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp | 1 + 15 files changed, 384 insertions(+), 4 deletions(-) diff --git a/clang/include/clang/AST/OperationKinds.def b/clang/include/clang/AST/OperationKinds.def index 8788b8ff0ef0a4..9323d4e861a734 100644 --- a/clang/include/clang/AST/OperationKinds.def +++ b/clang/include/clang/AST/OperationKinds.def @@ -367,6 +367,9 @@ CAST_OPERATION(HLSLVectorTruncation) // Non-decaying array RValue cast (HLSL only). CAST_OPERATION(HLSLArrayRValue) +// Aggregate by Value cast (HLSL only). +CAST_OPERATION(HLSLAggregateCast) + //===- Binary Operations -===// // Operators listed in order of precedence. // Note that additions to this should also update the StmtVisitor class, diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h index ee685d95c96154..6bda1e8ce0ea5b 100644 --- a/clang/include/clang/Sema/SemaHLSL.h +++ b/clang/include/clang/Sema/SemaHLSL.h @@ -140,6 +140,8 @@ class SemaHLSL : public SemaBase { // Diagnose whether the input ID is uint/unit2/uint3 type. bool diagnoseInputIDType(QualType T, const ParsedAttr &AL); + bool CanPerformScalarCast(QualType SrcTy, QualType DestTy); + bool CanPerformAggregateCast(Expr *Src, QualType DestType); ExprResult ActOnOutParamExpr(ParmVarDecl *Param, Expr *Arg); QualType getInoutParameterType(QualType Ty); diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index a4fb4d5a1f2ec4..4764bc84ce498a 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -1942,6 +1942,7 @@ bool CastExpr::CastConsistency() const { case CK_FixedPointToBoolean: case CK_HLSLArrayRValue: case CK_HLSLVectorTruncation: + case CK_HLSLAggregateCast: CheckNoBasePath: assert(path_empty() && "Cast kind should not have a base path!"); break; diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 6b5b95aee35522..b548cef41b7525 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -15733,6 +15733,7 @@ bool ComplexExprEvaluator::VisitCastExpr(const CastExpr *E) { case CK_IntegralToFixedPoint: case CK_MatrixCast: case CK_HLSLVectorTruncation: + case CK_HLSLAggregateCast: llvm_unreachable("invalid cast kind for complex value"); case CK_LValueToRValue: diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 5fccc9cbb37ec1..b7608b1226758d 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -5320,6 +5320,7 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) { case CK_MatrixCast: case CK_HLSLVectorTruncation: case CK_HLSLArrayRValue: + case CK_HLSLAggregateCast: return EmitUnsupportedLValue(E, "unexpected cast lvalue"); case CK_Dependent: @@ -6358,3 +6359,86 @@ RValue CodeGenFunction::EmitPseudoObjectRValue(const PseudoObjectExpr *E, LValue CodeGenFunction::EmitPseudoObjectLValue(const PseudoObjectExpr *E) { return emitPseudoObjectExpr(*this, E, true, AggValueSlot::ignored()).LV; } + +llvm::Value* CodeGenFunction::PerformLoad(std::pair &GEP) { + Address GEPAddress = GEP.first; + llvm::Value *Idx = GEP.second; + llvm::Value *V = Builder.CreateLoad(GEPAddress, "load"); + if (Idx) { // loading from a vector so perform an extract as well +return Builder.CreateExtractElement(V, Idx, "vec.load"); + } + return V; +} + +llvm::Value* CodeGenFunction::PerformStore(std::pair &GEP, + llvm::Value *Val) { + Address GEPAddress = GEP.first; + llvm::Value *Idx = GEP.second; + if (Idx) { +llvm::Value *V = Builder.CreateLoad(GEPAddress, "load.for.insert"); +return Builder.CreateInsertElement(V, Val, Idx); + } else { +return Builder.CreateStore(Val, GEPAddress); + } +} + +void CodeGen
[clang] [HLSL] Implement HLSL Flat casting (excluding splat cases) (PR #118842)
https://github.com/spall edited https://github.com/llvm/llvm-project/pull/118842 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [HLSL] Implement HLSL Flat casting (excluding splat cases) (PR #118842)
https://github.com/spall edited https://github.com/llvm/llvm-project/pull/118842 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [HLSL] get inout/out ABI for array parameters working (PR #111047)
https://github.com/spall updated https://github.com/llvm/llvm-project/pull/111047 >From 119def060924f13bd1fe07f6d73ce27a1b52ea12 Mon Sep 17 00:00:00 2001 From: Sarah Spall Date: Tue, 17 Sep 2024 20:25:46 + Subject: [PATCH 1/8] theoretically fix issue --- clang/lib/Sema/SemaType.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index e526a11973975d..4874a4902a5cc6 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -5675,6 +5675,9 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, assert(!T.isNull() && "T must not be null at the end of this function"); if (!AreDeclaratorChunksValid) return Context.getTrivialTypeSourceInfo(T); + + if (state.didParseHLSLParamMod() && !T->isConstantArrayType()) +T = S.HLSL().getInoutParameterType(T); return GetTypeSourceInfoForDeclarator(state, T, TInfo); } @@ -8616,7 +8619,6 @@ static void HandleHLSLParamModifierAttr(TypeProcessingState &State, return; if (Attr.getSemanticSpelling() == HLSLParamModifierAttr::Keyword_inout || Attr.getSemanticSpelling() == HLSLParamModifierAttr::Keyword_out) { -CurType = S.HLSL().getInoutParameterType(CurType); State.setParsedHLSLParamMod(true); } } >From 3231a7b7327b6550291dfbeeec5a1907a7473e7f Mon Sep 17 00:00:00 2001 From: Sarah Spall Date: Wed, 2 Oct 2024 21:34:02 + Subject: [PATCH 2/8] get inout working --- clang/include/clang/AST/ASTContext.h | 4 +++ clang/lib/AST/ASTContext.cpp | 10 +++ clang/lib/CodeGen/CGCall.cpp | 3 +- clang/lib/CodeGen/CGExpr.cpp | 7 +++-- clang/lib/Sema/SemaExprCXX.cpp | 13 +++-- clang/lib/Sema/SemaOverload.cpp | 43 6 files changed, 55 insertions(+), 25 deletions(-) diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 89fcb6789d880a..e9bacf8d7391c4 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -1480,6 +1480,10 @@ class ASTContext : public RefCountedBase { /// type to the decayed type. QualType getDecayedType(QualType Orig, QualType Decayed) const; + /// Return the uniqued reference to a constant array type from the + /// original array parameter type. + QualType getConstantArrayFromArrayParameterType(QualType Ty) const; + /// Return the uniqued reference to a specified array parameter type from the /// original array type. QualType getArrayParameterType(QualType Ty) const; diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 09d159e5c3efd6..202d17d3999658 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -3852,6 +3852,16 @@ QualType ASTContext::getDecayedType(QualType T) const { return getDecayedType(T, Decayed); } +QualType ASTContext::getConstantArrayFromArrayParameterType(QualType Ty) const { + if (Ty->isConstantArrayType() && !Ty->isArrayParameterType()) +return Ty; + assert(Ty->isArrayParameterType() && "Ty must be an array parameter type."); + const auto *ATy = cast(Ty); + return getConstantArrayType(ATy->getElementType(), ATy->getSize(), + ATy->getSizeExpr(), ATy->getSizeModifier(), + ATy->getIndexTypeQualifiers().getAsOpaqueValue()); +} + QualType ASTContext::getArrayParameterType(QualType Ty) const { if (Ty->isArrayParameterType()) return Ty; diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 8f4f5d3ed81601..0206d2c1360d47 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -4726,7 +4726,8 @@ void CodeGenFunction::EmitCallArg(CallArgList &args, const Expr *E, return emitWritebackArg(*this, args, CRE); } - assert(type->isReferenceType() == E->isGLValue() && + assert(type->isArrayParameterType() || +(type->isReferenceType() == E->isGLValue()) && "reference binding to unmaterialized r-value!"); // Add writeback for HLSLOutParamExpr. diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 096f4c4f550435..fcab838be40f2b 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -5830,9 +5830,12 @@ LValue CodeGenFunction::EmitBinaryOperatorLValue(const BinaryOperator *E) { // This function implements trivial copy assignment for HLSL's // assignable constant arrays. LValue CodeGenFunction::EmitHLSLArrayAssignLValue(const BinaryOperator *E) { - LValue TrivialAssignmentRHS = EmitLValue(E->getRHS()); + // Don't emit an LValue for the RHS because it might not be an LValue LValue LHS = EmitLValue(E->getLHS()); - EmitAggregateAssign(LHS, TrivialAssignmentRHS, E->getLHS()->getType()); + // In C assignment operator RHS is often an RValue. + // EmitAggregateAssign expects an LValue for the RHS so call the below + // function instead. + EmitInitiali
[clang] [HLSL] get inout/out ABI for array parameters working (PR #111047)
https://github.com/spall closed https://github.com/llvm/llvm-project/pull/111047 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits