[clang] [llvm] [HLSL] [DXIL] Implement the `AddUint64` HLSL function and the `UAddc` DXIL op (PR #125319)
@@ -19105,6 +19105,51 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, return nullptr; switch (BuiltinID) { + case Builtin::BI__builtin_hlsl_adduint64: { Icohedron wrote: `__builtin_addc` was not able to be used to implement `AddUint64` in `hlsl_intrinsics.h` and (by extension) `hlsl_detail.h` because its `carryout` argument is a pointer (as documented [here](https://github.com/llvm/llvm-project/blob/main/clang/lib/CodeGen/CGBuiltin.cpp#L5508)). Since pointers are not supported in HLSL, an error is emitted when running HLSL codegen tests with an example implementation like the following in `hlsl_intrinsics.h`. ```cpp _HLSL_AVAILABILITY(shadermodel, 6.0) const inline uint32_t2 AddUint64(uint32_t2 a, uint32_t2 b) { uint32_t carry; uint32_t low_sum = __builtin_addc(a.x, b.x, 0, &carry); uint32_t high_sum = __builtin_addc(a.y, b.y, carry, nullptr); return uint32_t2(low_sum, high_sum); } ``` ``` build/lib/clang/20/include/hlsl/hlsl_intrinsics.h:158:50: error: the '&' operator is unsupported in HLSL 158 | uint32_t low_sum = __builtin_addc(a.x, b.x, 0, &carry); ``` https://github.com/llvm/llvm-project/pull/125319 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] Reland "[HLSL] Implement the reflect HLSL function" (PR #125599)
https://github.com/Icohedron created https://github.com/llvm/llvm-project/pull/125599 This PR relands #122992. A reland was attempted before (#123853), but it [failed to pass the `sanitizer-aarch64-linux-bootstrap-hwasan` buildbot](https://github.com/llvm/llvm-project/pull/123853#issuecomment-2608389396). An issue (#124045) was made to document the failure and to try to determine the cause. Currently we do not have working local reproduction of the issue, so it is difficult to debug and test fixes. Our current guess is that the hwasan check is being aborted when an error is reported via `report_fatal_error` in the test [`reflect-error.ll`](https://github.com/Icohedron/llvm-project/blob/4363cd2685ad5a1772c8a66796d644783bce0951/clang/test/SemaHLSL/BuiltIns/reflect-errors.hlsl). Hence, a fix we are attempting is to define `HWASAN_OPTIONS="abort_on_error=0"` when running the test. @vitalybuka Could you test this PR on the `sanitizer-aarch64-linux-bootstrap-hwasan` build bot? I will ask @inbelic to commit the PR to an upstream users/ branch. >From d72c55528a71c9d529ee854cf49d57417f2708b1 Mon Sep 17 00:00:00 2001 From: Icohedron Date: Mon, 3 Feb 2025 23:10:16 + Subject: [PATCH 1/2] Reapply "Reland "[HLSL] Implement the `reflect` HLSL function"" (#124046) This reverts commit 0fe8e70c6609ff86cd40fbb45a85a8ed04c153c2. --- clang/include/clang/Basic/BuiltinsSPIRV.td| 6 + clang/lib/CodeGen/CGBuiltin.cpp | 13 ++ clang/lib/Headers/hlsl/hlsl_detail.h | 16 ++ clang/lib/Headers/hlsl/hlsl_intrinsics.h | 43 + clang/lib/Sema/SemaSPIRV.cpp | 32 clang/test/CodeGenHLSL/builtins/reflect.hlsl | 177 ++ clang/test/CodeGenSPIRV/Builtins/reflect.c| 32 .../SemaHLSL/BuiltIns/reflect-errors.hlsl | 33 .../test/SemaSPIRV/BuiltIns/reflect-errors.c | 23 +++ llvm/include/llvm/IR/IntrinsicsSPIRV.td | 1 + .../Target/SPIRV/SPIRVInstructionSelector.cpp | 16 +- .../CodeGen/SPIRV/hlsl-intrinsics/reflect.ll | 33 .../CodeGen/SPIRV/opencl/reflect-error.ll | 13 ++ 13 files changed, 434 insertions(+), 4 deletions(-) create mode 100644 clang/test/CodeGenHLSL/builtins/reflect.hlsl create mode 100644 clang/test/CodeGenSPIRV/Builtins/reflect.c create mode 100644 clang/test/SemaHLSL/BuiltIns/reflect-errors.hlsl create mode 100644 clang/test/SemaSPIRV/BuiltIns/reflect-errors.c create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/reflect.ll create mode 100644 llvm/test/CodeGen/SPIRV/opencl/reflect-error.ll diff --git a/clang/include/clang/Basic/BuiltinsSPIRV.td b/clang/include/clang/Basic/BuiltinsSPIRV.td index f72c555921dfe68..34933e889ba314b 100644 --- a/clang/include/clang/Basic/BuiltinsSPIRV.td +++ b/clang/include/clang/Basic/BuiltinsSPIRV.td @@ -19,3 +19,9 @@ def SPIRVLength : Builtin { let Attributes = [NoThrow, Const]; let Prototype = "void(...)"; } + +def SPIRVReflect : Builtin { + let Spellings = ["__builtin_spirv_reflect"]; + let Attributes = [NoThrow, Const]; + let Prototype = "void(...)"; +} diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 11fa295dad9524c..c7b7d048dd2a9b3 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -20786,6 +20786,19 @@ Value *CodeGenFunction::EmitSPIRVBuiltinExpr(unsigned BuiltinID, /*ReturnType=*/X->getType()->getScalarType(), Intrinsic::spv_length, ArrayRef{X}, nullptr, "spv.length"); } + case SPIRV::BI__builtin_spirv_reflect: { +Value *I = EmitScalarExpr(E->getArg(0)); +Value *N = EmitScalarExpr(E->getArg(1)); +assert(E->getArg(0)->getType()->hasFloatingRepresentation() && + E->getArg(1)->getType()->hasFloatingRepresentation() && + "Reflect operands must have a float representation"); +assert(E->getArg(0)->getType()->isVectorType() && + E->getArg(1)->getType()->isVectorType() && + "Reflect operands must be a vector"); +return Builder.CreateIntrinsic( +/*ReturnType=*/I->getType(), Intrinsic::spv_reflect, +ArrayRef{I, N}, nullptr, "spv.reflect"); + } } return nullptr; } diff --git a/clang/lib/Headers/hlsl/hlsl_detail.h b/clang/lib/Headers/hlsl/hlsl_detail.h index b2c8cc6c5c3dbb0..0d568539cd66a85 100644 --- a/clang/lib/Headers/hlsl/hlsl_detail.h +++ b/clang/lib/Headers/hlsl/hlsl_detail.h @@ -79,6 +79,22 @@ constexpr enable_if_t::value || is_same::value, T> distance_vec_impl(vector X, vector Y) { return length_vec_impl(X - Y); } + +template +constexpr enable_if_t::value || is_same::value, T> +reflect_impl(T I, T N) { + return I - 2 * N * I * N; +} + +template +constexpr vector reflect_vec_impl(vector I, vector N) { +#if (__has_builtin(__builtin_spirv_reflect)) + return __builtin_spirv_reflect(I, N); +#else + return I - 2 * N * __builtin_hlsl_dot(I, N); +#endif +} + } // namespace __detail } // namespace hlsl #endif //_HLSL_HLSL_DETAILS_H_ diff --gi
[clang] [llvm] [HLSL] [DXIL] Implement the `AddUint64` HLSL function and the `UAddc` DXIL op (PR #125319)
https://github.com/Icohedron edited https://github.com/llvm/llvm-project/pull/125319 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] [DXIL] Implement the `AddUint64` HLSL function and the `UAddc` DXIL op (PR #125319)
@@ -359,18 +359,21 @@ class OpLowerer { return lowerToBindAndAnnotateHandle(F); } - Error replaceSplitDoubleCallUsages(CallInst *Intrin, CallInst *Op) { + Error replaceExtractElementTypeOfCallUsages(CallInst *Intrin, CallInst *Op) { for (Use &U : make_early_inc_range(Intrin->uses())) { if (auto *EVI = dyn_cast(U.getUser())) { if (EVI->getNumIndices() != 1) - return createStringError(std::errc::invalid_argument, - "Splitdouble has only 2 elements"); + return createStringError( Icohedron wrote: To be as generic as possible, I could replace the entire function so that it reads: ```c++ Error replaceExtractElementTypeOfCallUsages(CallInst *Intrin, CallInst *Op) { for (Use &U : make_early_inc_range(Intrin->uses())) { U.set(Op); } Intrin->eraseFromParent(); return Error::success(); } ``` This function would just replace all uses of the intrinsic with one to match the new named struct op return type. The function name would need to be changed, or it could be inlined into `replaceFunctionWithNamedStructOp`, since that is the only user of `replaceExtractElementTypeOfCallUsages`. https://github.com/llvm/llvm-project/pull/125319 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] [DXIL] Implement the `AddUint64` HLSL function and the `UAddc` DXIL op (PR #125319)
https://github.com/Icohedron edited https://github.com/llvm/llvm-project/pull/125319 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] [DXIL] Implement the `AddUint64` HLSL function and the `UAddc` DXIL op (PR #125319)
https://github.com/Icohedron edited https://github.com/llvm/llvm-project/pull/125319 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] [DXIL] Implement the `AddUint64` HLSL function and the `UAddc` DXIL op (PR #125319)
@@ -359,18 +359,21 @@ class OpLowerer { return lowerToBindAndAnnotateHandle(F); } - Error replaceSplitDoubleCallUsages(CallInst *Intrin, CallInst *Op) { + Error replaceExtractElementTypeOfCallUsages(CallInst *Intrin, CallInst *Op) { for (Use &U : make_early_inc_range(Intrin->uses())) { if (auto *EVI = dyn_cast(U.getUser())) { if (EVI->getNumIndices() != 1) - return createStringError(std::errc::invalid_argument, - "Splitdouble has only 2 elements"); + return createStringError( Icohedron wrote: The new `replaceFunctionWithNamedStructOp` would look like this ```c++ [[nodiscard]] bool replaceFunctionWithNamedStructOp(Function &F, dxil::OpCode DXILOp, Type *NewRetTy) { bool IsVectorArgExpansion = isVectorArgExpansion(F); return replaceFunction(F, [&](CallInst *CI) -> Error { SmallVector Args; OpBuilder.getIRB().SetInsertPoint(CI); if (IsVectorArgExpansion) { SmallVector NewArgs = argVectorFlatten(CI, OpBuilder.getIRB()); Args.append(NewArgs.begin(), NewArgs.end()); } else Args.append(CI->arg_begin(), CI->arg_end()); Expected OpCall = OpBuilder.tryCreateOp(DXILOp, Args, CI->getName(), NewRetTy); if (Error E = OpCall.takeError()) return E; for (Use &U : make_early_inc_range(CI->uses())) { U.set(*OpCall); } CI->eraseFromParent(); return Error::success(); }); } ``` It works. All aggregate operations (`extractvalue`, `insertvalue`) get replaced correctly. The only issue is if a function returns the result directly: ```c++ define noundef { i32, i1 } @test_UAddc2(i32 noundef %a, i32 noundef %b) { ; CHECK-LABEL: define noundef %dx.types.i32c @test_UAddc2( ; CHECK-SAME: i32 noundef [[A:%.*]], i32 noundef [[B:%.*]]) { ; CHECK-NEXT:[[UAddc:%.*]] = call %dx.types.i32c @dx.op.binaryWithCarryOrBorrow.i32(i32 44, i32 [[A]], i32 [[B]]) ; CHECK-NEXT:ret %dx.types.i32c [[Result]] ; %uaddc = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %a, i32 %b) ret { i32, i1 } %uaddc } ``` It results in an error that reads: ``` opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library /home/icohedron/workspace/feature-uaddc/llvm/test/CodeGen/DirectX/UAddc.ll Function return type does not match operand type of return inst! ret %dx.types.i32c %uaddc1 { i32, i1 }in function test_UAddc2 LLVM ERROR: Broken function found, compilation aborted! ... ``` https://github.com/llvm/llvm-project/pull/125319 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] [DXIL] Implement the `AddUint64` HLSL function and the `UAddc` DXIL op (PR #125319)
https://github.com/Icohedron edited https://github.com/llvm/llvm-project/pull/125319 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] [DXIL] Implement the `AddUint64` HLSL function and the `UAddc` DXIL op (PR #125319)
https://github.com/Icohedron edited https://github.com/llvm/llvm-project/pull/125319 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] [DXIL] Implement the `AddUint64` HLSL function and the `UAddc` DXIL op (PR #125319)
https://github.com/Icohedron edited https://github.com/llvm/llvm-project/pull/125319 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] [DXIL] Implement the `AddUint64` HLSL function and the `UAddc` DXIL op (PR #125319)
https://github.com/Icohedron updated https://github.com/llvm/llvm-project/pull/125319 >From 1e194fdf6dc731276cd867501708b348e3bbc97c Mon Sep 17 00:00:00 2001 From: Icohedron Date: Mon, 27 Jan 2025 11:18:09 -0800 Subject: [PATCH 1/5] Implement AddUint64 HLSL codegen and sema --- clang/include/clang/Basic/Builtins.td | 6 ++ .../clang/Basic/DiagnosticSemaKinds.td| 2 +- clang/lib/CodeGen/CGBuiltin.cpp | 45 clang/lib/Headers/hlsl/hlsl_intrinsics.h | 21 ++ clang/lib/Sema/SemaHLSL.cpp | 49 + .../test/CodeGenHLSL/builtins/AddUint64.hlsl | 71 +++ .../SemaHLSL/BuiltIns/AddUint64-errors.hlsl | 46 7 files changed, 239 insertions(+), 1 deletion(-) create mode 100644 clang/test/CodeGenHLSL/builtins/AddUint64.hlsl create mode 100644 clang/test/SemaHLSL/BuiltIns/AddUint64-errors.hlsl diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 60c360d4a9e075..ffa60bf98aea06 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -4753,6 +4753,12 @@ def GetDeviceSideMangledName : LangBuiltin<"CUDA_LANG"> { } // HLSL +def HLSLAddUint64: LangBuiltin<"HLSL_LANG"> { + let Spellings = ["__builtin_hlsl_adduint64"]; + let Attributes = [NoThrow, Const]; + let Prototype = "void(...)"; +} + def HLSLResourceGetPointer : LangBuiltin<"HLSL_LANG"> { let Spellings = ["__builtin_hlsl_resource_getpointer"]; let Attributes = [NoThrow]; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 774e5484cfa0e7..2d7d306a207417 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -10623,7 +10623,7 @@ def err_second_argument_to_cwsc_not_pointer : Error< "second argument to __builtin_call_with_static_chain must be of pointer type">; def err_vector_incorrect_num_elements : Error< - "%select{too many|too few}0 elements in vector %select{initialization|operand}3 (expected %1 elements, have %2)">; + "%select{too many|too few|incorrect number of}0 elements in vector %select{initialization|operand}3 (expected %1 elements, have %2)">; def err_altivec_empty_initializer : Error<"expected initializer">; def err_invalid_neon_type_code : Error< diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 26bdc5e36e..3a2c74f39afa78 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -19105,6 +19105,51 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, return nullptr; switch (BuiltinID) { + case Builtin::BI__builtin_hlsl_adduint64: { +Value *OpA = EmitScalarExpr(E->getArg(0)); +Value *OpB = EmitScalarExpr(E->getArg(1)); +assert(E->getArg(0)->getType()->hasIntegerRepresentation() && + E->getArg(1)->getType()->hasIntegerRepresentation() && + "AddUint64 operands must have an integer representation"); +assert(((E->getArg(0)->getType()->castAs()->getNumElements() == + 2 && + E->getArg(1)->getType()->castAs()->getNumElements() == + 2) || +(E->getArg(0)->getType()->castAs()->getNumElements() == + 4 && + E->getArg(1)->getType()->castAs()->getNumElements() == + 4)) && + "input vectors must have 2 or 4 elements each"); + +llvm::Value *Result = PoisonValue::get(OpA->getType()); +uint64_t NumElements = +E->getArg(0)->getType()->castAs()->getNumElements(); +for (uint64_t i = 0; i < NumElements / 2; ++i) { + + // Obtain low and high words of inputs A and B + llvm::Value *LowA = Builder.CreateExtractElement(OpA, 2 * i + 0); + llvm::Value *HighA = Builder.CreateExtractElement(OpA, 2 * i + 1); + llvm::Value *LowB = Builder.CreateExtractElement(OpB, 2 * i + 0); + llvm::Value *HighB = Builder.CreateExtractElement(OpB, 2 * i + 1); + + // Use an uadd_with_overflow to compute the sum of low words and obtain a + // carry value + llvm::Value *Carry; + llvm::Value *LowSum = EmitOverflowIntrinsic( + *this, llvm::Intrinsic::uadd_with_overflow, LowA, LowB, Carry); + llvm::Value *ZExtCarry = Builder.CreateZExt(Carry, HighA->getType()); + + // Sum the high words and the carry + llvm::Value *HighSum = Builder.CreateAdd(HighA, HighB); + llvm::Value *HighSumPlusCarry = Builder.CreateAdd(HighSum, ZExtCarry); + + // Insert the low and high word sums into the result vector + Result = Builder.CreateInsertElement(Result, LowSum, 2 * i + 0); + Result = Builder.CreateInsertElement(Result, HighSumPlusCarry, 2 * i + 1, + "hlsl.AddUint64"); +} +return Result; + } case Builtin::BI__builtin_hlsl_resource_getpointer: { Value *HandleOp = EmitScalarE
[clang] [llvm] Reland "[HLSL] Implement the reflect HLSL function" (PR #125599)
Icohedron wrote: @vitalybuka Could you get more details as to why the original PR failed in the hwasan-check from the `sanitizer-aarch64-linux-bootstrap-hwasan` buildbot? The buildbot's report is linked here: [https://lab.llvm.org/buildbot/#/builders/55/builds/5962](https://lab.llvm.org/buildbot/#/builders/55/builds/5962) https://github.com/llvm/llvm-project/pull/125599 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] [DXIL] Implement the `AddUint64` HLSL function and the `UAddc` DXIL op (PR #125319)
@@ -10623,7 +10623,7 @@ def err_second_argument_to_cwsc_not_pointer : Error< "second argument to __builtin_call_with_static_chain must be of pointer type">; def err_vector_incorrect_num_elements : Error< - "%select{too many|too few}0 elements in vector %select{initialization|operand}3 (expected %1 elements, have %2)">; + "%select{too many|too few|incorrect number of}0 elements in vector %select{initialization|operand}3 (expected %1 elements, have %2)">; Icohedron wrote: @inbelic [suggested](https://github.com/llvm/llvm-project/pull/125319#discussion_r1941619629) using `diag::err_vec_builtin_non_vector` instead. It has the message "%select{first two|all}1 arguments to %0 must be vectors" https://github.com/llvm/llvm-project/pull/125319 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] [DXIL] Implement the `AddUint64` HLSL function and the `UAddc` DXIL op (PR #125319)
@@ -2023,6 +2024,18 @@ static bool CheckAllArgsHaveFloatRepresentation(Sema *S, CallExpr *TheCall) { checkAllFloatTypes); } +static bool CheckUnsignedIntegerRepresentation(Sema *S, CallExpr *TheCall) { + auto checkUnsignedInteger = [](clang::QualType PassedType) -> bool { +clang::QualType BaseType = +PassedType->isVectorType() +? PassedType->getAs()->getElementType() +: PassedType; +return !BaseType->isUnsignedIntegerType(); Icohedron wrote: According to what I see in the original issue and in the DXC implementation, only unsigned integers are allowed (specifically, `uint2` and `uint4`). `clang/test/SemaHLSL/BuiltIns/AddUIint64-errors.hlsl` has a test with `int2` passed as arguments that is expected to fail. As for checking if the integer is 32-bits, that is a good idea. The following test is currently valid and does not emit an error. ```c++ uint2 test_16_bit_integer_type(uint16_t2 a, uint16_t2 b) { return __builtin_hlsl_adduint64(a, b); } ``` I am having trouble trying to implement a check on the integer bit count however. I do not know how to get access to `llvm::IntegerType::getIntegerBitWidth()` from a `clang::QualType`. https://github.com/llvm/llvm-project/pull/125319 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] [DXIL] Implement the `AddUint64` HLSL function and the `UAddc` DXIL op (PR #125319)
https://github.com/Icohedron edited https://github.com/llvm/llvm-project/pull/125319 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] [DXIL] Implement the `AddUint64` HLSL function and the `UAddc` DXIL op (PR #125319)
@@ -10623,7 +10623,7 @@ def err_second_argument_to_cwsc_not_pointer : Error< "second argument to __builtin_call_with_static_chain must be of pointer type">; def err_vector_incorrect_num_elements : Error< - "%select{too many|too few}0 elements in vector %select{initialization|operand}3 (expected %1 elements, have %2)">; + "%select{too many|too few|incorrect number of}0 elements in vector %select{initialization|operand}3 (expected %1 elements, have %2)">; Icohedron wrote: I would still need this change for the other error message when a uint3 is passed. We don't know if the programmer intended to use the uint2 or the uint4 version of the function, so uint3 has neither more or less elements than expected -- it's just an incorrect number. https://github.com/llvm/llvm-project/pull/125319 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] [DXIL] Implement the `AddUint64` HLSL function and the `UAddc` DXIL op (PR #125319)
https://github.com/Icohedron updated https://github.com/llvm/llvm-project/pull/125319 >From 1e194fdf6dc731276cd867501708b348e3bbc97c Mon Sep 17 00:00:00 2001 From: Icohedron Date: Mon, 27 Jan 2025 11:18:09 -0800 Subject: [PATCH 1/4] Implement AddUint64 HLSL codegen and sema --- clang/include/clang/Basic/Builtins.td | 6 ++ .../clang/Basic/DiagnosticSemaKinds.td| 2 +- clang/lib/CodeGen/CGBuiltin.cpp | 45 clang/lib/Headers/hlsl/hlsl_intrinsics.h | 21 ++ clang/lib/Sema/SemaHLSL.cpp | 49 + .../test/CodeGenHLSL/builtins/AddUint64.hlsl | 71 +++ .../SemaHLSL/BuiltIns/AddUint64-errors.hlsl | 46 7 files changed, 239 insertions(+), 1 deletion(-) create mode 100644 clang/test/CodeGenHLSL/builtins/AddUint64.hlsl create mode 100644 clang/test/SemaHLSL/BuiltIns/AddUint64-errors.hlsl diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 60c360d4a9e0759..ffa60bf98aea06f 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -4753,6 +4753,12 @@ def GetDeviceSideMangledName : LangBuiltin<"CUDA_LANG"> { } // HLSL +def HLSLAddUint64: LangBuiltin<"HLSL_LANG"> { + let Spellings = ["__builtin_hlsl_adduint64"]; + let Attributes = [NoThrow, Const]; + let Prototype = "void(...)"; +} + def HLSLResourceGetPointer : LangBuiltin<"HLSL_LANG"> { let Spellings = ["__builtin_hlsl_resource_getpointer"]; let Attributes = [NoThrow]; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 774e5484cfa0e75..2d7d306a2074179 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -10623,7 +10623,7 @@ def err_second_argument_to_cwsc_not_pointer : Error< "second argument to __builtin_call_with_static_chain must be of pointer type">; def err_vector_incorrect_num_elements : Error< - "%select{too many|too few}0 elements in vector %select{initialization|operand}3 (expected %1 elements, have %2)">; + "%select{too many|too few|incorrect number of}0 elements in vector %select{initialization|operand}3 (expected %1 elements, have %2)">; def err_altivec_empty_initializer : Error<"expected initializer">; def err_invalid_neon_type_code : Error< diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 26bdc5e36e5..3a2c74f39afa78f 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -19105,6 +19105,51 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, return nullptr; switch (BuiltinID) { + case Builtin::BI__builtin_hlsl_adduint64: { +Value *OpA = EmitScalarExpr(E->getArg(0)); +Value *OpB = EmitScalarExpr(E->getArg(1)); +assert(E->getArg(0)->getType()->hasIntegerRepresentation() && + E->getArg(1)->getType()->hasIntegerRepresentation() && + "AddUint64 operands must have an integer representation"); +assert(((E->getArg(0)->getType()->castAs()->getNumElements() == + 2 && + E->getArg(1)->getType()->castAs()->getNumElements() == + 2) || +(E->getArg(0)->getType()->castAs()->getNumElements() == + 4 && + E->getArg(1)->getType()->castAs()->getNumElements() == + 4)) && + "input vectors must have 2 or 4 elements each"); + +llvm::Value *Result = PoisonValue::get(OpA->getType()); +uint64_t NumElements = +E->getArg(0)->getType()->castAs()->getNumElements(); +for (uint64_t i = 0; i < NumElements / 2; ++i) { + + // Obtain low and high words of inputs A and B + llvm::Value *LowA = Builder.CreateExtractElement(OpA, 2 * i + 0); + llvm::Value *HighA = Builder.CreateExtractElement(OpA, 2 * i + 1); + llvm::Value *LowB = Builder.CreateExtractElement(OpB, 2 * i + 0); + llvm::Value *HighB = Builder.CreateExtractElement(OpB, 2 * i + 1); + + // Use an uadd_with_overflow to compute the sum of low words and obtain a + // carry value + llvm::Value *Carry; + llvm::Value *LowSum = EmitOverflowIntrinsic( + *this, llvm::Intrinsic::uadd_with_overflow, LowA, LowB, Carry); + llvm::Value *ZExtCarry = Builder.CreateZExt(Carry, HighA->getType()); + + // Sum the high words and the carry + llvm::Value *HighSum = Builder.CreateAdd(HighA, HighB); + llvm::Value *HighSumPlusCarry = Builder.CreateAdd(HighSum, ZExtCarry); + + // Insert the low and high word sums into the result vector + Result = Builder.CreateInsertElement(Result, LowSum, 2 * i + 0); + Result = Builder.CreateInsertElement(Result, HighSumPlusCarry, 2 * i + 1, + "hlsl.AddUint64"); +} +return Result; + } case Builtin::BI__builtin_hlsl_resource_getpointer: { Value *HandleOp = EmitS
[clang] [llvm] [HLSL] [DXIL] Implement the `AddUint64` HLSL function and the `UAddc` DXIL op (PR #125319)
@@ -0,0 +1,17 @@ +; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s 2>&1 | FileCheck %s + +; DXIL operation UAddc only supports i32. Other integer types are unsupported. +; CHECK: in function uaddc_i16 Icohedron wrote: LLVM ERROR is not output there. The full error message is: `error: :0:0: in function uaddc_i16 i16 (i16, i16): Cannot create UAddc operation: Invalid overload type` This is similar to the way other directx error tests were written, such as [cos](https://github.com/llvm/llvm-project/blob/main/llvm/test/CodeGen/DirectX/cos_error.ll) https://github.com/llvm/llvm-project/pull/125319 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] [DXIL] Implement the `AddUint64` HLSL function and the `UAddc` DXIL op (PR #125319)
@@ -0,0 +1,46 @@ +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify + +uint2 test_too_few_arg() { + return __builtin_hlsl_adduint64(); + // expected-error@-1 {{too few arguments to function call, expected 2, have 0}} +} + +uint4 test_too_many_arg(uint4 a) { + return __builtin_hlsl_adduint64(a, a, a); + // expected-error@-1 {{too many arguments to function call, expected 2, have 3}} +} + +uint2 test_mismatched_arg_types(uint2 a, uint4 b) { + return __builtin_hlsl_adduint64(a, b); + // expected-error@-1 {{all arguments to '__builtin_hlsl_adduint64' must have the same type}} +} + +uint2 test_too_many_arg_elements(uint3 a, uint3 b) { Icohedron wrote: Renamed the test in commit [28b7eb8](https://github.com/llvm/llvm-project/pull/125319/commits/28b7eb8c6ac603ef1c316e7731b07cb6f6f3a34e) https://github.com/llvm/llvm-project/pull/125319 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] [DXIL] Implement the `AddUint64` HLSL function and the `UAddc` DXIL op (PR #125319)
@@ -21,6 +21,7 @@ #include "clang/AST/Type.h" #include "clang/AST/TypeLoc.h" #include "clang/Basic/Builtins.h" +#include "clang/Basic/DiagnosticParse.h" Icohedron wrote: Removed with commit [28b7eb8](https://github.com/llvm/llvm-project/pull/125319/commits/28b7eb8c6ac603ef1c316e7731b07cb6f6f3a34e) https://github.com/llvm/llvm-project/pull/125319 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] [DXIL] Implement the `AddUint64` HLSL function and the `UAddc` DXIL op (PR #125319)
@@ -0,0 +1,46 @@ +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify + +uint2 test_too_few_arg() { + return __builtin_hlsl_adduint64(); + // expected-error@-1 {{too few arguments to function call, expected 2, have 0}} +} + +uint4 test_too_many_arg(uint4 a) { + return __builtin_hlsl_adduint64(a, a, a); + // expected-error@-1 {{too many arguments to function call, expected 2, have 3}} +} + +uint2 test_mismatched_arg_types(uint2 a, uint4 b) { + return __builtin_hlsl_adduint64(a, b); + // expected-error@-1 {{all arguments to '__builtin_hlsl_adduint64' must have the same type}} +} + +uint2 test_too_many_arg_elements(uint3 a, uint3 b) { + return __builtin_hlsl_adduint64(a, b); + // expected-error@-1 {{incorrect number of elements in vector operand (expected 2 or 4 elements, have 3)}} +} + +uint4 test_too_few_arg_elements(uint3 a, uint3 b) { + return __builtin_hlsl_adduint64(a, b); + // expected-error@-1 {{incorrect number of elements in vector operand (expected 2 or 4 elements, have 3)}} +} Icohedron wrote: Removed in commit [28b7eb8](https://github.com/llvm/llvm-project/pull/125319/commits/28b7eb8c6ac603ef1c316e7731b07cb6f6f3a34e) https://github.com/llvm/llvm-project/pull/125319 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] [DXIL] Implement the `AddUint64` HLSL function and the `UAddc` DXIL op (PR #125319)
@@ -2214,6 +2227,42 @@ static bool CheckResourceHandle( // returning an ExprError bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { switch (BuiltinID) { + case Builtin::BI__builtin_hlsl_adduint64: { +if (SemaRef.checkArgCount(TheCall, 2)) + return true; +if (CheckVectorElementCallArgs(&SemaRef, TheCall)) + return true; +if (CheckUnsignedIntegerRepresentation(&SemaRef, TheCall)) + return true; + +// CheckVectorElementCallArgs(...) guarantees both args are the same type. +assert(TheCall->getArg(0)->getType() == TheCall->getArg(1)->getType() && + "Both args must be of the same type"); + +// ensure both args are vectors +auto *VTy = TheCall->getArg(0)->getType()->getAs(); +if (!VTy) { + SemaRef.Diag(TheCall->getBeginLoc(), + diag::err_vector_incorrect_num_elements) Icohedron wrote: I changed the error message for this in commit [28b7eb8](https://github.com/llvm/llvm-project/pull/125319/commits/28b7eb8c6ac603ef1c316e7731b07cb6f6f3a34e) https://github.com/llvm/llvm-project/pull/125319 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] [DXIL] Implement the `AddUint64` HLSL function and the `UAddc` DXIL op (PR #125319)
@@ -10623,7 +10623,7 @@ def err_second_argument_to_cwsc_not_pointer : Error< "second argument to __builtin_call_with_static_chain must be of pointer type">; def err_vector_incorrect_num_elements : Error< - "%select{too many|too few}0 elements in vector %select{initialization|operand}3 (expected %1 elements, have %2)">; + "%select{too many|too few|incorrect number of}0 elements in vector %select{initialization|operand}3 (expected %1 elements, have %2)">; Icohedron wrote: My latest commit ([28b7eb8](https://github.com/llvm/llvm-project/pull/125319/commits/28b7eb8c6ac603ef1c316e7731b07cb6f6f3a34e)) changed the diag message. Is it now to your liking, or do you still think the diag message should be changed? https://github.com/llvm/llvm-project/pull/125319 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] [DXIL] Implement the `AddUint64` HLSL function and the `UAddc` DXIL op (PR #125319)
@@ -359,18 +359,21 @@ class OpLowerer { return lowerToBindAndAnnotateHandle(F); } - Error replaceSplitDoubleCallUsages(CallInst *Intrin, CallInst *Op) { + Error replaceExtractElementTypeOfCallUsages(CallInst *Intrin, CallInst *Op) { for (Use &U : make_early_inc_range(Intrin->uses())) { if (auto *EVI = dyn_cast(U.getUser())) { if (EVI->getNumIndices() != 1) - return createStringError(std::errc::invalid_argument, - "Splitdouble has only 2 elements"); + return createStringError( Icohedron wrote: I don't think it is possible to make an HLSL test that exercises the error on `if (EVI->getNumIndices() != 1)`. It's just invalid LLVM IR to have more indices than allowed for the struct type. It is caught by some other error handler: ``` $ opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library /home/icohedron/workspace/feature-uaddc/llvm/test/CodeGen/DirectX/UAddc.ll /home/icohedron/workspace/feature-uaddc/build/bin/opt: /home/icohedron/workspace/feature-uaddc/llvm/test/CodeGen/DirectX/UAddc.ll:35:25: error: invalid indices for extractvalue %carry = extractvalue { i32, i1 } %uaddc, 1, 0 ``` The other error is able to be exercised just by having a use that is not an extractvalue. For example, returning the `{ i32, i1 }`: ``` $ opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library /home/icohedron/workspace/feature-uaddc/llvm/test/CodeGen/DirectX/UAddc.ll error: :0:0: in function test_UAddc2 { i32, i1 } (i32, i32): call use is not ExtractValueInst ``` I also see now that `std::string(Intrin->getOpcodeName()` only says "call" and doesn't mention the name of the actual intrinsic being called. So that needs to be fixed, and an error test should be made. https://github.com/llvm/llvm-project/pull/125319 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] [DXIL] Implement the `AddUint64` HLSL function and the `UAddc` DXIL op (PR #125319)
@@ -359,18 +359,21 @@ class OpLowerer { return lowerToBindAndAnnotateHandle(F); } - Error replaceSplitDoubleCallUsages(CallInst *Intrin, CallInst *Op) { + Error replaceExtractElementTypeOfCallUsages(CallInst *Intrin, CallInst *Op) { for (Use &U : make_early_inc_range(Intrin->uses())) { if (auto *EVI = dyn_cast(U.getUser())) { if (EVI->getNumIndices() != 1) - return createStringError(std::errc::invalid_argument, - "Splitdouble has only 2 elements"); + return createStringError( Icohedron wrote: I can replace the error (that checks the number of indicies = 1) with an assert, but since I changed the function name to be more generic, I don't think it should even be present. https://github.com/llvm/llvm-project/pull/125319 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] [DXIL] Implement the `AddUint64` HLSL function and the `UAddc` DXIL op (PR #125319)
@@ -359,18 +359,21 @@ class OpLowerer { return lowerToBindAndAnnotateHandle(F); } - Error replaceSplitDoubleCallUsages(CallInst *Intrin, CallInst *Op) { + Error replaceExtractElementTypeOfCallUsages(CallInst *Intrin, CallInst *Op) { for (Use &U : make_early_inc_range(Intrin->uses())) { if (auto *EVI = dyn_cast(U.getUser())) { if (EVI->getNumIndices() != 1) - return createStringError(std::errc::invalid_argument, - "Splitdouble has only 2 elements"); + return createStringError( Icohedron wrote: Should there even be an error if there are non-`extractvalue` instructions using the result? The function name I chose (`replaceExtractElementTypeOfCallUsages`) implies it will just change the type of `extractelement` instructions that use the result of the call. https://github.com/llvm/llvm-project/pull/125319 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] [DXIL] Implement the `AddUint64` HLSL function and the `UAddc` DXIL op (PR #125319)
https://github.com/Icohedron edited https://github.com/llvm/llvm-project/pull/125319 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] [DXIL] Implement the `AddUint64` HLSL function and the `UAddc` DXIL op (PR #125319)
@@ -19105,6 +19105,51 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, return nullptr; switch (BuiltinID) { + case Builtin::BI__builtin_hlsl_adduint64: { Icohedron wrote: Do you think it is something I should do for this implementation? Are there other HLSL functions that would benefit from / reuse the new builtin using the out args? https://github.com/llvm/llvm-project/pull/125319 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] [DXIL] Implement the `AddUint64` HLSL function and the `UAddc` DXIL op (PR #125319)
https://github.com/Icohedron edited https://github.com/llvm/llvm-project/pull/125319 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] [DXIL] Implement the `AddUint64` HLSL function and the `UAddc` DXIL op (PR #125319)
https://github.com/Icohedron edited https://github.com/llvm/llvm-project/pull/125319 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] [DXIL] Implement the `AddUint64` HLSL function and the `UAddc` DXIL op (PR #125319)
@@ -10623,7 +10623,7 @@ def err_second_argument_to_cwsc_not_pointer : Error< "second argument to __builtin_call_with_static_chain must be of pointer type">; def err_vector_incorrect_num_elements : Error< - "%select{too many|too few}0 elements in vector %select{initialization|operand}3 (expected %1 elements, have %2)">; + "%select{too many|too few|incorrect number of}0 elements in vector %select{initialization|operand}3 (expected %1 elements, have %2)">; Icohedron wrote: I made a new commit ([d2b315a](https://github.com/llvm/llvm-project/pull/125319/commits/d2b315a24f850c6115675ee99c804873f19a8f40)) that creates a new diag message specifically for AddUint64, as per your suggestion (which I can't seem to find anymore?). Is this better? https://github.com/llvm/llvm-project/pull/125319 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] [DXIL] Implement the `AddUint64` HLSL function and the `UAddc` DXIL op (PR #125319)
https://github.com/Icohedron updated https://github.com/llvm/llvm-project/pull/125319 >From 1e194fdf6dc731276cd867501708b348e3bbc97c Mon Sep 17 00:00:00 2001 From: Icohedron Date: Mon, 27 Jan 2025 11:18:09 -0800 Subject: [PATCH 1/6] Implement AddUint64 HLSL codegen and sema --- clang/include/clang/Basic/Builtins.td | 6 ++ .../clang/Basic/DiagnosticSemaKinds.td| 2 +- clang/lib/CodeGen/CGBuiltin.cpp | 45 clang/lib/Headers/hlsl/hlsl_intrinsics.h | 21 ++ clang/lib/Sema/SemaHLSL.cpp | 49 + .../test/CodeGenHLSL/builtins/AddUint64.hlsl | 71 +++ .../SemaHLSL/BuiltIns/AddUint64-errors.hlsl | 46 7 files changed, 239 insertions(+), 1 deletion(-) create mode 100644 clang/test/CodeGenHLSL/builtins/AddUint64.hlsl create mode 100644 clang/test/SemaHLSL/BuiltIns/AddUint64-errors.hlsl diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 60c360d4a9e0759..ffa60bf98aea06f 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -4753,6 +4753,12 @@ def GetDeviceSideMangledName : LangBuiltin<"CUDA_LANG"> { } // HLSL +def HLSLAddUint64: LangBuiltin<"HLSL_LANG"> { + let Spellings = ["__builtin_hlsl_adduint64"]; + let Attributes = [NoThrow, Const]; + let Prototype = "void(...)"; +} + def HLSLResourceGetPointer : LangBuiltin<"HLSL_LANG"> { let Spellings = ["__builtin_hlsl_resource_getpointer"]; let Attributes = [NoThrow]; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 774e5484cfa0e75..2d7d306a2074179 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -10623,7 +10623,7 @@ def err_second_argument_to_cwsc_not_pointer : Error< "second argument to __builtin_call_with_static_chain must be of pointer type">; def err_vector_incorrect_num_elements : Error< - "%select{too many|too few}0 elements in vector %select{initialization|operand}3 (expected %1 elements, have %2)">; + "%select{too many|too few|incorrect number of}0 elements in vector %select{initialization|operand}3 (expected %1 elements, have %2)">; def err_altivec_empty_initializer : Error<"expected initializer">; def err_invalid_neon_type_code : Error< diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 26bdc5e36e5..3a2c74f39afa78f 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -19105,6 +19105,51 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, return nullptr; switch (BuiltinID) { + case Builtin::BI__builtin_hlsl_adduint64: { +Value *OpA = EmitScalarExpr(E->getArg(0)); +Value *OpB = EmitScalarExpr(E->getArg(1)); +assert(E->getArg(0)->getType()->hasIntegerRepresentation() && + E->getArg(1)->getType()->hasIntegerRepresentation() && + "AddUint64 operands must have an integer representation"); +assert(((E->getArg(0)->getType()->castAs()->getNumElements() == + 2 && + E->getArg(1)->getType()->castAs()->getNumElements() == + 2) || +(E->getArg(0)->getType()->castAs()->getNumElements() == + 4 && + E->getArg(1)->getType()->castAs()->getNumElements() == + 4)) && + "input vectors must have 2 or 4 elements each"); + +llvm::Value *Result = PoisonValue::get(OpA->getType()); +uint64_t NumElements = +E->getArg(0)->getType()->castAs()->getNumElements(); +for (uint64_t i = 0; i < NumElements / 2; ++i) { + + // Obtain low and high words of inputs A and B + llvm::Value *LowA = Builder.CreateExtractElement(OpA, 2 * i + 0); + llvm::Value *HighA = Builder.CreateExtractElement(OpA, 2 * i + 1); + llvm::Value *LowB = Builder.CreateExtractElement(OpB, 2 * i + 0); + llvm::Value *HighB = Builder.CreateExtractElement(OpB, 2 * i + 1); + + // Use an uadd_with_overflow to compute the sum of low words and obtain a + // carry value + llvm::Value *Carry; + llvm::Value *LowSum = EmitOverflowIntrinsic( + *this, llvm::Intrinsic::uadd_with_overflow, LowA, LowB, Carry); + llvm::Value *ZExtCarry = Builder.CreateZExt(Carry, HighA->getType()); + + // Sum the high words and the carry + llvm::Value *HighSum = Builder.CreateAdd(HighA, HighB); + llvm::Value *HighSumPlusCarry = Builder.CreateAdd(HighSum, ZExtCarry); + + // Insert the low and high word sums into the result vector + Result = Builder.CreateInsertElement(Result, LowSum, 2 * i + 0); + Result = Builder.CreateInsertElement(Result, HighSumPlusCarry, 2 * i + 1, + "hlsl.AddUint64"); +} +return Result; + } case Builtin::BI__builtin_hlsl_resource_getpointer: { Value *HandleOp = EmitS
[clang] [llvm] [HLSL] [DXIL] Implement the `AddUint64` HLSL function and the `UAddc` DXIL op (PR #125319)
https://github.com/Icohedron updated https://github.com/llvm/llvm-project/pull/125319 >From 1e194fdf6dc731276cd867501708b348e3bbc97c Mon Sep 17 00:00:00 2001 From: Icohedron Date: Mon, 27 Jan 2025 11:18:09 -0800 Subject: [PATCH 1/6] Implement AddUint64 HLSL codegen and sema --- clang/include/clang/Basic/Builtins.td | 6 ++ .../clang/Basic/DiagnosticSemaKinds.td| 2 +- clang/lib/CodeGen/CGBuiltin.cpp | 45 clang/lib/Headers/hlsl/hlsl_intrinsics.h | 21 ++ clang/lib/Sema/SemaHLSL.cpp | 49 + .../test/CodeGenHLSL/builtins/AddUint64.hlsl | 71 +++ .../SemaHLSL/BuiltIns/AddUint64-errors.hlsl | 46 7 files changed, 239 insertions(+), 1 deletion(-) create mode 100644 clang/test/CodeGenHLSL/builtins/AddUint64.hlsl create mode 100644 clang/test/SemaHLSL/BuiltIns/AddUint64-errors.hlsl diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 60c360d4a9e075..ffa60bf98aea06 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -4753,6 +4753,12 @@ def GetDeviceSideMangledName : LangBuiltin<"CUDA_LANG"> { } // HLSL +def HLSLAddUint64: LangBuiltin<"HLSL_LANG"> { + let Spellings = ["__builtin_hlsl_adduint64"]; + let Attributes = [NoThrow, Const]; + let Prototype = "void(...)"; +} + def HLSLResourceGetPointer : LangBuiltin<"HLSL_LANG"> { let Spellings = ["__builtin_hlsl_resource_getpointer"]; let Attributes = [NoThrow]; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 774e5484cfa0e7..2d7d306a207417 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -10623,7 +10623,7 @@ def err_second_argument_to_cwsc_not_pointer : Error< "second argument to __builtin_call_with_static_chain must be of pointer type">; def err_vector_incorrect_num_elements : Error< - "%select{too many|too few}0 elements in vector %select{initialization|operand}3 (expected %1 elements, have %2)">; + "%select{too many|too few|incorrect number of}0 elements in vector %select{initialization|operand}3 (expected %1 elements, have %2)">; def err_altivec_empty_initializer : Error<"expected initializer">; def err_invalid_neon_type_code : Error< diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 26bdc5e36e..3a2c74f39afa78 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -19105,6 +19105,51 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, return nullptr; switch (BuiltinID) { + case Builtin::BI__builtin_hlsl_adduint64: { +Value *OpA = EmitScalarExpr(E->getArg(0)); +Value *OpB = EmitScalarExpr(E->getArg(1)); +assert(E->getArg(0)->getType()->hasIntegerRepresentation() && + E->getArg(1)->getType()->hasIntegerRepresentation() && + "AddUint64 operands must have an integer representation"); +assert(((E->getArg(0)->getType()->castAs()->getNumElements() == + 2 && + E->getArg(1)->getType()->castAs()->getNumElements() == + 2) || +(E->getArg(0)->getType()->castAs()->getNumElements() == + 4 && + E->getArg(1)->getType()->castAs()->getNumElements() == + 4)) && + "input vectors must have 2 or 4 elements each"); + +llvm::Value *Result = PoisonValue::get(OpA->getType()); +uint64_t NumElements = +E->getArg(0)->getType()->castAs()->getNumElements(); +for (uint64_t i = 0; i < NumElements / 2; ++i) { + + // Obtain low and high words of inputs A and B + llvm::Value *LowA = Builder.CreateExtractElement(OpA, 2 * i + 0); + llvm::Value *HighA = Builder.CreateExtractElement(OpA, 2 * i + 1); + llvm::Value *LowB = Builder.CreateExtractElement(OpB, 2 * i + 0); + llvm::Value *HighB = Builder.CreateExtractElement(OpB, 2 * i + 1); + + // Use an uadd_with_overflow to compute the sum of low words and obtain a + // carry value + llvm::Value *Carry; + llvm::Value *LowSum = EmitOverflowIntrinsic( + *this, llvm::Intrinsic::uadd_with_overflow, LowA, LowB, Carry); + llvm::Value *ZExtCarry = Builder.CreateZExt(Carry, HighA->getType()); + + // Sum the high words and the carry + llvm::Value *HighSum = Builder.CreateAdd(HighA, HighB); + llvm::Value *HighSumPlusCarry = Builder.CreateAdd(HighSum, ZExtCarry); + + // Insert the low and high word sums into the result vector + Result = Builder.CreateInsertElement(Result, LowSum, 2 * i + 0); + Result = Builder.CreateInsertElement(Result, HighSumPlusCarry, 2 * i + 1, + "hlsl.AddUint64"); +} +return Result; + } case Builtin::BI__builtin_hlsl_resource_getpointer: { Value *HandleOp = EmitScalarE
[clang] [llvm] [HLSL] [DXIL] Implement the `AddUint64` HLSL function and the `UAddc` DXIL op (PR #125319)
https://github.com/Icohedron updated https://github.com/llvm/llvm-project/pull/125319 >From 1e194fdf6dc731276cd867501708b348e3bbc97c Mon Sep 17 00:00:00 2001 From: Icohedron Date: Mon, 27 Jan 2025 11:18:09 -0800 Subject: [PATCH 1/8] Implement AddUint64 HLSL codegen and sema --- clang/include/clang/Basic/Builtins.td | 6 ++ .../clang/Basic/DiagnosticSemaKinds.td| 2 +- clang/lib/CodeGen/CGBuiltin.cpp | 45 clang/lib/Headers/hlsl/hlsl_intrinsics.h | 21 ++ clang/lib/Sema/SemaHLSL.cpp | 49 + .../test/CodeGenHLSL/builtins/AddUint64.hlsl | 71 +++ .../SemaHLSL/BuiltIns/AddUint64-errors.hlsl | 46 7 files changed, 239 insertions(+), 1 deletion(-) create mode 100644 clang/test/CodeGenHLSL/builtins/AddUint64.hlsl create mode 100644 clang/test/SemaHLSL/BuiltIns/AddUint64-errors.hlsl diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 60c360d4a9e0759..ffa60bf98aea06f 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -4753,6 +4753,12 @@ def GetDeviceSideMangledName : LangBuiltin<"CUDA_LANG"> { } // HLSL +def HLSLAddUint64: LangBuiltin<"HLSL_LANG"> { + let Spellings = ["__builtin_hlsl_adduint64"]; + let Attributes = [NoThrow, Const]; + let Prototype = "void(...)"; +} + def HLSLResourceGetPointer : LangBuiltin<"HLSL_LANG"> { let Spellings = ["__builtin_hlsl_resource_getpointer"]; let Attributes = [NoThrow]; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 774e5484cfa0e75..2d7d306a2074179 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -10623,7 +10623,7 @@ def err_second_argument_to_cwsc_not_pointer : Error< "second argument to __builtin_call_with_static_chain must be of pointer type">; def err_vector_incorrect_num_elements : Error< - "%select{too many|too few}0 elements in vector %select{initialization|operand}3 (expected %1 elements, have %2)">; + "%select{too many|too few|incorrect number of}0 elements in vector %select{initialization|operand}3 (expected %1 elements, have %2)">; def err_altivec_empty_initializer : Error<"expected initializer">; def err_invalid_neon_type_code : Error< diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 26bdc5e36e5..3a2c74f39afa78f 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -19105,6 +19105,51 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, return nullptr; switch (BuiltinID) { + case Builtin::BI__builtin_hlsl_adduint64: { +Value *OpA = EmitScalarExpr(E->getArg(0)); +Value *OpB = EmitScalarExpr(E->getArg(1)); +assert(E->getArg(0)->getType()->hasIntegerRepresentation() && + E->getArg(1)->getType()->hasIntegerRepresentation() && + "AddUint64 operands must have an integer representation"); +assert(((E->getArg(0)->getType()->castAs()->getNumElements() == + 2 && + E->getArg(1)->getType()->castAs()->getNumElements() == + 2) || +(E->getArg(0)->getType()->castAs()->getNumElements() == + 4 && + E->getArg(1)->getType()->castAs()->getNumElements() == + 4)) && + "input vectors must have 2 or 4 elements each"); + +llvm::Value *Result = PoisonValue::get(OpA->getType()); +uint64_t NumElements = +E->getArg(0)->getType()->castAs()->getNumElements(); +for (uint64_t i = 0; i < NumElements / 2; ++i) { + + // Obtain low and high words of inputs A and B + llvm::Value *LowA = Builder.CreateExtractElement(OpA, 2 * i + 0); + llvm::Value *HighA = Builder.CreateExtractElement(OpA, 2 * i + 1); + llvm::Value *LowB = Builder.CreateExtractElement(OpB, 2 * i + 0); + llvm::Value *HighB = Builder.CreateExtractElement(OpB, 2 * i + 1); + + // Use an uadd_with_overflow to compute the sum of low words and obtain a + // carry value + llvm::Value *Carry; + llvm::Value *LowSum = EmitOverflowIntrinsic( + *this, llvm::Intrinsic::uadd_with_overflow, LowA, LowB, Carry); + llvm::Value *ZExtCarry = Builder.CreateZExt(Carry, HighA->getType()); + + // Sum the high words and the carry + llvm::Value *HighSum = Builder.CreateAdd(HighA, HighB); + llvm::Value *HighSumPlusCarry = Builder.CreateAdd(HighSum, ZExtCarry); + + // Insert the low and high word sums into the result vector + Result = Builder.CreateInsertElement(Result, LowSum, 2 * i + 0); + Result = Builder.CreateInsertElement(Result, HighSumPlusCarry, 2 * i + 1, + "hlsl.AddUint64"); +} +return Result; + } case Builtin::BI__builtin_hlsl_resource_getpointer: { Value *HandleOp = EmitS
[clang] [llvm] [HLSL] [DXIL] Implement the `AddUint64` HLSL function and the `UAddc` DXIL op (PR #125319)
@@ -12553,6 +12553,8 @@ def err_std_initializer_list_malformed : Error< "%0 layout not recognized. Must be a non-polymorphic class type with no bases and two fields: a 'const E *' and either another 'const E *' or a 'std::size_t'">; // HLSL Diagnostics +def err_hlsl_adduint64_invalid_arguments: Error< Icohedron wrote: I pushed a new commit ([eac0fe5](https://github.com/llvm/llvm-project/pull/125319/commits/eac0fe53c4a306886256ea52b308b3e842572170)). The case of a scalar being passed as an argument is now back to using `err_vec_builtin_non_vector` to emit an example error message of: `all arguments to AddUint64 must be vectors` The case of a `uint3` being passed as an argument is now using a new diag called `err_invalid_even_odd_vector_element_count` which emits an example error message of: `invalid element count of 3 in vector operand (expected an even element count in the range of 2 and 4)`. I omitted the expected type from the error message, because passing in an invalid type would hit a separate error handler anyways. (The error would be `passing 'int3' (aka 'vector') to parameter of incompatible type '__attribute__((__vector_size__(3 * sizeof(unsigned int unsigned int' (vector of 3 'unsigned int' values)` https://github.com/llvm/llvm-project/pull/125319 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] Reland "[HLSL] Implement the reflect HLSL function" (PR #125599)
https://github.com/Icohedron updated https://github.com/llvm/llvm-project/pull/125599 >From dc616212f496098776d30f56151213d530917ba2 Mon Sep 17 00:00:00 2001 From: Icohedron Date: Mon, 3 Feb 2025 23:10:16 + Subject: [PATCH 1/2] Reapply "Reland "[HLSL] Implement the `reflect` HLSL function"" (#124046) This reverts commit 0fe8e70c6609ff86cd40fbb45a85a8ed04c153c2. --- clang/include/clang/Basic/BuiltinsSPIRV.td| 6 + clang/lib/CodeGen/CGBuiltin.cpp | 13 ++ clang/lib/Headers/hlsl/hlsl_detail.h | 16 ++ clang/lib/Headers/hlsl/hlsl_intrinsics.h | 43 + clang/lib/Sema/SemaSPIRV.cpp | 32 clang/test/CodeGenHLSL/builtins/reflect.hlsl | 177 ++ clang/test/CodeGenSPIRV/Builtins/reflect.c| 32 .../SemaHLSL/BuiltIns/reflect-errors.hlsl | 33 .../test/SemaSPIRV/BuiltIns/reflect-errors.c | 23 +++ llvm/include/llvm/IR/IntrinsicsSPIRV.td | 1 + .../Target/SPIRV/SPIRVInstructionSelector.cpp | 16 +- .../CodeGen/SPIRV/hlsl-intrinsics/reflect.ll | 33 .../CodeGen/SPIRV/opencl/reflect-error.ll | 13 ++ 13 files changed, 434 insertions(+), 4 deletions(-) create mode 100644 clang/test/CodeGenHLSL/builtins/reflect.hlsl create mode 100644 clang/test/CodeGenSPIRV/Builtins/reflect.c create mode 100644 clang/test/SemaHLSL/BuiltIns/reflect-errors.hlsl create mode 100644 clang/test/SemaSPIRV/BuiltIns/reflect-errors.c create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/reflect.ll create mode 100644 llvm/test/CodeGen/SPIRV/opencl/reflect-error.ll diff --git a/clang/include/clang/Basic/BuiltinsSPIRV.td b/clang/include/clang/Basic/BuiltinsSPIRV.td index f72c555921dfe68..34933e889ba314b 100644 --- a/clang/include/clang/Basic/BuiltinsSPIRV.td +++ b/clang/include/clang/Basic/BuiltinsSPIRV.td @@ -19,3 +19,9 @@ def SPIRVLength : Builtin { let Attributes = [NoThrow, Const]; let Prototype = "void(...)"; } + +def SPIRVReflect : Builtin { + let Spellings = ["__builtin_spirv_reflect"]; + let Attributes = [NoThrow, Const]; + let Prototype = "void(...)"; +} diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 361e4c4bf2e2edb..509784888b445b1 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -20790,6 +20790,19 @@ Value *CodeGenFunction::EmitSPIRVBuiltinExpr(unsigned BuiltinID, /*ReturnType=*/X->getType()->getScalarType(), Intrinsic::spv_length, ArrayRef{X}, nullptr, "spv.length"); } + case SPIRV::BI__builtin_spirv_reflect: { +Value *I = EmitScalarExpr(E->getArg(0)); +Value *N = EmitScalarExpr(E->getArg(1)); +assert(E->getArg(0)->getType()->hasFloatingRepresentation() && + E->getArg(1)->getType()->hasFloatingRepresentation() && + "Reflect operands must have a float representation"); +assert(E->getArg(0)->getType()->isVectorType() && + E->getArg(1)->getType()->isVectorType() && + "Reflect operands must be a vector"); +return Builder.CreateIntrinsic( +/*ReturnType=*/I->getType(), Intrinsic::spv_reflect, +ArrayRef{I, N}, nullptr, "spv.reflect"); + } } return nullptr; } diff --git a/clang/lib/Headers/hlsl/hlsl_detail.h b/clang/lib/Headers/hlsl/hlsl_detail.h index b2c8cc6c5c3dbb0..0d568539cd66a85 100644 --- a/clang/lib/Headers/hlsl/hlsl_detail.h +++ b/clang/lib/Headers/hlsl/hlsl_detail.h @@ -79,6 +79,22 @@ constexpr enable_if_t::value || is_same::value, T> distance_vec_impl(vector X, vector Y) { return length_vec_impl(X - Y); } + +template +constexpr enable_if_t::value || is_same::value, T> +reflect_impl(T I, T N) { + return I - 2 * N * I * N; +} + +template +constexpr vector reflect_vec_impl(vector I, vector N) { +#if (__has_builtin(__builtin_spirv_reflect)) + return __builtin_spirv_reflect(I, N); +#else + return I - 2 * N * __builtin_hlsl_dot(I, N); +#endif +} + } // namespace __detail } // namespace hlsl #endif //_HLSL_HLSL_DETAILS_H_ diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index d1f5fdff8b6008d..4e416ffc0e1e36a 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -2008,6 +2008,49 @@ double3 rcp(double3); _HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_rcp) double4 rcp(double4); +//===--===// +// reflect builtin +//===--===// + +/// \fn T reflect(T I, T N) +/// \brief Returns a reflection using an incident ray, \a I, and a surface +/// normal, \a N. +/// \param I The incident ray. +/// \param N The surface normal. +/// +/// The return value is a floating-point vector that represents the reflection +/// of the incident ray, \a I, off a surface with the normal \a N. +/// +/// This function calculates the reflection vector using the following formula: +/// V = I - 2 * N
[clang] [llvm] Reland "[HLSL] Implement the reflect HLSL function" (PR #125599)
https://github.com/Icohedron edited https://github.com/llvm/llvm-project/pull/125599 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] [DXIL] Implement the `AddUint64` HLSL function and the `UAddc` DXIL op (PR #125319)
https://github.com/Icohedron edited https://github.com/llvm/llvm-project/pull/125319 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] [DXIL] Implement the `AddUint64` HLSL function and the `UAddc` DXIL op (PR #125319)
@@ -0,0 +1,40 @@ +; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s + +; CHECK: %dx.types.i32c = type { i32, i1 } Icohedron wrote: Perhaps I made the incorrect assumption that UAddc only accepts scalars. In the current implementation, UAddc is only used with scalar i32 arguments because the codegen for AddUint64 only uses the scalar version of the uadd_with_overflow llvm intrinsic. The only case where the resulting front-end IR, DXIL, and SPIR-V will differ from the current implementation is when `AddUint64` receives `uint4` arguments. With the current version of the PR, I can do a successful end-to-end compilation of of the [`AddUint64.hlsl` test](https://github.com/llvm/llvm-project/blob/55f764e23e8b14328192ed05b3d8429f70b22277/clang/test/CodeGenHLSL/builtins/AddUint64.hlsl) (which uses uint2 and uint4 vectors) using the command: `build/bin/clang -cc1 -finclude-default-header -triple dxil-pc-shadermodel6.3-library clang/test/CodeGenHLSL/builtins/AddUint64.hlsl -emit-llvm -o - | build/bin/opt -S -scalarizer -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library -o -`. This works because the vector is already scalarized in the clang/front-end codegen. I will work on reimplementing AddUint64 for the uint4 case by using vectors, and make UAddc scalarizable. https://github.com/llvm/llvm-project/pull/125319 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] Reland "[HLSL] Implement the reflect HLSL function" (PR #125599)
https://github.com/Icohedron ready_for_review https://github.com/llvm/llvm-project/pull/125599 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] Reland "[HLSL] Implement the reflect HLSL function" (PR #125599)
Icohedron wrote: To get the PR up and running, I am just marking hwasan as unsupported for now. A proper fix will be implemented later. The Issue #124045 will remain open to track this. https://github.com/llvm/llvm-project/pull/125599 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] [DXIL] Implement the `AddUint64` HLSL function and the `UAddc` DXIL op (PR #125319)
https://github.com/Icohedron created https://github.com/llvm/llvm-project/pull/125319 This PR addresses #99205 - Implements the HLSL intrinsic `AddUint64` used to perform unsigned 64-bit integer addition by using pairs of unsigned 32-bit integers instead of native 64-bit types - The LLVM intrinsic `uadd_with_overflow` is used in the implementation of `AddUint64` in `CGBuiltin.cpp` - The DXIL op `UAddc` was defined in `DXIL.td`, and a lowering of the LLVM intrinsic `uadd_with_overflow` to the `UAddc` DXIL op was implemented in `DXILOpLowering.cpp` Notes: - `__builtin_addc` was not able to be used to implement `AddUint64` in `hlsl_intrinsics.h` because its `CarryOut` argument is a pointer, and pointers are not supported in HLSL - A lowering of the LLVM intrinsic `uadd_with_overflow` to SPIR-V [already exists](https://github.com/llvm/llvm-project/blob/main/llvm/test/CodeGen/SPIRV/llvm-intrinsics/uadd.with.overflow.ll) - When lowering the LLVM intrinsic `uadd_with_overflow` to the `UAddc` DXIL op, the anonymous struct type `{ i32, i1 }` is replaced with a named struct type `%dx.types.i32c`. This aspect of the implementation may be changed when issue #113192 gets addressed >From 1e194fdf6dc731276cd867501708b348e3bbc97c Mon Sep 17 00:00:00 2001 From: Icohedron Date: Mon, 27 Jan 2025 11:18:09 -0800 Subject: [PATCH 1/2] Implement AddUint64 HLSL codegen and sema --- clang/include/clang/Basic/Builtins.td | 6 ++ .../clang/Basic/DiagnosticSemaKinds.td| 2 +- clang/lib/CodeGen/CGBuiltin.cpp | 45 clang/lib/Headers/hlsl/hlsl_intrinsics.h | 21 ++ clang/lib/Sema/SemaHLSL.cpp | 49 + .../test/CodeGenHLSL/builtins/AddUint64.hlsl | 71 +++ .../SemaHLSL/BuiltIns/AddUint64-errors.hlsl | 46 7 files changed, 239 insertions(+), 1 deletion(-) create mode 100644 clang/test/CodeGenHLSL/builtins/AddUint64.hlsl create mode 100644 clang/test/SemaHLSL/BuiltIns/AddUint64-errors.hlsl diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 60c360d4a9e075..ffa60bf98aea06 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -4753,6 +4753,12 @@ def GetDeviceSideMangledName : LangBuiltin<"CUDA_LANG"> { } // HLSL +def HLSLAddUint64: LangBuiltin<"HLSL_LANG"> { + let Spellings = ["__builtin_hlsl_adduint64"]; + let Attributes = [NoThrow, Const]; + let Prototype = "void(...)"; +} + def HLSLResourceGetPointer : LangBuiltin<"HLSL_LANG"> { let Spellings = ["__builtin_hlsl_resource_getpointer"]; let Attributes = [NoThrow]; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 774e5484cfa0e7..2d7d306a207417 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -10623,7 +10623,7 @@ def err_second_argument_to_cwsc_not_pointer : Error< "second argument to __builtin_call_with_static_chain must be of pointer type">; def err_vector_incorrect_num_elements : Error< - "%select{too many|too few}0 elements in vector %select{initialization|operand}3 (expected %1 elements, have %2)">; + "%select{too many|too few|incorrect number of}0 elements in vector %select{initialization|operand}3 (expected %1 elements, have %2)">; def err_altivec_empty_initializer : Error<"expected initializer">; def err_invalid_neon_type_code : Error< diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 26bdc5e36e..3a2c74f39afa78 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -19105,6 +19105,51 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, return nullptr; switch (BuiltinID) { + case Builtin::BI__builtin_hlsl_adduint64: { +Value *OpA = EmitScalarExpr(E->getArg(0)); +Value *OpB = EmitScalarExpr(E->getArg(1)); +assert(E->getArg(0)->getType()->hasIntegerRepresentation() && + E->getArg(1)->getType()->hasIntegerRepresentation() && + "AddUint64 operands must have an integer representation"); +assert(((E->getArg(0)->getType()->castAs()->getNumElements() == + 2 && + E->getArg(1)->getType()->castAs()->getNumElements() == + 2) || +(E->getArg(0)->getType()->castAs()->getNumElements() == + 4 && + E->getArg(1)->getType()->castAs()->getNumElements() == + 4)) && + "input vectors must have 2 or 4 elements each"); + +llvm::Value *Result = PoisonValue::get(OpA->getType()); +uint64_t NumElements = +E->getArg(0)->getType()->castAs()->getNumElements(); +for (uint64_t i = 0; i < NumElements / 2; ++i) { + + // Obtain low and high words of inputs A and B + llvm::Value *LowA = Builder.CreateExtractElement(OpA, 2 * i + 0); + llvm::Value *HighA = Bui
[clang] [llvm] [HLSL] [DXIL] Implement the `AddUint64` HLSL function and the `UAddc` DXIL op (PR #125319)
https://github.com/Icohedron updated https://github.com/llvm/llvm-project/pull/125319 >From 1e194fdf6dc731276cd867501708b348e3bbc97c Mon Sep 17 00:00:00 2001 From: Icohedron Date: Mon, 27 Jan 2025 11:18:09 -0800 Subject: [PATCH 1/3] Implement AddUint64 HLSL codegen and sema --- clang/include/clang/Basic/Builtins.td | 6 ++ .../clang/Basic/DiagnosticSemaKinds.td| 2 +- clang/lib/CodeGen/CGBuiltin.cpp | 45 clang/lib/Headers/hlsl/hlsl_intrinsics.h | 21 ++ clang/lib/Sema/SemaHLSL.cpp | 49 + .../test/CodeGenHLSL/builtins/AddUint64.hlsl | 71 +++ .../SemaHLSL/BuiltIns/AddUint64-errors.hlsl | 46 7 files changed, 239 insertions(+), 1 deletion(-) create mode 100644 clang/test/CodeGenHLSL/builtins/AddUint64.hlsl create mode 100644 clang/test/SemaHLSL/BuiltIns/AddUint64-errors.hlsl diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 60c360d4a9e075..ffa60bf98aea06 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -4753,6 +4753,12 @@ def GetDeviceSideMangledName : LangBuiltin<"CUDA_LANG"> { } // HLSL +def HLSLAddUint64: LangBuiltin<"HLSL_LANG"> { + let Spellings = ["__builtin_hlsl_adduint64"]; + let Attributes = [NoThrow, Const]; + let Prototype = "void(...)"; +} + def HLSLResourceGetPointer : LangBuiltin<"HLSL_LANG"> { let Spellings = ["__builtin_hlsl_resource_getpointer"]; let Attributes = [NoThrow]; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 774e5484cfa0e7..2d7d306a207417 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -10623,7 +10623,7 @@ def err_second_argument_to_cwsc_not_pointer : Error< "second argument to __builtin_call_with_static_chain must be of pointer type">; def err_vector_incorrect_num_elements : Error< - "%select{too many|too few}0 elements in vector %select{initialization|operand}3 (expected %1 elements, have %2)">; + "%select{too many|too few|incorrect number of}0 elements in vector %select{initialization|operand}3 (expected %1 elements, have %2)">; def err_altivec_empty_initializer : Error<"expected initializer">; def err_invalid_neon_type_code : Error< diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 26bdc5e36e..3a2c74f39afa78 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -19105,6 +19105,51 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, return nullptr; switch (BuiltinID) { + case Builtin::BI__builtin_hlsl_adduint64: { +Value *OpA = EmitScalarExpr(E->getArg(0)); +Value *OpB = EmitScalarExpr(E->getArg(1)); +assert(E->getArg(0)->getType()->hasIntegerRepresentation() && + E->getArg(1)->getType()->hasIntegerRepresentation() && + "AddUint64 operands must have an integer representation"); +assert(((E->getArg(0)->getType()->castAs()->getNumElements() == + 2 && + E->getArg(1)->getType()->castAs()->getNumElements() == + 2) || +(E->getArg(0)->getType()->castAs()->getNumElements() == + 4 && + E->getArg(1)->getType()->castAs()->getNumElements() == + 4)) && + "input vectors must have 2 or 4 elements each"); + +llvm::Value *Result = PoisonValue::get(OpA->getType()); +uint64_t NumElements = +E->getArg(0)->getType()->castAs()->getNumElements(); +for (uint64_t i = 0; i < NumElements / 2; ++i) { + + // Obtain low and high words of inputs A and B + llvm::Value *LowA = Builder.CreateExtractElement(OpA, 2 * i + 0); + llvm::Value *HighA = Builder.CreateExtractElement(OpA, 2 * i + 1); + llvm::Value *LowB = Builder.CreateExtractElement(OpB, 2 * i + 0); + llvm::Value *HighB = Builder.CreateExtractElement(OpB, 2 * i + 1); + + // Use an uadd_with_overflow to compute the sum of low words and obtain a + // carry value + llvm::Value *Carry; + llvm::Value *LowSum = EmitOverflowIntrinsic( + *this, llvm::Intrinsic::uadd_with_overflow, LowA, LowB, Carry); + llvm::Value *ZExtCarry = Builder.CreateZExt(Carry, HighA->getType()); + + // Sum the high words and the carry + llvm::Value *HighSum = Builder.CreateAdd(HighA, HighB); + llvm::Value *HighSumPlusCarry = Builder.CreateAdd(HighSum, ZExtCarry); + + // Insert the low and high word sums into the result vector + Result = Builder.CreateInsertElement(Result, LowSum, 2 * i + 0); + Result = Builder.CreateInsertElement(Result, HighSumPlusCarry, 2 * i + 1, + "hlsl.AddUint64"); +} +return Result; + } case Builtin::BI__builtin_hlsl_resource_getpointer: { Value *HandleOp = EmitScalarE
[clang] [HLSL] Implement D3DCOLORtoUBYTE4 intrinsic (PR #122202)
https://github.com/Icohedron updated https://github.com/llvm/llvm-project/pull/122202 >From 07112471edfc569eb12b2a6178ddc28b4f3a36d5 Mon Sep 17 00:00:00 2001 From: Icohedron Date: Thu, 9 Jan 2025 01:14:52 + Subject: [PATCH 1/5] Implement D3DCOLORtoUBYTE4 intrinsic --- clang/lib/Headers/hlsl/hlsl_detail.h| 8 clang/lib/Headers/hlsl/hlsl_intrinsics.h| 17 + .../CodeGenHLSL/builtins/D3DCOLORtoUBYTE4.hlsl | 12 .../BuiltIns/D3DCOLORtoUBYTE4-errors.hlsl | 13 + 4 files changed, 50 insertions(+) create mode 100644 clang/test/CodeGenHLSL/builtins/D3DCOLORtoUBYTE4.hlsl create mode 100644 clang/test/SemaHLSL/BuiltIns/D3DCOLORtoUBYTE4-errors.hlsl diff --git a/clang/lib/Headers/hlsl/hlsl_detail.h b/clang/lib/Headers/hlsl/hlsl_detail.h index 8d5fd941331531..470fa4214a12f8 100644 --- a/clang/lib/Headers/hlsl/hlsl_detail.h +++ b/clang/lib/Headers/hlsl/hlsl_detail.h @@ -33,6 +33,14 @@ constexpr enable_if_t bit_cast(T F) { return __builtin_bit_cast(U, F); } +constexpr vector d3d_color_to_ubyte4(vector V) { + // Use the same scaling factor used by FXC (i.e., 255.001953) + // Excerpt from stackoverflow discussion: + // "Built-in rounding, necessary because of truncation. 0.001953 * 256 = 0.5" + // https://stackoverflow.com/questions/52103720/why-does-d3dcolortoubyte4-multiplies-components-by-255-001953f + return V.zyxw * 255.001953f; +} + } // namespace __detail } // namespace hlsl #endif //_HLSL_HLSL_DETAILS_H_ diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index b745997f1d5a2b..e44403c6c802e0 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -1857,6 +1857,23 @@ half3 cross(half3, half3); _HLSL_BUILTIN_ALIAS(__builtin_hlsl_cross) float3 cross(float3, float3); +//===--===// +// D3DCOLORtoUBYTE4 builtins +//===--===// + +/// \fn T D3DCOLORtoUBYTE4(T x) +/// \brief Converts a floating-point, 4D vector set by a D3DCOLOR to a UBYTE4. +/// \param x [in] The floating-point vector4 to convert. +/// +/// The return value is the UBYTE4 representation of the \a x parameter. +/// +/// This function swizzles and scales components of the \a x parameter. Use this +/// function to compensate for the lack of UBYTE4 support in some hardware. + +constexpr vector D3DCOLORtoUBYTE4(vector V) { + return __detail::d3d_color_to_ubyte4(V); +} + //===--===// // rcp builtins //===--===// diff --git a/clang/test/CodeGenHLSL/builtins/D3DCOLORtoUBYTE4.hlsl b/clang/test/CodeGenHLSL/builtins/D3DCOLORtoUBYTE4.hlsl new file mode 100644 index 00..6e48800dae6698 --- /dev/null +++ b/clang/test/CodeGenHLSL/builtins/D3DCOLORtoUBYTE4.hlsl @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -finclude-default-header -triple \ +// RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \ +// RUN: -emit-llvm -O1 -o - | FileCheck %s --check-prefixes=CHECK + +// CHECK-LABEL: D3DCOLORtoUBYTE4 +int4 test_D3DCOLORtoUBYTE4 ( float4 p1 ) { + // CHECK: %[[SCALED:.*]] = fmul <4 x float> %{{.*}}, splat (float 0x406FE010) + // CHECK: %[[CONVERTED:.*]] = fptoui <4 x float> %[[SCALED]] to <4 x i32> + // CHECK: %[[SHUFFLED:.*]] = shufflevector <4 x i32> %{{.*}}, <4 x i32> poison, <4 x i32> + // CHECK: ret <4 x i32> %[[SHUFFLED]] + return D3DCOLORtoUBYTE4 ( p1 ); +} diff --git a/clang/test/SemaHLSL/BuiltIns/D3DCOLORtoUBYTE4-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/D3DCOLORtoUBYTE4-errors.hlsl new file mode 100644 index 00..fb41c212bd0be3 --- /dev/null +++ b/clang/test/SemaHLSL/BuiltIns/D3DCOLORtoUBYTE4-errors.hlsl @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -emit-llvm-only -disable-llvm-passes -verify + +int4 test_too_few_arg() { + return D3DCOLORtoUBYTE4(); + // expected-error@-1 {{no matching function for call to 'D3DCOLORtoUBYTE4'}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function not viable: requires single argument 'V', but no arguments were provided}} +} + +int4 test_too_many_arg(float4 v) { + return D3DCOLORtoUBYTE4(v, v); + // expected-error@-1 {{no matching function for call to 'D3DCOLORtoUBYTE4'}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function not viable: requires single argument 'V', but 2 arguments were provided}} +} >From d8632ec0526536afb5ce9c3d242079be777c15c0 Mon Sep 17 00:00:00 2001 From: Icohedron Date: Thu, 9 Jan 2025 17:30:45 + Subject: [PATCH 2/5] Add additional sema tests for D3DCOLORtoUBYTE4 for invalid arg types --- .../BuiltIns/D3DCOLORtoUBYTE4-errors.hlsl| 16 1 file changed, 16 insertions(+) diff --
[clang] [HLSL] Implement D3DCOLORtoUBYTE4 intrinsic (PR #122202)
https://github.com/Icohedron updated https://github.com/llvm/llvm-project/pull/122202 >From 5610b225e76b046e911c1a7a0c1e4ccc128d35a1 Mon Sep 17 00:00:00 2001 From: Icohedron Date: Thu, 9 Jan 2025 01:14:52 + Subject: [PATCH] [HLSL] Implement the D3DCOLORtoUBYTE4 intrinsic --- clang/lib/Headers/hlsl/hlsl_detail.h | 8 + clang/lib/Headers/hlsl/hlsl_intrinsics.h | 17 +++ .../builtins/D3DCOLORtoUBYTE4.hlsl| 12 .../BuiltIns/D3DCOLORtoUBYTE4-errors.hlsl | 29 +++ 4 files changed, 66 insertions(+) create mode 100644 clang/test/CodeGenHLSL/builtins/D3DCOLORtoUBYTE4.hlsl create mode 100644 clang/test/SemaHLSL/BuiltIns/D3DCOLORtoUBYTE4-errors.hlsl diff --git a/clang/lib/Headers/hlsl/hlsl_detail.h b/clang/lib/Headers/hlsl/hlsl_detail.h index 8d5fd941331531..470fa4214a12f8 100644 --- a/clang/lib/Headers/hlsl/hlsl_detail.h +++ b/clang/lib/Headers/hlsl/hlsl_detail.h @@ -33,6 +33,14 @@ constexpr enable_if_t bit_cast(T F) { return __builtin_bit_cast(U, F); } +constexpr vector d3d_color_to_ubyte4(vector V) { + // Use the same scaling factor used by FXC (i.e., 255.001953) + // Excerpt from stackoverflow discussion: + // "Built-in rounding, necessary because of truncation. 0.001953 * 256 = 0.5" + // https://stackoverflow.com/questions/52103720/why-does-d3dcolortoubyte4-multiplies-components-by-255-001953f + return V.zyxw * 255.001953f; +} + } // namespace __detail } // namespace hlsl #endif //_HLSL_HLSL_DETAILS_H_ diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index b745997f1d5a2b..e44403c6c802e0 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -1857,6 +1857,23 @@ half3 cross(half3, half3); _HLSL_BUILTIN_ALIAS(__builtin_hlsl_cross) float3 cross(float3, float3); +//===--===// +// D3DCOLORtoUBYTE4 builtins +//===--===// + +/// \fn T D3DCOLORtoUBYTE4(T x) +/// \brief Converts a floating-point, 4D vector set by a D3DCOLOR to a UBYTE4. +/// \param x [in] The floating-point vector4 to convert. +/// +/// The return value is the UBYTE4 representation of the \a x parameter. +/// +/// This function swizzles and scales components of the \a x parameter. Use this +/// function to compensate for the lack of UBYTE4 support in some hardware. + +constexpr vector D3DCOLORtoUBYTE4(vector V) { + return __detail::d3d_color_to_ubyte4(V); +} + //===--===// // rcp builtins //===--===// diff --git a/clang/test/CodeGenHLSL/builtins/D3DCOLORtoUBYTE4.hlsl b/clang/test/CodeGenHLSL/builtins/D3DCOLORtoUBYTE4.hlsl new file mode 100644 index 00..7021de7192b5e5 --- /dev/null +++ b/clang/test/CodeGenHLSL/builtins/D3DCOLORtoUBYTE4.hlsl @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -finclude-default-header -triple \ +// RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \ +// RUN: -emit-llvm -O1 -o - | FileCheck %s --check-prefixes=CHECK + +// CHECK-LABEL: D3DCOLORtoUBYTE4 +int4 test_D3DCOLORtoUBYTE4(float4 p1) { + // CHECK: %[[SCALED:.*]] = fmul [[FMFLAGS:.*]]<4 x float> %{{.*}}, splat (float 0x406FE010) + // CHECK: %[[CONVERTED:.*]] = fptoui <4 x float> %[[SCALED]] to <4 x i32> + // CHECK: %[[SHUFFLED:.*]] = shufflevector <4 x i32> %{{.*}}, <4 x i32> poison, <4 x i32> + // CHECK: ret <4 x i32> %[[SHUFFLED]] + return D3DCOLORtoUBYTE4(p1); +} diff --git a/clang/test/SemaHLSL/BuiltIns/D3DCOLORtoUBYTE4-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/D3DCOLORtoUBYTE4-errors.hlsl new file mode 100644 index 00..e9ba851007c941 --- /dev/null +++ b/clang/test/SemaHLSL/BuiltIns/D3DCOLORtoUBYTE4-errors.hlsl @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -emit-llvm-only -disable-llvm-passes -verify + +int4 test_too_few_arg() { + return D3DCOLORtoUBYTE4(); + // expected-error@-1 {{no matching function for call to 'D3DCOLORtoUBYTE4'}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function not viable: requires single argument 'V', but no arguments were provided}} +} + +int4 test_too_many_arg(float4 v) { + return D3DCOLORtoUBYTE4(v, v); + // expected-error@-1 {{no matching function for call to 'D3DCOLORtoUBYTE4'}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function not viable: requires single argument 'V', but 2 arguments were provided}} +} + +int4 float2_arg(float2 v) { +return D3DCOLORtoUBYTE4(v); +// expected-error@-1 {{no matching function for call to 'D3DCOLORtoUBYTE4'}} +// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function not viable: no known conversion from 'vector<[...], 2>' to 'vector<[...], 4>' for 1st argument}} +} + +struct S { + flo
[clang] [HLSL] Implement D3DCOLORtoUBYTE4 intrinsic (PR #122202)
https://github.com/Icohedron updated https://github.com/llvm/llvm-project/pull/122202 >From 5610b225e76b046e911c1a7a0c1e4ccc128d35a1 Mon Sep 17 00:00:00 2001 From: Icohedron Date: Thu, 9 Jan 2025 01:14:52 + Subject: [PATCH 1/2] [HLSL] Implement the D3DCOLORtoUBYTE4 intrinsic --- clang/lib/Headers/hlsl/hlsl_detail.h | 8 + clang/lib/Headers/hlsl/hlsl_intrinsics.h | 17 +++ .../builtins/D3DCOLORtoUBYTE4.hlsl| 12 .../BuiltIns/D3DCOLORtoUBYTE4-errors.hlsl | 29 +++ 4 files changed, 66 insertions(+) create mode 100644 clang/test/CodeGenHLSL/builtins/D3DCOLORtoUBYTE4.hlsl create mode 100644 clang/test/SemaHLSL/BuiltIns/D3DCOLORtoUBYTE4-errors.hlsl diff --git a/clang/lib/Headers/hlsl/hlsl_detail.h b/clang/lib/Headers/hlsl/hlsl_detail.h index 8d5fd941331531..470fa4214a12f8 100644 --- a/clang/lib/Headers/hlsl/hlsl_detail.h +++ b/clang/lib/Headers/hlsl/hlsl_detail.h @@ -33,6 +33,14 @@ constexpr enable_if_t bit_cast(T F) { return __builtin_bit_cast(U, F); } +constexpr vector d3d_color_to_ubyte4(vector V) { + // Use the same scaling factor used by FXC (i.e., 255.001953) + // Excerpt from stackoverflow discussion: + // "Built-in rounding, necessary because of truncation. 0.001953 * 256 = 0.5" + // https://stackoverflow.com/questions/52103720/why-does-d3dcolortoubyte4-multiplies-components-by-255-001953f + return V.zyxw * 255.001953f; +} + } // namespace __detail } // namespace hlsl #endif //_HLSL_HLSL_DETAILS_H_ diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index b745997f1d5a2b..e44403c6c802e0 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -1857,6 +1857,23 @@ half3 cross(half3, half3); _HLSL_BUILTIN_ALIAS(__builtin_hlsl_cross) float3 cross(float3, float3); +//===--===// +// D3DCOLORtoUBYTE4 builtins +//===--===// + +/// \fn T D3DCOLORtoUBYTE4(T x) +/// \brief Converts a floating-point, 4D vector set by a D3DCOLOR to a UBYTE4. +/// \param x [in] The floating-point vector4 to convert. +/// +/// The return value is the UBYTE4 representation of the \a x parameter. +/// +/// This function swizzles and scales components of the \a x parameter. Use this +/// function to compensate for the lack of UBYTE4 support in some hardware. + +constexpr vector D3DCOLORtoUBYTE4(vector V) { + return __detail::d3d_color_to_ubyte4(V); +} + //===--===// // rcp builtins //===--===// diff --git a/clang/test/CodeGenHLSL/builtins/D3DCOLORtoUBYTE4.hlsl b/clang/test/CodeGenHLSL/builtins/D3DCOLORtoUBYTE4.hlsl new file mode 100644 index 00..7021de7192b5e5 --- /dev/null +++ b/clang/test/CodeGenHLSL/builtins/D3DCOLORtoUBYTE4.hlsl @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -finclude-default-header -triple \ +// RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \ +// RUN: -emit-llvm -O1 -o - | FileCheck %s --check-prefixes=CHECK + +// CHECK-LABEL: D3DCOLORtoUBYTE4 +int4 test_D3DCOLORtoUBYTE4(float4 p1) { + // CHECK: %[[SCALED:.*]] = fmul [[FMFLAGS:.*]]<4 x float> %{{.*}}, splat (float 0x406FE010) + // CHECK: %[[CONVERTED:.*]] = fptoui <4 x float> %[[SCALED]] to <4 x i32> + // CHECK: %[[SHUFFLED:.*]] = shufflevector <4 x i32> %{{.*}}, <4 x i32> poison, <4 x i32> + // CHECK: ret <4 x i32> %[[SHUFFLED]] + return D3DCOLORtoUBYTE4(p1); +} diff --git a/clang/test/SemaHLSL/BuiltIns/D3DCOLORtoUBYTE4-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/D3DCOLORtoUBYTE4-errors.hlsl new file mode 100644 index 00..e9ba851007c941 --- /dev/null +++ b/clang/test/SemaHLSL/BuiltIns/D3DCOLORtoUBYTE4-errors.hlsl @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -emit-llvm-only -disable-llvm-passes -verify + +int4 test_too_few_arg() { + return D3DCOLORtoUBYTE4(); + // expected-error@-1 {{no matching function for call to 'D3DCOLORtoUBYTE4'}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function not viable: requires single argument 'V', but no arguments were provided}} +} + +int4 test_too_many_arg(float4 v) { + return D3DCOLORtoUBYTE4(v, v); + // expected-error@-1 {{no matching function for call to 'D3DCOLORtoUBYTE4'}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function not viable: requires single argument 'V', but 2 arguments were provided}} +} + +int4 float2_arg(float2 v) { +return D3DCOLORtoUBYTE4(v); +// expected-error@-1 {{no matching function for call to 'D3DCOLORtoUBYTE4'}} +// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function not viable: no known conversion from 'vector<[...], 2>' to 'vector<[...], 4>' for 1st argument}} +} + +struct S { +
[clang] [llvm] [HLSL] Implement the `reflect` HLSL function (PR #122992)
Icohedron wrote: > Will a follow-up issue be created to move the useful Sema helpers into a > common file? I just created issue #123831 for this. https://github.com/llvm/llvm-project/pull/122992 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] Reland "[HLSL] Implement the `reflect` HLSL function" (PR #123853)
https://github.com/Icohedron created https://github.com/llvm/llvm-project/pull/123853 This PR relands [#122992](https://github.com/llvm/llvm-project/pull/122992). Some machines were failing to run the `reflect-error.ll` test due to the RUN lines ```llvm ; RUN: not %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o /dev/null 2>&1 -filetype=obj %} ; RUN: not %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o /dev/null 2>&1 -filetype=obj %} ``` which failed when `spirv-tools` was not present on the machine due to running the command `not` without any arguments. These RUN lines have been removed since they don't actually test anything new compared to the other two RUN lines due to the expected error during instruction selection. ```llvm ; RUN: not llc -verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown %s -o /dev/null 2>&1 | FileCheck %s ; RUN: not llc -verify-machineinstrs -O0 -mtriple=spirv32-unknown-unknown %s -o /dev/null 2>&1 | FileCheck %s ``` >From f9fd109c4038f5646586c70c40bc298c20996d40 Mon Sep 17 00:00:00 2001 From: Icohedron Date: Mon, 13 Jan 2025 21:23:31 + Subject: [PATCH 1/4] Implement the `reflect` HLSL function --- clang/include/clang/Basic/BuiltinsSPIRV.td| 6 + clang/lib/CodeGen/CGBuiltin.cpp | 13 ++ clang/lib/Headers/hlsl/hlsl_detail.h | 16 ++ clang/lib/Headers/hlsl/hlsl_intrinsics.h | 43 + clang/lib/Sema/SemaSPIRV.cpp | 32 clang/test/CodeGenHLSL/builtins/reflect.hlsl | 177 ++ clang/test/CodeGenSPIRV/Builtins/reflect.c| 32 .../SemaHLSL/BuiltIns/reflect-errors.hlsl | 33 .../test/SemaSPIRV/BuiltIns/reflect-errors.c | 23 +++ llvm/include/llvm/IR/IntrinsicsSPIRV.td | 1 + .../Target/SPIRV/SPIRVInstructionSelector.cpp | 12 ++ .../CodeGen/SPIRV/hlsl-intrinsics/reflect.ll | 33 .../CodeGen/SPIRV/opencl/reflect-error.ll | 22 +++ 13 files changed, 443 insertions(+) create mode 100644 clang/test/CodeGenHLSL/builtins/reflect.hlsl create mode 100644 clang/test/CodeGenSPIRV/Builtins/reflect.c create mode 100644 clang/test/SemaHLSL/BuiltIns/reflect-errors.hlsl create mode 100644 clang/test/SemaSPIRV/BuiltIns/reflect-errors.c create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/reflect.ll create mode 100644 llvm/test/CodeGen/SPIRV/opencl/reflect-error.ll diff --git a/clang/include/clang/Basic/BuiltinsSPIRV.td b/clang/include/clang/Basic/BuiltinsSPIRV.td index f72c555921dfe6..34933e889ba314 100644 --- a/clang/include/clang/Basic/BuiltinsSPIRV.td +++ b/clang/include/clang/Basic/BuiltinsSPIRV.td @@ -19,3 +19,9 @@ def SPIRVLength : Builtin { let Attributes = [NoThrow, Const]; let Prototype = "void(...)"; } + +def SPIRVReflect : Builtin { + let Spellings = ["__builtin_spirv_reflect"]; + let Attributes = [NoThrow, Const]; + let Prototype = "void(...)"; +} diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index b80833fd91884d..ab61609ab35a99 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -20538,6 +20538,19 @@ Value *CodeGenFunction::EmitSPIRVBuiltinExpr(unsigned BuiltinID, /*ReturnType=*/X->getType()->getScalarType(), Intrinsic::spv_length, ArrayRef{X}, nullptr, "spv.length"); } + case SPIRV::BI__builtin_spirv_reflect: { +Value *I = EmitScalarExpr(E->getArg(0)); +Value *N = EmitScalarExpr(E->getArg(1)); +assert(E->getArg(0)->getType()->hasFloatingRepresentation() && + E->getArg(1)->getType()->hasFloatingRepresentation() && + "Reflect operands must have a float representation"); +assert(E->getArg(0)->getType()->isVectorType() && + E->getArg(1)->getType()->isVectorType() && + "Reflect operands must be a vector"); +return Builder.CreateIntrinsic( +/*ReturnType=*/I->getType(), Intrinsic::spv_reflect, +ArrayRef{I, N}, nullptr, "spv.reflect"); + } } return nullptr; } diff --git a/clang/lib/Headers/hlsl/hlsl_detail.h b/clang/lib/Headers/hlsl/hlsl_detail.h index b2c8cc6c5c3dbb..0d568539cd66a8 100644 --- a/clang/lib/Headers/hlsl/hlsl_detail.h +++ b/clang/lib/Headers/hlsl/hlsl_detail.h @@ -79,6 +79,22 @@ constexpr enable_if_t::value || is_same::value, T> distance_vec_impl(vector X, vector Y) { return length_vec_impl(X - Y); } + +template +constexpr enable_if_t::value || is_same::value, T> +reflect_impl(T I, T N) { + return I - 2 * N * I * N; +} + +template +constexpr vector reflect_vec_impl(vector I, vector N) { +#if (__has_builtin(__builtin_spirv_reflect)) + return __builtin_spirv_reflect(I, N); +#else + return I - 2 * N * __builtin_hlsl_dot(I, N); +#endif +} + } // namespace __detail } // namespace hlsl #endif //_HLSL_HLSL_DETAILS_H_ diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index d1e4eb08aa7646..3b47074f07ecf4 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++
[clang] [llvm] [HLSL] Implement the `reflect` HLSL function (PR #122992)
@@ -34,6 +34,7 @@ #include "llvm/IR/IntrinsicsSPIRV.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" Icohedron wrote: I don't recall adding that. I think my IDE did that for me :P I will remove it https://github.com/llvm/llvm-project/pull/122992 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Implement the `reflect` HLSL function (PR #122992)
https://github.com/Icohedron updated https://github.com/llvm/llvm-project/pull/122992 >From 7ddd5b264731ef375d99d012d9fbfd54c744e5b2 Mon Sep 17 00:00:00 2001 From: Icohedron Date: Mon, 13 Jan 2025 21:23:31 + Subject: [PATCH 1/5] Implement `reflect` HLSL function --- clang/include/clang/Basic/BuiltinsSPIRV.td| 6 + clang/lib/CodeGen/CGBuiltin.cpp | 13 ++ clang/lib/Headers/hlsl/hlsl_detail.h | 17 ++ clang/lib/Headers/hlsl/hlsl_intrinsics.h | 43 clang/lib/Sema/SemaSPIRV.cpp | 32 +++ clang/test/CodeGenHLSL/builtins/reflect.hlsl | 195 ++ clang/test/CodeGenSPIRV/Builtins/reflect.c| 32 +++ .../SemaHLSL/BuiltIns/reflect-errors.hlsl | 33 +++ .../test/SemaSPIRV/BuiltIns/reflect-errors.c | 23 +++ llvm/include/llvm/IR/IntrinsicsSPIRV.td | 1 + .../Target/SPIRV/SPIRVInstructionSelector.cpp | 2 + .../CodeGen/SPIRV/hlsl-intrinsics/reflect.ll | 33 +++ 12 files changed, 430 insertions(+) create mode 100644 clang/test/CodeGenHLSL/builtins/reflect.hlsl create mode 100644 clang/test/CodeGenSPIRV/Builtins/reflect.c create mode 100644 clang/test/SemaHLSL/BuiltIns/reflect-errors.hlsl create mode 100644 clang/test/SemaSPIRV/BuiltIns/reflect-errors.c create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/reflect.ll diff --git a/clang/include/clang/Basic/BuiltinsSPIRV.td b/clang/include/clang/Basic/BuiltinsSPIRV.td index f72c555921dfe68..34933e889ba314b 100644 --- a/clang/include/clang/Basic/BuiltinsSPIRV.td +++ b/clang/include/clang/Basic/BuiltinsSPIRV.td @@ -19,3 +19,9 @@ def SPIRVLength : Builtin { let Attributes = [NoThrow, Const]; let Prototype = "void(...)"; } + +def SPIRVReflect : Builtin { + let Spellings = ["__builtin_spirv_reflect"]; + let Attributes = [NoThrow, Const]; + let Prototype = "void(...)"; +} diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index b80833fd91884d8..ab61609ab35a99f 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -20538,6 +20538,19 @@ Value *CodeGenFunction::EmitSPIRVBuiltinExpr(unsigned BuiltinID, /*ReturnType=*/X->getType()->getScalarType(), Intrinsic::spv_length, ArrayRef{X}, nullptr, "spv.length"); } + case SPIRV::BI__builtin_spirv_reflect: { +Value *I = EmitScalarExpr(E->getArg(0)); +Value *N = EmitScalarExpr(E->getArg(1)); +assert(E->getArg(0)->getType()->hasFloatingRepresentation() && + E->getArg(1)->getType()->hasFloatingRepresentation() && + "Reflect operands must have a float representation"); +assert(E->getArg(0)->getType()->isVectorType() && + E->getArg(1)->getType()->isVectorType() && + "Reflect operands must be a vector"); +return Builder.CreateIntrinsic( +/*ReturnType=*/I->getType(), Intrinsic::spv_reflect, +ArrayRef{I, N}, nullptr, "spv.reflect"); + } } return nullptr; } diff --git a/clang/lib/Headers/hlsl/hlsl_detail.h b/clang/lib/Headers/hlsl/hlsl_detail.h index b2c8cc6c5c3dbb0..3e09f8b10735122 100644 --- a/clang/lib/Headers/hlsl/hlsl_detail.h +++ b/clang/lib/Headers/hlsl/hlsl_detail.h @@ -79,6 +79,23 @@ constexpr enable_if_t::value || is_same::value, T> distance_vec_impl(vector X, vector Y) { return length_vec_impl(X - Y); } + +template +constexpr enable_if_t::value || is_same::value, T> +reflect_impl(T I, T N) { + return I - 2 * N * I * N; +} + +template +constexpr enable_if_t::value || is_same::value, T> +reflect_vec_impl(vector I, vector N) { +#if (__has_builtin(__builtin_spirv_reflect)) + return __builtin_spirv_reflect(I, N); +#else + return I - 2 * N * __builtin_hlsl_dot(I, N); +#endif +} + } // namespace __detail } // namespace hlsl #endif //_HLSL_HLSL_DETAILS_H_ diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index d1e4eb08aa7646a..54454cf0ea0d0bd 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -2008,6 +2008,49 @@ double3 rcp(double3); _HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_rcp) double4 rcp(double4); +//===--===// +// reflect builtin +//===--===// + +/// \fn T reflect(T I, T N) +/// \brief Returns a reflection using an incident ray, \a I, and a surface +/// normal, \a N. +/// \param I The incident ray. +/// \param N The surface normal. +/// +/// The return value is a floating-point vector that represents the reflection +/// of the incident ray, \a I, off a surface with the normal \a N. +/// +/// This function calculates the reflection vector using the following formula: +/// V = I - 2 * N * dot(I N) . +/// +/// N must already be normalized in order to achieve the desired result. +/// +/// The operands must all be a scalar or vector whose component type is +/// floating-point. +/// +/// Result type
[clang] [llvm] [HLSL] Implement the `reflect` HLSL function (PR #122992)
@@ -3030,6 +3031,15 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg, return selectExtInst(ResVReg, ResType, I, CL::fract, GL::Fract); case Intrinsic::spv_normalize: return selectExtInst(ResVReg, ResType, I, CL::normalize, GL::Normalize); + case Intrinsic::spv_reflect: +if (!STI.canUseExtInstSet(SPIRV::InstructionSet::InstructionSet::GLSL_std_450)) { Icohedron wrote: Should I add a similar conditional to the OpenCL overloaded version of selectExtInst? Just to keep the OpenCL and GLSL functions similar. https://github.com/llvm/llvm-project/pull/122992 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Implement the `reflect` HLSL function (PR #122992)
https://github.com/Icohedron updated https://github.com/llvm/llvm-project/pull/122992 >From f9fd109c4038f5646586c70c40bc298c20996d40 Mon Sep 17 00:00:00 2001 From: Icohedron Date: Mon, 13 Jan 2025 21:23:31 + Subject: [PATCH 1/2] Implement the `reflect` HLSL function --- clang/include/clang/Basic/BuiltinsSPIRV.td| 6 + clang/lib/CodeGen/CGBuiltin.cpp | 13 ++ clang/lib/Headers/hlsl/hlsl_detail.h | 16 ++ clang/lib/Headers/hlsl/hlsl_intrinsics.h | 43 + clang/lib/Sema/SemaSPIRV.cpp | 32 clang/test/CodeGenHLSL/builtins/reflect.hlsl | 177 ++ clang/test/CodeGenSPIRV/Builtins/reflect.c| 32 .../SemaHLSL/BuiltIns/reflect-errors.hlsl | 33 .../test/SemaSPIRV/BuiltIns/reflect-errors.c | 23 +++ llvm/include/llvm/IR/IntrinsicsSPIRV.td | 1 + .../Target/SPIRV/SPIRVInstructionSelector.cpp | 12 ++ .../CodeGen/SPIRV/hlsl-intrinsics/reflect.ll | 33 .../CodeGen/SPIRV/opencl/reflect-error.ll | 22 +++ 13 files changed, 443 insertions(+) create mode 100644 clang/test/CodeGenHLSL/builtins/reflect.hlsl create mode 100644 clang/test/CodeGenSPIRV/Builtins/reflect.c create mode 100644 clang/test/SemaHLSL/BuiltIns/reflect-errors.hlsl create mode 100644 clang/test/SemaSPIRV/BuiltIns/reflect-errors.c create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/reflect.ll create mode 100644 llvm/test/CodeGen/SPIRV/opencl/reflect-error.ll diff --git a/clang/include/clang/Basic/BuiltinsSPIRV.td b/clang/include/clang/Basic/BuiltinsSPIRV.td index f72c555921dfe6..34933e889ba314 100644 --- a/clang/include/clang/Basic/BuiltinsSPIRV.td +++ b/clang/include/clang/Basic/BuiltinsSPIRV.td @@ -19,3 +19,9 @@ def SPIRVLength : Builtin { let Attributes = [NoThrow, Const]; let Prototype = "void(...)"; } + +def SPIRVReflect : Builtin { + let Spellings = ["__builtin_spirv_reflect"]; + let Attributes = [NoThrow, Const]; + let Prototype = "void(...)"; +} diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index b80833fd91884d..ab61609ab35a99 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -20538,6 +20538,19 @@ Value *CodeGenFunction::EmitSPIRVBuiltinExpr(unsigned BuiltinID, /*ReturnType=*/X->getType()->getScalarType(), Intrinsic::spv_length, ArrayRef{X}, nullptr, "spv.length"); } + case SPIRV::BI__builtin_spirv_reflect: { +Value *I = EmitScalarExpr(E->getArg(0)); +Value *N = EmitScalarExpr(E->getArg(1)); +assert(E->getArg(0)->getType()->hasFloatingRepresentation() && + E->getArg(1)->getType()->hasFloatingRepresentation() && + "Reflect operands must have a float representation"); +assert(E->getArg(0)->getType()->isVectorType() && + E->getArg(1)->getType()->isVectorType() && + "Reflect operands must be a vector"); +return Builder.CreateIntrinsic( +/*ReturnType=*/I->getType(), Intrinsic::spv_reflect, +ArrayRef{I, N}, nullptr, "spv.reflect"); + } } return nullptr; } diff --git a/clang/lib/Headers/hlsl/hlsl_detail.h b/clang/lib/Headers/hlsl/hlsl_detail.h index b2c8cc6c5c3dbb..0d568539cd66a8 100644 --- a/clang/lib/Headers/hlsl/hlsl_detail.h +++ b/clang/lib/Headers/hlsl/hlsl_detail.h @@ -79,6 +79,22 @@ constexpr enable_if_t::value || is_same::value, T> distance_vec_impl(vector X, vector Y) { return length_vec_impl(X - Y); } + +template +constexpr enable_if_t::value || is_same::value, T> +reflect_impl(T I, T N) { + return I - 2 * N * I * N; +} + +template +constexpr vector reflect_vec_impl(vector I, vector N) { +#if (__has_builtin(__builtin_spirv_reflect)) + return __builtin_spirv_reflect(I, N); +#else + return I - 2 * N * __builtin_hlsl_dot(I, N); +#endif +} + } // namespace __detail } // namespace hlsl #endif //_HLSL_HLSL_DETAILS_H_ diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index d1e4eb08aa7646..3b47074f07ecf4 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -2008,6 +2008,49 @@ double3 rcp(double3); _HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_rcp) double4 rcp(double4); +//===--===// +// reflect builtin +//===--===// + +/// \fn T reflect(T I, T N) +/// \brief Returns a reflection using an incident ray, \a I, and a surface +/// normal, \a N. +/// \param I The incident ray. +/// \param N The surface normal. +/// +/// The return value is a floating-point vector that represents the reflection +/// of the incident ray, \a I, off a surface with the normal \a N. +/// +/// This function calculates the reflection vector using the following formula: +/// V = I - 2 * N * dot(I N) . +/// +/// N must already be normalized in order to achieve the desired result. +/// +/// The operands must a
[clang] [llvm] [HLSL] Implement the `reflect` HLSL function (PR #122992)
https://github.com/Icohedron edited https://github.com/llvm/llvm-project/pull/122992 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Implement the `reflect` HLSL function (PR #122992)
@@ -0,0 +1,22 @@ +; RUN: not llc -verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown %s -o /dev/null 2>&1 | FileCheck %s +; RUN: not llc -verify-machineinstrs -O0 -mtriple=spirv32-unknown-unknown %s -o /dev/null 2>&1 | FileCheck %s +; RUN: not %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o /dev/null 2>&1 -filetype=obj %} +; RUN: not %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o /dev/null 2>&1 -filetype=obj %} + +; CHECK: LLVM ERROR: Intrinsic selection not supported for this instruction set: %{{.*}} = G_INTRINSIC intrinsic(@llvm.spv.reflect), %{{.*}}, %{{.*}} Icohedron wrote: I have changed the error message to read `LLVM ERROR: %{{.*}} = G_INTRINSIC intrinsic(@llvm.spv.reflect), %{{.*}}, %{{.*}} is only supported with the GLSL extended instruction set.` https://github.com/llvm/llvm-project/pull/122992 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [HLSL] Implement D3DCOLORtoUBYTE4 intrinsic (PR #122202)
https://github.com/Icohedron updated https://github.com/llvm/llvm-project/pull/122202 >From 5610b225e76b046e911c1a7a0c1e4ccc128d35a1 Mon Sep 17 00:00:00 2001 From: Icohedron Date: Thu, 9 Jan 2025 01:14:52 + Subject: [PATCH 1/3] [HLSL] Implement the D3DCOLORtoUBYTE4 intrinsic --- clang/lib/Headers/hlsl/hlsl_detail.h | 8 + clang/lib/Headers/hlsl/hlsl_intrinsics.h | 17 +++ .../builtins/D3DCOLORtoUBYTE4.hlsl| 12 .../BuiltIns/D3DCOLORtoUBYTE4-errors.hlsl | 29 +++ 4 files changed, 66 insertions(+) create mode 100644 clang/test/CodeGenHLSL/builtins/D3DCOLORtoUBYTE4.hlsl create mode 100644 clang/test/SemaHLSL/BuiltIns/D3DCOLORtoUBYTE4-errors.hlsl diff --git a/clang/lib/Headers/hlsl/hlsl_detail.h b/clang/lib/Headers/hlsl/hlsl_detail.h index 8d5fd941331531..470fa4214a12f8 100644 --- a/clang/lib/Headers/hlsl/hlsl_detail.h +++ b/clang/lib/Headers/hlsl/hlsl_detail.h @@ -33,6 +33,14 @@ constexpr enable_if_t bit_cast(T F) { return __builtin_bit_cast(U, F); } +constexpr vector d3d_color_to_ubyte4(vector V) { + // Use the same scaling factor used by FXC (i.e., 255.001953) + // Excerpt from stackoverflow discussion: + // "Built-in rounding, necessary because of truncation. 0.001953 * 256 = 0.5" + // https://stackoverflow.com/questions/52103720/why-does-d3dcolortoubyte4-multiplies-components-by-255-001953f + return V.zyxw * 255.001953f; +} + } // namespace __detail } // namespace hlsl #endif //_HLSL_HLSL_DETAILS_H_ diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index b745997f1d5a2b..e44403c6c802e0 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -1857,6 +1857,23 @@ half3 cross(half3, half3); _HLSL_BUILTIN_ALIAS(__builtin_hlsl_cross) float3 cross(float3, float3); +//===--===// +// D3DCOLORtoUBYTE4 builtins +//===--===// + +/// \fn T D3DCOLORtoUBYTE4(T x) +/// \brief Converts a floating-point, 4D vector set by a D3DCOLOR to a UBYTE4. +/// \param x [in] The floating-point vector4 to convert. +/// +/// The return value is the UBYTE4 representation of the \a x parameter. +/// +/// This function swizzles and scales components of the \a x parameter. Use this +/// function to compensate for the lack of UBYTE4 support in some hardware. + +constexpr vector D3DCOLORtoUBYTE4(vector V) { + return __detail::d3d_color_to_ubyte4(V); +} + //===--===// // rcp builtins //===--===// diff --git a/clang/test/CodeGenHLSL/builtins/D3DCOLORtoUBYTE4.hlsl b/clang/test/CodeGenHLSL/builtins/D3DCOLORtoUBYTE4.hlsl new file mode 100644 index 00..7021de7192b5e5 --- /dev/null +++ b/clang/test/CodeGenHLSL/builtins/D3DCOLORtoUBYTE4.hlsl @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -finclude-default-header -triple \ +// RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \ +// RUN: -emit-llvm -O1 -o - | FileCheck %s --check-prefixes=CHECK + +// CHECK-LABEL: D3DCOLORtoUBYTE4 +int4 test_D3DCOLORtoUBYTE4(float4 p1) { + // CHECK: %[[SCALED:.*]] = fmul [[FMFLAGS:.*]]<4 x float> %{{.*}}, splat (float 0x406FE010) + // CHECK: %[[CONVERTED:.*]] = fptoui <4 x float> %[[SCALED]] to <4 x i32> + // CHECK: %[[SHUFFLED:.*]] = shufflevector <4 x i32> %{{.*}}, <4 x i32> poison, <4 x i32> + // CHECK: ret <4 x i32> %[[SHUFFLED]] + return D3DCOLORtoUBYTE4(p1); +} diff --git a/clang/test/SemaHLSL/BuiltIns/D3DCOLORtoUBYTE4-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/D3DCOLORtoUBYTE4-errors.hlsl new file mode 100644 index 00..e9ba851007c941 --- /dev/null +++ b/clang/test/SemaHLSL/BuiltIns/D3DCOLORtoUBYTE4-errors.hlsl @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -emit-llvm-only -disable-llvm-passes -verify + +int4 test_too_few_arg() { + return D3DCOLORtoUBYTE4(); + // expected-error@-1 {{no matching function for call to 'D3DCOLORtoUBYTE4'}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function not viable: requires single argument 'V', but no arguments were provided}} +} + +int4 test_too_many_arg(float4 v) { + return D3DCOLORtoUBYTE4(v, v); + // expected-error@-1 {{no matching function for call to 'D3DCOLORtoUBYTE4'}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function not viable: requires single argument 'V', but 2 arguments were provided}} +} + +int4 float2_arg(float2 v) { +return D3DCOLORtoUBYTE4(v); +// expected-error@-1 {{no matching function for call to 'D3DCOLORtoUBYTE4'}} +// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function not viable: no known conversion from 'vector<[...], 2>' to 'vector<[...], 4>' for 1st argument}} +} + +struct S { +
[clang] [HLSL] Implement D3DCOLORtoUBYTE4 intrinsic (PR #122202)
@@ -41,6 +41,14 @@ constexpr enable_if_t bit_cast(T F) { return __builtin_bit_cast(U, F); } +constexpr vector d3d_color_to_ubyte4_impl(vector V) { + // Use the same scaling factor used by FXC (i.e., 255.001953) + // Excerpt from stackoverflow discussion: + // "Built-in rounding, necessary because of truncation. 0.001953 * 256 = 0.5" + // https://stackoverflow.com/questions/52103720/why-does-d3dcolortoubyte4-multiplies-components-by-255-001953f Icohedron wrote: I revised the comment to mention that the scaling factor is the same as FXC and also the DXC DXIL implementation. I also kept the link to the stackoverflow discussion, as the comments in the DXC DXIL implementation referred to it but did not provide a link, which I think is kind of important. Are these new comments more suitable? Or should I just simply just provide a link to the DXC implementation and cut out the repetition? https://github.com/llvm/llvm-project/pull/122202 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Implement the `reflect` HLSL function (PR #122992)
https://github.com/Icohedron edited https://github.com/llvm/llvm-project/pull/122992 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Implement `reflect` HLSL function (PR #122992)
https://github.com/Icohedron created https://github.com/llvm/llvm-project/pull/122992 Fixes #99152 Tasks completed: - Implement `reflect` in `clang/lib/Headers/hlsl/hlsl_intrinsics.h` - Implement the `reflect` SPIR-V target built-in in `clang/include/clang/Basic/BuiltinsSPIRV.td` - Add a SPIR-V fast path in `clang/lib/Headers/hlsl/hlsl_detail.h` in the form ```c++ #if (__has_builtin(__builtin_spirv_reflect)) return __builtin_spirv_reflect(...); #else return ...; // regular behavior #endif ``` - Add codegen for the SPIR-V `reflect` built-in to `EmitSPIRVBuiltinExpr` in `clang/lib/CodeGen/CGBuiltin.cpp` - Add HLSL codegen tests to `clang/test/CodeGenHLSL/builtins/reflect.hlsl` - Add SPIR-V built-in codegen tests to `clang/test/CodeGenSPIRV/Builtins/reflect.c` - Add sema tests to `clang/test/SemaHLSL/BuiltIns/reflect-errors.hlsl` - Add SPIR-V sema tests to `clang/test/CodeGenSPIRV/Builtins/reflect-errors.c` - Create the `int_spv_reflect` intrinsic in `llvm/include/llvm/IR/IntrinsicsSPIRV.td` - In `llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp` create the `reflect` lowering and map it to `int_spv_reflect` in `SPIRVInstructionSelector::selectIntrinsic` - Create a SPIR-V backend test case in `llvm/test/CodeGen/SPIRV/hlsl-intrinsics/reflect.ll` Additional tasks completed: - Implement sema check for the `reflect` SPIR-V built-in in `clang/lib/Sema/SemaSPIRV.cpp` - Required for HLSL codegen to work via the SPIR-V fast path, otherwise the test `clang/test/CodeGenHLSL/builtins/reflect.hlsl` outright fails to compile Incomplete tasks: - Create SPIR-V backend test case in llvm/test/CodeGen/SPIRV/opencl/reflect.ll - I do not think an OpenCL test is applicable in this case because the [OpenCL SPIR-V extended instruction set](https://registry.khronos.org/SPIR-V/specs/unified1/OpenCL.ExtendedInstructionSet.100.html) does not include a `reflect` function >From 3f3b8c75c14bb9b3ed611c9cddec49d0e9339705 Mon Sep 17 00:00:00 2001 From: Icohedron Date: Mon, 13 Jan 2025 21:23:31 + Subject: [PATCH] Implement `reflect` HLSL function --- clang/include/clang/Basic/BuiltinsSPIRV.td| 6 + clang/lib/CodeGen/CGBuiltin.cpp | 13 ++ clang/lib/Headers/hlsl/hlsl_detail.h | 17 ++ clang/lib/Headers/hlsl/hlsl_intrinsics.h | 43 clang/lib/Sema/SemaSPIRV.cpp | 32 +++ clang/test/CodeGenHLSL/builtins/reflect.hlsl | 195 ++ clang/test/CodeGenSPIRV/Builtins/reflect.c| 32 +++ .../SemaHLSL/BuiltIns/reflect-errors.hlsl | 33 +++ .../test/SemaSPIRV/BuiltIns/reflect-errors.c | 23 +++ llvm/include/llvm/IR/IntrinsicsSPIRV.td | 1 + .../Target/SPIRV/SPIRVInstructionSelector.cpp | 2 + .../CodeGen/SPIRV/hlsl-intrinsics/reflect.ll | 33 +++ 12 files changed, 430 insertions(+) create mode 100644 clang/test/CodeGenHLSL/builtins/reflect.hlsl create mode 100644 clang/test/CodeGenSPIRV/Builtins/reflect.c create mode 100644 clang/test/SemaHLSL/BuiltIns/reflect-errors.hlsl create mode 100644 clang/test/SemaSPIRV/BuiltIns/reflect-errors.c create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/reflect.ll diff --git a/clang/include/clang/Basic/BuiltinsSPIRV.td b/clang/include/clang/Basic/BuiltinsSPIRV.td index 1e66939b822ef8..ce00459fc8ede7 100644 --- a/clang/include/clang/Basic/BuiltinsSPIRV.td +++ b/clang/include/clang/Basic/BuiltinsSPIRV.td @@ -13,3 +13,9 @@ def SPIRVDistance : Builtin { let Attributes = [NoThrow, Const]; let Prototype = "void(...)"; } + +def SPIRVReflect : Builtin { + let Spellings = ["__builtin_spirv_reflect"]; + let Attributes = [NoThrow, Const]; + let Prototype = "void(...)"; +} diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 1b25d365932c30..b9e680685b05e0 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -20487,6 +20487,19 @@ Value *CodeGenFunction::EmitSPIRVBuiltinExpr(unsigned BuiltinID, /*ReturnType=*/X->getType()->getScalarType(), Intrinsic::spv_distance, ArrayRef{X, Y}, nullptr, "spv.distance"); } + case SPIRV::BI__builtin_spirv_reflect: { +Value *I = EmitScalarExpr(E->getArg(0)); +Value *N = EmitScalarExpr(E->getArg(1)); +assert(E->getArg(0)->getType()->hasFloatingRepresentation() && + E->getArg(1)->getType()->hasFloatingRepresentation() && + "Reflect operands must have a float representation"); +assert(E->getArg(0)->getType()->isVectorType() && + E->getArg(1)->getType()->isVectorType() && + "Reflect operands must be a vector"); +return Builder.CreateIntrinsic( +/*ReturnType=*/I->getType(), Intrinsic::spv_reflect, +ArrayRef{I, N}, nullptr, "spv.reflect"); + } } return nullptr; } diff --git a/clang/lib/Headers/hlsl/hlsl_detail.h b/clang/lib/Headers/hlsl/hlsl_detail.h index 19d83ea5471c7c..624a7b05b56ad0 100644 --- a/clang/lib/Headers/hlsl/hlsl_detail.h +++ b/clang/lib/Headers/hlsl/hlsl_detail.
[clang] [llvm] [HLSL] Implement `reflect` HLSL function (PR #122992)
https://github.com/Icohedron edited https://github.com/llvm/llvm-project/pull/122992 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Implement the `reflect` HLSL function (PR #122992)
https://github.com/Icohedron updated https://github.com/llvm/llvm-project/pull/122992 >From 3f3b8c75c14bb9b3ed611c9cddec49d0e9339705 Mon Sep 17 00:00:00 2001 From: Icohedron Date: Mon, 13 Jan 2025 21:23:31 + Subject: [PATCH 1/3] Implement `reflect` HLSL function --- clang/include/clang/Basic/BuiltinsSPIRV.td| 6 + clang/lib/CodeGen/CGBuiltin.cpp | 13 ++ clang/lib/Headers/hlsl/hlsl_detail.h | 17 ++ clang/lib/Headers/hlsl/hlsl_intrinsics.h | 43 clang/lib/Sema/SemaSPIRV.cpp | 32 +++ clang/test/CodeGenHLSL/builtins/reflect.hlsl | 195 ++ clang/test/CodeGenSPIRV/Builtins/reflect.c| 32 +++ .../SemaHLSL/BuiltIns/reflect-errors.hlsl | 33 +++ .../test/SemaSPIRV/BuiltIns/reflect-errors.c | 23 +++ llvm/include/llvm/IR/IntrinsicsSPIRV.td | 1 + .../Target/SPIRV/SPIRVInstructionSelector.cpp | 2 + .../CodeGen/SPIRV/hlsl-intrinsics/reflect.ll | 33 +++ 12 files changed, 430 insertions(+) create mode 100644 clang/test/CodeGenHLSL/builtins/reflect.hlsl create mode 100644 clang/test/CodeGenSPIRV/Builtins/reflect.c create mode 100644 clang/test/SemaHLSL/BuiltIns/reflect-errors.hlsl create mode 100644 clang/test/SemaSPIRV/BuiltIns/reflect-errors.c create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/reflect.ll diff --git a/clang/include/clang/Basic/BuiltinsSPIRV.td b/clang/include/clang/Basic/BuiltinsSPIRV.td index 1e66939b822ef8..ce00459fc8ede7 100644 --- a/clang/include/clang/Basic/BuiltinsSPIRV.td +++ b/clang/include/clang/Basic/BuiltinsSPIRV.td @@ -13,3 +13,9 @@ def SPIRVDistance : Builtin { let Attributes = [NoThrow, Const]; let Prototype = "void(...)"; } + +def SPIRVReflect : Builtin { + let Spellings = ["__builtin_spirv_reflect"]; + let Attributes = [NoThrow, Const]; + let Prototype = "void(...)"; +} diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 1b25d365932c30..b9e680685b05e0 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -20487,6 +20487,19 @@ Value *CodeGenFunction::EmitSPIRVBuiltinExpr(unsigned BuiltinID, /*ReturnType=*/X->getType()->getScalarType(), Intrinsic::spv_distance, ArrayRef{X, Y}, nullptr, "spv.distance"); } + case SPIRV::BI__builtin_spirv_reflect: { +Value *I = EmitScalarExpr(E->getArg(0)); +Value *N = EmitScalarExpr(E->getArg(1)); +assert(E->getArg(0)->getType()->hasFloatingRepresentation() && + E->getArg(1)->getType()->hasFloatingRepresentation() && + "Reflect operands must have a float representation"); +assert(E->getArg(0)->getType()->isVectorType() && + E->getArg(1)->getType()->isVectorType() && + "Reflect operands must be a vector"); +return Builder.CreateIntrinsic( +/*ReturnType=*/I->getType(), Intrinsic::spv_reflect, +ArrayRef{I, N}, nullptr, "spv.reflect"); + } } return nullptr; } diff --git a/clang/lib/Headers/hlsl/hlsl_detail.h b/clang/lib/Headers/hlsl/hlsl_detail.h index 19d83ea5471c7c..624a7b05b56ad0 100644 --- a/clang/lib/Headers/hlsl/hlsl_detail.h +++ b/clang/lib/Headers/hlsl/hlsl_detail.h @@ -68,6 +68,23 @@ distance_vec_impl(vector X, vector Y) { return length_vec_impl(X - Y); #endif } + +template +constexpr enable_if_t::value || is_same::value, T> +reflect_impl(T I, T N) { + return I - 2 * N * I * N; +} + +template +constexpr enable_if_t::value || is_same::value, T> +reflect_vec_impl(vector I, vector N) { +#if (__has_builtin(__builtin_spirv_reflect)) + return __builtin_spirv_reflect(I, N); +#else + return I - 2 * N * __builtin_hlsl_dot(I, N); +#endif +} + } // namespace __detail } // namespace hlsl #endif //_HLSL_HLSL_DETAILS_H_ diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index d2d3abd92ea6a8..484ae708342a59 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -1919,6 +1919,49 @@ double3 rcp(double3); _HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_rcp) double4 rcp(double4); +//===--===// +// reflect builtin +//===--===// + +/// \fn T reflect(T I, T N) +/// \brief Returns a reflection using an incident ray, \a I, and a surface +/// normal, \a N. +/// \param I The incident ray. +/// \param N The surface normal. +/// +/// The return value is a floating-point vector that represents the reflection +/// of the incident ray, \a I, off a surface with the normal \a N. +/// +/// This function calculates the reflection vector using the following formula: +/// V = I - 2 * N * dot(I N) . +/// +/// N must already be normalized in order to achieve the desired result. +/// +/// The operands must all be a scalar or vector whose component type is +/// floating-point. +/// +/// Result type and the type of all operands must be the sam
[clang] [llvm] [HLSL] Implement the `reflect` HLSL function (PR #122992)
https://github.com/Icohedron updated https://github.com/llvm/llvm-project/pull/122992 >From 3f3b8c75c14bb9b3ed611c9cddec49d0e9339705 Mon Sep 17 00:00:00 2001 From: Icohedron Date: Mon, 13 Jan 2025 21:23:31 + Subject: [PATCH 1/4] Implement `reflect` HLSL function --- clang/include/clang/Basic/BuiltinsSPIRV.td| 6 + clang/lib/CodeGen/CGBuiltin.cpp | 13 ++ clang/lib/Headers/hlsl/hlsl_detail.h | 17 ++ clang/lib/Headers/hlsl/hlsl_intrinsics.h | 43 clang/lib/Sema/SemaSPIRV.cpp | 32 +++ clang/test/CodeGenHLSL/builtins/reflect.hlsl | 195 ++ clang/test/CodeGenSPIRV/Builtins/reflect.c| 32 +++ .../SemaHLSL/BuiltIns/reflect-errors.hlsl | 33 +++ .../test/SemaSPIRV/BuiltIns/reflect-errors.c | 23 +++ llvm/include/llvm/IR/IntrinsicsSPIRV.td | 1 + .../Target/SPIRV/SPIRVInstructionSelector.cpp | 2 + .../CodeGen/SPIRV/hlsl-intrinsics/reflect.ll | 33 +++ 12 files changed, 430 insertions(+) create mode 100644 clang/test/CodeGenHLSL/builtins/reflect.hlsl create mode 100644 clang/test/CodeGenSPIRV/Builtins/reflect.c create mode 100644 clang/test/SemaHLSL/BuiltIns/reflect-errors.hlsl create mode 100644 clang/test/SemaSPIRV/BuiltIns/reflect-errors.c create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/reflect.ll diff --git a/clang/include/clang/Basic/BuiltinsSPIRV.td b/clang/include/clang/Basic/BuiltinsSPIRV.td index 1e66939b822ef8..ce00459fc8ede7 100644 --- a/clang/include/clang/Basic/BuiltinsSPIRV.td +++ b/clang/include/clang/Basic/BuiltinsSPIRV.td @@ -13,3 +13,9 @@ def SPIRVDistance : Builtin { let Attributes = [NoThrow, Const]; let Prototype = "void(...)"; } + +def SPIRVReflect : Builtin { + let Spellings = ["__builtin_spirv_reflect"]; + let Attributes = [NoThrow, Const]; + let Prototype = "void(...)"; +} diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 1b25d365932c30..b9e680685b05e0 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -20487,6 +20487,19 @@ Value *CodeGenFunction::EmitSPIRVBuiltinExpr(unsigned BuiltinID, /*ReturnType=*/X->getType()->getScalarType(), Intrinsic::spv_distance, ArrayRef{X, Y}, nullptr, "spv.distance"); } + case SPIRV::BI__builtin_spirv_reflect: { +Value *I = EmitScalarExpr(E->getArg(0)); +Value *N = EmitScalarExpr(E->getArg(1)); +assert(E->getArg(0)->getType()->hasFloatingRepresentation() && + E->getArg(1)->getType()->hasFloatingRepresentation() && + "Reflect operands must have a float representation"); +assert(E->getArg(0)->getType()->isVectorType() && + E->getArg(1)->getType()->isVectorType() && + "Reflect operands must be a vector"); +return Builder.CreateIntrinsic( +/*ReturnType=*/I->getType(), Intrinsic::spv_reflect, +ArrayRef{I, N}, nullptr, "spv.reflect"); + } } return nullptr; } diff --git a/clang/lib/Headers/hlsl/hlsl_detail.h b/clang/lib/Headers/hlsl/hlsl_detail.h index 19d83ea5471c7c..624a7b05b56ad0 100644 --- a/clang/lib/Headers/hlsl/hlsl_detail.h +++ b/clang/lib/Headers/hlsl/hlsl_detail.h @@ -68,6 +68,23 @@ distance_vec_impl(vector X, vector Y) { return length_vec_impl(X - Y); #endif } + +template +constexpr enable_if_t::value || is_same::value, T> +reflect_impl(T I, T N) { + return I - 2 * N * I * N; +} + +template +constexpr enable_if_t::value || is_same::value, T> +reflect_vec_impl(vector I, vector N) { +#if (__has_builtin(__builtin_spirv_reflect)) + return __builtin_spirv_reflect(I, N); +#else + return I - 2 * N * __builtin_hlsl_dot(I, N); +#endif +} + } // namespace __detail } // namespace hlsl #endif //_HLSL_HLSL_DETAILS_H_ diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index d2d3abd92ea6a8..484ae708342a59 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -1919,6 +1919,49 @@ double3 rcp(double3); _HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_rcp) double4 rcp(double4); +//===--===// +// reflect builtin +//===--===// + +/// \fn T reflect(T I, T N) +/// \brief Returns a reflection using an incident ray, \a I, and a surface +/// normal, \a N. +/// \param I The incident ray. +/// \param N The surface normal. +/// +/// The return value is a floating-point vector that represents the reflection +/// of the incident ray, \a I, off a surface with the normal \a N. +/// +/// This function calculates the reflection vector using the following formula: +/// V = I - 2 * N * dot(I N) . +/// +/// N must already be normalized in order to achieve the desired result. +/// +/// The operands must all be a scalar or vector whose component type is +/// floating-point. +/// +/// Result type and the type of all operands must be the sam
[clang] [llvm] [HLSL] Implement the `reflect` HLSL function (PR #122992)
https://github.com/Icohedron edited https://github.com/llvm/llvm-project/pull/122992 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [HLSL] Implement D3DCOLORtoUBYTE4 intrinsic (PR #122202)
https://github.com/Icohedron created https://github.com/llvm/llvm-project/pull/122202 Fixes #99092. 1. Defines the function `D3DCOLORtoUBYTE4` in `clang/lib/Headers/hlsl/hlsl_intrinsics.h`. 2. Implements the function `D3DCOLORtoUBYTE4` as `d3d_color_to_ubyte4` in `clang/lib/Headers/hlsl/hlsl_detail.h` 3. Adds a HLSL codegen test to `clang/test/CodeGenHLSL/builtins/D3DCOLORtoUBYTE4.hlsl` 4. Adds error tests to `clang/test/SemaHLSL/BuiltIns/D3DCOLORtoUBYTE4-errors.hlsl` >From 0ef5e0217c04aa16c2f54b5f0edf0a6dc4cdc28d Mon Sep 17 00:00:00 2001 From: Icohedron Date: Thu, 9 Jan 2025 01:14:52 + Subject: [PATCH] Implement D3DCOLORtoUBYTE4 intrinsic --- clang/lib/Headers/hlsl/hlsl_detail.h| 8 clang/lib/Headers/hlsl/hlsl_intrinsics.h| 17 + .../CodeGenHLSL/builtins/D3DCOLORtoUBYTE4.hlsl | 12 .../BuiltIns/D3DCOLORtoUBYTE4-errors.hlsl | 13 + 4 files changed, 50 insertions(+) create mode 100644 clang/test/CodeGenHLSL/builtins/D3DCOLORtoUBYTE4.hlsl create mode 100644 clang/test/SemaHLSL/BuiltIns/D3DCOLORtoUBYTE4-errors.hlsl diff --git a/clang/lib/Headers/hlsl/hlsl_detail.h b/clang/lib/Headers/hlsl/hlsl_detail.h index 8d5fd941331531..470fa4214a12f8 100644 --- a/clang/lib/Headers/hlsl/hlsl_detail.h +++ b/clang/lib/Headers/hlsl/hlsl_detail.h @@ -33,6 +33,14 @@ constexpr enable_if_t bit_cast(T F) { return __builtin_bit_cast(U, F); } +constexpr vector d3d_color_to_ubyte4(vector V) { + // Use the same scaling factor used by FXC (i.e., 255.001953) + // Excerpt from stackoverflow discussion: + // "Built-in rounding, necessary because of truncation. 0.001953 * 256 = 0.5" + // https://stackoverflow.com/questions/52103720/why-does-d3dcolortoubyte4-multiplies-components-by-255-001953f + return V.zyxw * 255.001953f; +} + } // namespace __detail } // namespace hlsl #endif //_HLSL_HLSL_DETAILS_H_ diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index b745997f1d5a2b..e44403c6c802e0 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -1857,6 +1857,23 @@ half3 cross(half3, half3); _HLSL_BUILTIN_ALIAS(__builtin_hlsl_cross) float3 cross(float3, float3); +//===--===// +// D3DCOLORtoUBYTE4 builtins +//===--===// + +/// \fn T D3DCOLORtoUBYTE4(T x) +/// \brief Converts a floating-point, 4D vector set by a D3DCOLOR to a UBYTE4. +/// \param x [in] The floating-point vector4 to convert. +/// +/// The return value is the UBYTE4 representation of the \a x parameter. +/// +/// This function swizzles and scales components of the \a x parameter. Use this +/// function to compensate for the lack of UBYTE4 support in some hardware. + +constexpr vector D3DCOLORtoUBYTE4(vector V) { + return __detail::d3d_color_to_ubyte4(V); +} + //===--===// // rcp builtins //===--===// diff --git a/clang/test/CodeGenHLSL/builtins/D3DCOLORtoUBYTE4.hlsl b/clang/test/CodeGenHLSL/builtins/D3DCOLORtoUBYTE4.hlsl new file mode 100644 index 00..6e48800dae6698 --- /dev/null +++ b/clang/test/CodeGenHLSL/builtins/D3DCOLORtoUBYTE4.hlsl @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -finclude-default-header -triple \ +// RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \ +// RUN: -emit-llvm -O1 -o - | FileCheck %s --check-prefixes=CHECK + +// CHECK-LABEL: D3DCOLORtoUBYTE4 +int4 test_D3DCOLORtoUBYTE4 ( float4 p1 ) { + // CHECK: %[[SCALED:.*]] = fmul <4 x float> %{{.*}}, splat (float 0x406FE010) + // CHECK: %[[CONVERTED:.*]] = fptoui <4 x float> %[[SCALED]] to <4 x i32> + // CHECK: %[[SHUFFLED:.*]] = shufflevector <4 x i32> %{{.*}}, <4 x i32> poison, <4 x i32> + // CHECK: ret <4 x i32> %[[SHUFFLED]] + return D3DCOLORtoUBYTE4 ( p1 ); +} diff --git a/clang/test/SemaHLSL/BuiltIns/D3DCOLORtoUBYTE4-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/D3DCOLORtoUBYTE4-errors.hlsl new file mode 100644 index 00..fb41c212bd0be3 --- /dev/null +++ b/clang/test/SemaHLSL/BuiltIns/D3DCOLORtoUBYTE4-errors.hlsl @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -emit-llvm-only -disable-llvm-passes -verify + +int4 test_too_few_arg() { + return D3DCOLORtoUBYTE4(); + // expected-error@-1 {{no matching function for call to 'D3DCOLORtoUBYTE4'}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function not viable: requires single argument 'V', but no arguments were provided}} +} + +int4 test_too_many_arg(float4 v) { + return D3DCOLORtoUBYTE4(v, v); + // expected-error@-1 {{no matching function for call to 'D3DCOLORtoUBYTE4'}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function not viable: requires sing
[clang] [HLSL] Implement D3DCOLORtoUBYTE4 intrinsic (PR #122202)
https://github.com/Icohedron edited https://github.com/llvm/llvm-project/pull/122202 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [HLSL] Implement D3DCOLORtoUBYTE4 intrinsic (PR #122202)
https://github.com/Icohedron updated https://github.com/llvm/llvm-project/pull/122202 >From 0ef5e0217c04aa16c2f54b5f0edf0a6dc4cdc28d Mon Sep 17 00:00:00 2001 From: Icohedron Date: Thu, 9 Jan 2025 01:14:52 + Subject: [PATCH 1/4] Implement D3DCOLORtoUBYTE4 intrinsic --- clang/lib/Headers/hlsl/hlsl_detail.h| 8 clang/lib/Headers/hlsl/hlsl_intrinsics.h| 17 + .../CodeGenHLSL/builtins/D3DCOLORtoUBYTE4.hlsl | 12 .../BuiltIns/D3DCOLORtoUBYTE4-errors.hlsl | 13 + 4 files changed, 50 insertions(+) create mode 100644 clang/test/CodeGenHLSL/builtins/D3DCOLORtoUBYTE4.hlsl create mode 100644 clang/test/SemaHLSL/BuiltIns/D3DCOLORtoUBYTE4-errors.hlsl diff --git a/clang/lib/Headers/hlsl/hlsl_detail.h b/clang/lib/Headers/hlsl/hlsl_detail.h index 8d5fd941331531..470fa4214a12f8 100644 --- a/clang/lib/Headers/hlsl/hlsl_detail.h +++ b/clang/lib/Headers/hlsl/hlsl_detail.h @@ -33,6 +33,14 @@ constexpr enable_if_t bit_cast(T F) { return __builtin_bit_cast(U, F); } +constexpr vector d3d_color_to_ubyte4(vector V) { + // Use the same scaling factor used by FXC (i.e., 255.001953) + // Excerpt from stackoverflow discussion: + // "Built-in rounding, necessary because of truncation. 0.001953 * 256 = 0.5" + // https://stackoverflow.com/questions/52103720/why-does-d3dcolortoubyte4-multiplies-components-by-255-001953f + return V.zyxw * 255.001953f; +} + } // namespace __detail } // namespace hlsl #endif //_HLSL_HLSL_DETAILS_H_ diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index b745997f1d5a2b..e44403c6c802e0 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -1857,6 +1857,23 @@ half3 cross(half3, half3); _HLSL_BUILTIN_ALIAS(__builtin_hlsl_cross) float3 cross(float3, float3); +//===--===// +// D3DCOLORtoUBYTE4 builtins +//===--===// + +/// \fn T D3DCOLORtoUBYTE4(T x) +/// \brief Converts a floating-point, 4D vector set by a D3DCOLOR to a UBYTE4. +/// \param x [in] The floating-point vector4 to convert. +/// +/// The return value is the UBYTE4 representation of the \a x parameter. +/// +/// This function swizzles and scales components of the \a x parameter. Use this +/// function to compensate for the lack of UBYTE4 support in some hardware. + +constexpr vector D3DCOLORtoUBYTE4(vector V) { + return __detail::d3d_color_to_ubyte4(V); +} + //===--===// // rcp builtins //===--===// diff --git a/clang/test/CodeGenHLSL/builtins/D3DCOLORtoUBYTE4.hlsl b/clang/test/CodeGenHLSL/builtins/D3DCOLORtoUBYTE4.hlsl new file mode 100644 index 00..6e48800dae6698 --- /dev/null +++ b/clang/test/CodeGenHLSL/builtins/D3DCOLORtoUBYTE4.hlsl @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -finclude-default-header -triple \ +// RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \ +// RUN: -emit-llvm -O1 -o - | FileCheck %s --check-prefixes=CHECK + +// CHECK-LABEL: D3DCOLORtoUBYTE4 +int4 test_D3DCOLORtoUBYTE4 ( float4 p1 ) { + // CHECK: %[[SCALED:.*]] = fmul <4 x float> %{{.*}}, splat (float 0x406FE010) + // CHECK: %[[CONVERTED:.*]] = fptoui <4 x float> %[[SCALED]] to <4 x i32> + // CHECK: %[[SHUFFLED:.*]] = shufflevector <4 x i32> %{{.*}}, <4 x i32> poison, <4 x i32> + // CHECK: ret <4 x i32> %[[SHUFFLED]] + return D3DCOLORtoUBYTE4 ( p1 ); +} diff --git a/clang/test/SemaHLSL/BuiltIns/D3DCOLORtoUBYTE4-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/D3DCOLORtoUBYTE4-errors.hlsl new file mode 100644 index 00..fb41c212bd0be3 --- /dev/null +++ b/clang/test/SemaHLSL/BuiltIns/D3DCOLORtoUBYTE4-errors.hlsl @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -emit-llvm-only -disable-llvm-passes -verify + +int4 test_too_few_arg() { + return D3DCOLORtoUBYTE4(); + // expected-error@-1 {{no matching function for call to 'D3DCOLORtoUBYTE4'}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function not viable: requires single argument 'V', but no arguments were provided}} +} + +int4 test_too_many_arg(float4 v) { + return D3DCOLORtoUBYTE4(v, v); + // expected-error@-1 {{no matching function for call to 'D3DCOLORtoUBYTE4'}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function not viable: requires single argument 'V', but 2 arguments were provided}} +} >From cb89098fd6223a61b4e08ece8b50456c1ea3fcd7 Mon Sep 17 00:00:00 2001 From: Icohedron Date: Thu, 9 Jan 2025 17:30:45 + Subject: [PATCH 2/4] Add additional sema tests for D3DCOLORtoUBYTE4 for invalid arg types --- .../BuiltIns/D3DCOLORtoUBYTE4-errors.hlsl| 16 1 file changed, 16 insertions(+) diff --
[clang] [HLSL] Implement D3DCOLORtoUBYTE4 intrinsic (PR #122202)
https://github.com/Icohedron updated https://github.com/llvm/llvm-project/pull/122202 >From 5610b225e76b046e911c1a7a0c1e4ccc128d35a1 Mon Sep 17 00:00:00 2001 From: Icohedron Date: Thu, 9 Jan 2025 01:14:52 + Subject: [PATCH 1/2] [HLSL] Implement the D3DCOLORtoUBYTE4 intrinsic --- clang/lib/Headers/hlsl/hlsl_detail.h | 8 + clang/lib/Headers/hlsl/hlsl_intrinsics.h | 17 +++ .../builtins/D3DCOLORtoUBYTE4.hlsl| 12 .../BuiltIns/D3DCOLORtoUBYTE4-errors.hlsl | 29 +++ 4 files changed, 66 insertions(+) create mode 100644 clang/test/CodeGenHLSL/builtins/D3DCOLORtoUBYTE4.hlsl create mode 100644 clang/test/SemaHLSL/BuiltIns/D3DCOLORtoUBYTE4-errors.hlsl diff --git a/clang/lib/Headers/hlsl/hlsl_detail.h b/clang/lib/Headers/hlsl/hlsl_detail.h index 8d5fd941331531..470fa4214a12f8 100644 --- a/clang/lib/Headers/hlsl/hlsl_detail.h +++ b/clang/lib/Headers/hlsl/hlsl_detail.h @@ -33,6 +33,14 @@ constexpr enable_if_t bit_cast(T F) { return __builtin_bit_cast(U, F); } +constexpr vector d3d_color_to_ubyte4(vector V) { + // Use the same scaling factor used by FXC (i.e., 255.001953) + // Excerpt from stackoverflow discussion: + // "Built-in rounding, necessary because of truncation. 0.001953 * 256 = 0.5" + // https://stackoverflow.com/questions/52103720/why-does-d3dcolortoubyte4-multiplies-components-by-255-001953f + return V.zyxw * 255.001953f; +} + } // namespace __detail } // namespace hlsl #endif //_HLSL_HLSL_DETAILS_H_ diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index b745997f1d5a2b..e44403c6c802e0 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -1857,6 +1857,23 @@ half3 cross(half3, half3); _HLSL_BUILTIN_ALIAS(__builtin_hlsl_cross) float3 cross(float3, float3); +//===--===// +// D3DCOLORtoUBYTE4 builtins +//===--===// + +/// \fn T D3DCOLORtoUBYTE4(T x) +/// \brief Converts a floating-point, 4D vector set by a D3DCOLOR to a UBYTE4. +/// \param x [in] The floating-point vector4 to convert. +/// +/// The return value is the UBYTE4 representation of the \a x parameter. +/// +/// This function swizzles and scales components of the \a x parameter. Use this +/// function to compensate for the lack of UBYTE4 support in some hardware. + +constexpr vector D3DCOLORtoUBYTE4(vector V) { + return __detail::d3d_color_to_ubyte4(V); +} + //===--===// // rcp builtins //===--===// diff --git a/clang/test/CodeGenHLSL/builtins/D3DCOLORtoUBYTE4.hlsl b/clang/test/CodeGenHLSL/builtins/D3DCOLORtoUBYTE4.hlsl new file mode 100644 index 00..7021de7192b5e5 --- /dev/null +++ b/clang/test/CodeGenHLSL/builtins/D3DCOLORtoUBYTE4.hlsl @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -finclude-default-header -triple \ +// RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \ +// RUN: -emit-llvm -O1 -o - | FileCheck %s --check-prefixes=CHECK + +// CHECK-LABEL: D3DCOLORtoUBYTE4 +int4 test_D3DCOLORtoUBYTE4(float4 p1) { + // CHECK: %[[SCALED:.*]] = fmul [[FMFLAGS:.*]]<4 x float> %{{.*}}, splat (float 0x406FE010) + // CHECK: %[[CONVERTED:.*]] = fptoui <4 x float> %[[SCALED]] to <4 x i32> + // CHECK: %[[SHUFFLED:.*]] = shufflevector <4 x i32> %{{.*}}, <4 x i32> poison, <4 x i32> + // CHECK: ret <4 x i32> %[[SHUFFLED]] + return D3DCOLORtoUBYTE4(p1); +} diff --git a/clang/test/SemaHLSL/BuiltIns/D3DCOLORtoUBYTE4-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/D3DCOLORtoUBYTE4-errors.hlsl new file mode 100644 index 00..e9ba851007c941 --- /dev/null +++ b/clang/test/SemaHLSL/BuiltIns/D3DCOLORtoUBYTE4-errors.hlsl @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -emit-llvm-only -disable-llvm-passes -verify + +int4 test_too_few_arg() { + return D3DCOLORtoUBYTE4(); + // expected-error@-1 {{no matching function for call to 'D3DCOLORtoUBYTE4'}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function not viable: requires single argument 'V', but no arguments were provided}} +} + +int4 test_too_many_arg(float4 v) { + return D3DCOLORtoUBYTE4(v, v); + // expected-error@-1 {{no matching function for call to 'D3DCOLORtoUBYTE4'}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function not viable: requires single argument 'V', but 2 arguments were provided}} +} + +int4 float2_arg(float2 v) { +return D3DCOLORtoUBYTE4(v); +// expected-error@-1 {{no matching function for call to 'D3DCOLORtoUBYTE4'}} +// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function not viable: no known conversion from 'vector<[...], 2>' to 'vector<[...], 4>' for 1st argument}} +} + +struct S { +
[clang] [HLSL] Implement D3DCOLORtoUBYTE4 intrinsic (PR #122202)
https://github.com/Icohedron updated https://github.com/llvm/llvm-project/pull/122202 >From f76d5038811c72d1e185cdceeb24d5014c5c8281 Mon Sep 17 00:00:00 2001 From: Icohedron Date: Thu, 9 Jan 2025 01:14:52 + Subject: [PATCH 1/5] Implement D3DCOLORtoUBYTE4 intrinsic --- clang/lib/Headers/hlsl/hlsl_detail.h| 8 clang/lib/Headers/hlsl/hlsl_intrinsics.h| 17 + .../CodeGenHLSL/builtins/D3DCOLORtoUBYTE4.hlsl | 12 .../BuiltIns/D3DCOLORtoUBYTE4-errors.hlsl | 13 + 4 files changed, 50 insertions(+) create mode 100644 clang/test/CodeGenHLSL/builtins/D3DCOLORtoUBYTE4.hlsl create mode 100644 clang/test/SemaHLSL/BuiltIns/D3DCOLORtoUBYTE4-errors.hlsl diff --git a/clang/lib/Headers/hlsl/hlsl_detail.h b/clang/lib/Headers/hlsl/hlsl_detail.h index 392075d276b188..3d78f01b6be464 100644 --- a/clang/lib/Headers/hlsl/hlsl_detail.h +++ b/clang/lib/Headers/hlsl/hlsl_detail.h @@ -41,6 +41,14 @@ constexpr enable_if_t bit_cast(T F) { return __builtin_bit_cast(U, F); } +constexpr vector d3d_color_to_ubyte4(vector V) { + // Use the same scaling factor used by FXC (i.e., 255.001953) + // Excerpt from stackoverflow discussion: + // "Built-in rounding, necessary because of truncation. 0.001953 * 256 = 0.5" + // https://stackoverflow.com/questions/52103720/why-does-d3dcolortoubyte4-multiplies-components-by-255-001953f + return V.zyxw * 255.001953f; +} + template constexpr enable_if_t::value || is_same::value, T> length_impl(T X) { diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index cf287e598f76ba..1ec1038190ca53 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -1846,6 +1846,23 @@ half3 cross(half3, half3); _HLSL_BUILTIN_ALIAS(__builtin_hlsl_cross) float3 cross(float3, float3); +//===--===// +// D3DCOLORtoUBYTE4 builtins +//===--===// + +/// \fn T D3DCOLORtoUBYTE4(T x) +/// \brief Converts a floating-point, 4D vector set by a D3DCOLOR to a UBYTE4. +/// \param x [in] The floating-point vector4 to convert. +/// +/// The return value is the UBYTE4 representation of the \a x parameter. +/// +/// This function swizzles and scales components of the \a x parameter. Use this +/// function to compensate for the lack of UBYTE4 support in some hardware. + +constexpr vector D3DCOLORtoUBYTE4(vector V) { + return __detail::d3d_color_to_ubyte4(V); +} + //===--===// // rcp builtins //===--===// diff --git a/clang/test/CodeGenHLSL/builtins/D3DCOLORtoUBYTE4.hlsl b/clang/test/CodeGenHLSL/builtins/D3DCOLORtoUBYTE4.hlsl new file mode 100644 index 00..6e48800dae6698 --- /dev/null +++ b/clang/test/CodeGenHLSL/builtins/D3DCOLORtoUBYTE4.hlsl @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -finclude-default-header -triple \ +// RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \ +// RUN: -emit-llvm -O1 -o - | FileCheck %s --check-prefixes=CHECK + +// CHECK-LABEL: D3DCOLORtoUBYTE4 +int4 test_D3DCOLORtoUBYTE4 ( float4 p1 ) { + // CHECK: %[[SCALED:.*]] = fmul <4 x float> %{{.*}}, splat (float 0x406FE010) + // CHECK: %[[CONVERTED:.*]] = fptoui <4 x float> %[[SCALED]] to <4 x i32> + // CHECK: %[[SHUFFLED:.*]] = shufflevector <4 x i32> %{{.*}}, <4 x i32> poison, <4 x i32> + // CHECK: ret <4 x i32> %[[SHUFFLED]] + return D3DCOLORtoUBYTE4 ( p1 ); +} diff --git a/clang/test/SemaHLSL/BuiltIns/D3DCOLORtoUBYTE4-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/D3DCOLORtoUBYTE4-errors.hlsl new file mode 100644 index 00..fb41c212bd0be3 --- /dev/null +++ b/clang/test/SemaHLSL/BuiltIns/D3DCOLORtoUBYTE4-errors.hlsl @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -emit-llvm-only -disable-llvm-passes -verify + +int4 test_too_few_arg() { + return D3DCOLORtoUBYTE4(); + // expected-error@-1 {{no matching function for call to 'D3DCOLORtoUBYTE4'}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function not viable: requires single argument 'V', but no arguments were provided}} +} + +int4 test_too_many_arg(float4 v) { + return D3DCOLORtoUBYTE4(v, v); + // expected-error@-1 {{no matching function for call to 'D3DCOLORtoUBYTE4'}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function not viable: requires single argument 'V', but 2 arguments were provided}} +} >From 49e5ddf3942da0d8634da22e35f66f0b675f0744 Mon Sep 17 00:00:00 2001 From: Icohedron Date: Thu, 9 Jan 2025 17:30:45 + Subject: [PATCH 2/5] Add additional sema tests for D3DCOLORtoUBYTE4 for invalid arg types --- .../BuiltIns/D3DCOLORtoUBYTE4-errors.hlsl| 16 1 file changed, 16 insertions(+) di
[clang] [HLSL] Implement D3DCOLORtoUBYTE4 intrinsic (PR #122202)
@@ -33,6 +33,14 @@ constexpr enable_if_t bit_cast(T F) { return __builtin_bit_cast(U, F); } +constexpr vector d3d_color_to_ubyte4(vector V) { + // Use the same scaling factor used by FXC (i.e., 255.001953) + // Excerpt from stackoverflow discussion: + // "Built-in rounding, necessary because of truncation. 0.001953 * 256 = 0.5" + // https://stackoverflow.com/questions/52103720/why-does-d3dcolortoubyte4-multiplies-components-by-255-001953f + return V.zyxw * 255.001953f; Icohedron wrote: This implementation of `D3DCOLORtoUBYTE4` scales the vector by `255.001953`. This matches the way it was done in [DXC](https://github.com/microsoft/DirectXShaderCompiler/blob/070d0d5a2beacef9eeb51037a9b04665716fd6f3/lib/HLSL/HLOperationLower.cpp#L666C1-L697C2). However, it differs from the [SPIRV custom implementation](https://github.com/microsoft/DirectXShaderCompiler/blob/070d0d5a2beacef9eeb51037a9b04665716fd6f3/tools/clang/lib/SPIRV/SpirvEmitter.cpp#L11647C1-L11663C2) which scales the vector by `255.002`. https://github.com/llvm/llvm-project/pull/122202 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Implement the `reflect` HLSL function (PR #122992)
@@ -0,0 +1,195 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5 +// RUN: %clang_cc1 -finclude-default-header -triple \ +// RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \ +// RUN: -emit-llvm -O1 -o - | FileCheck %s +// RUN: %clang_cc1 -finclude-default-header -triple \ +// RUN: spirv-unknown-vulkan-compute %s -fnative-half-type \ +// RUN: -emit-llvm -O1 -o - | FileCheck %s --check-prefix=SPVCHECK + +// CHECK-LABEL: define noundef nofpclass(nan inf) half @_Z17test_reflect_halfDhDh( +// CHECK-SAME: half noundef nofpclass(nan inf) [[I:%.*]], half noundef nofpclass(nan inf) [[N:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT:[[MUL_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[I]], 0xH4000 +// CHECK-NEXT:[[TMP0:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[N]], [[N]] +// CHECK-NEXT:[[MUL2_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[TMP0]], [[MUL_I]] +// CHECK-NEXT:[[SUB_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn half [[I]], [[MUL2_I]] +// CHECK-NEXT:ret half [[SUB_I]] +// +// SPVCHECK-LABEL: define spir_func noundef nofpclass(nan inf) half @_Z17test_reflect_halfDhDh( +// SPVCHECK-SAME: half noundef nofpclass(nan inf) [[I:%.*]], half noundef nofpclass(nan inf) [[N:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { +// SPVCHECK-NEXT: [[ENTRY:.*:]] +// SPVCHECK-NEXT:[[MUL_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[I]], 0xH4000 +// SPVCHECK-NEXT:[[TMP0:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[N]], [[N]] +// SPVCHECK-NEXT:[[MUL2_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[TMP0]], [[MUL_I]] +// SPVCHECK-NEXT:[[SUB_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn half [[I]], [[MUL2_I]] +// SPVCHECK-NEXT:ret half [[SUB_I]] +// +half test_reflect_half(half I, half N) { +return reflect(I, N); +} + +// CHECK-LABEL: define noundef nofpclass(nan inf) <2 x half> @_Z18test_reflect_half2Dv2_DhS_( +// CHECK-SAME: <2 x half> noundef nofpclass(nan inf) [[I:%.*]], <2 x half> noundef nofpclass(nan inf) [[N:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT:[[HLSL_DOT_I:%.*]] = tail call reassoc nnan ninf nsz arcp afn half @llvm.dx.fdot.v2f16(<2 x half> [[I]], <2 x half> [[N]]) +// CHECK-NEXT:[[TMP0:%.*]] = extractelement <2 x half> [[I]], i64 0 +// CHECK-NEXT:[[TMP1:%.*]] = extractelement <2 x half> [[N]], i64 0 +// CHECK-NEXT:[[TMP2:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[TMP1]], 0xH4000 Icohedron wrote: Yea that's another issue I spotted and am troubleshooting right now https://github.com/llvm/llvm-project/pull/122992 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Implement the `reflect` HLSL function (PR #122992)
@@ -0,0 +1,33 @@ +; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s Icohedron wrote: Changing the triple to `-mtriple=spirv32-unknown-unknown` does indeed cause the test to fail at instruction selection ``` FAIL: LLVM :: CodeGen/SPIRV/hlsl-intrinsics/reflect.ll (282 of 582) TEST 'LLVM :: CodeGen/SPIRV/hlsl-intrinsics/reflect.ll' FAILED Exit Code: 2 Command Output (stderr): -- RUN: at line 1: /workspace/feature-reflect/build/bin/llc -O0 -mtriple=spirv32-unknown-unknown /workspace/feature-reflect/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/reflect.ll -o - | /workspace/feature-reflect/build/bin/FileCheck /workspace/feature-reflect/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/reflect.ll + /workspace/feature-reflect/build/bin/FileCheck /workspace/feature-reflect/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/reflect.ll + /workspace/feature-reflect/build/bin/llc -O0 -mtriple=spirv32-unknown-unknown /workspace/feature-reflect/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/reflect.ll -o - LLVM ERROR: cannot select: %6:id(<2 x s64>) = G_INTRINSIC intrinsic(@llvm.spv.reflect), %0:vfid(<2 x s64>), %1:vfid(<2 x s64>) (in function: reflect_half4) PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace. Stack dump: 0. Program arguments: /workspace/feature-reflect/build/bin/llc -O0 -mtriple=spirv32-unknown-unknown /workspace/feature-reflect/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/reflect.ll -o - 1. Running pass 'Function Pass Manager' on module '/workspace/feature-reflect/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/reflect.ll'. 2. Running pass 'InstructionSelect' on function '@reflect_half4' #0 0x5a7a8f13318f llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) /workspace/feature-reflect/llvm/lib/Support/Unix/Signals.inc:804:3 #1 0x5a7a8f130a5f llvm::sys::RunSignalHandlers() /workspace/feature-reflect/llvm/lib/Support/Signals.cpp:105:20 #2 0x5a7a8f130db6 SignalHandler(int) /workspace/feature-reflect/llvm/lib/Support/Unix/Signals.inc:417:1 #3 0x71ee82242520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520) #4 0x71ee822969fc pthread_kill (/lib/x86_64-linux-gnu/libc.so.6+0x969fc) #5 0x71ee82242476 gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x42476) #6 0x71ee822287f3 abort (/lib/x86_64-linux-gnu/libc.so.6+0x287f3) #7 0x5a7a8f08b463 (/workspace/feature-reflect/build/bin/llc+0x3631463) #8 0x5a7a8f664b32 reportGISelDiagnostic(llvm::DiagnosticSeverity, llvm::MachineFunction&, llvm::TargetPassConfig const&, llvm::MachineOptimizationRemarkEmitter&, llvm::MachineOptimizationRemarkMissed&) /workspace/feature-reflect/llvm/lib/CodeGen/GlobalISel/Utils.cpp:248:23 #9 0x5a7a8f666a55 llvm::DiagnosticInfoOptimizationBase::~DiagnosticInfoOptimizationBase() /workspace/feature-reflect/llvm/include/llvm/IR/DiagnosticInfo.h:486:7 #10 0x5a7a8f666a55 llvm::DiagnosticInfoMIROptimization::~DiagnosticInfoMIROptimization() /workspace/feature-reflect/llvm/include/llvm/CodeGen/MachineOptimizationRemarkEmitter.h:31:7 #11 0x5a7a8f666a55 llvm::MachineOptimizationRemarkMissed::~MachineOptimizationRemarkMissed() /workspace/feature-reflect/llvm/include/llvm/CodeGen/MachineOptimizationRemarkEmitter.h:85:7 #12 0x5a7a8f666a55 llvm::reportGISelFailure(llvm::MachineFunction&, llvm::TargetPassConfig const&, llvm::MachineOptimizationRemarkEmitter&, char const*, llvm::StringRef, llvm::MachineInstr const&) /workspace/feature-reflect/llvm/lib/CodeGen/GlobalISel/Utils.cpp:277:1 #13 0x5a7a8f5ce077 llvm::SmallVectorTemplateCommon, void>::begin() /workspace/feature-reflect/llvm/include/llvm/ADT/SmallVector.h:267:45 #14 0x5a7a8f5ce077 llvm::SmallVectorTemplateCommon, void>::end() /workspace/feature-reflect/llvm/include/llvm/ADT/SmallVector.h:269:32 #15 0x5a7a8f5ce077 llvm::SmallVector, 8u>::~SmallVector() /workspace/feature-reflect/llvm/include/llvm/ADT/SmallVector.h:1202:24 #16 0x5a7a8f5ce077 llvm::po_iterator, false, llvm::GraphTraits>::~po_iterator() /workspace/feature-reflect/llvm/include/llvm/ADT/PostOrderIterator.h:97:7 #17 0x5a7a8f5ce077 llvm::InstructionSelect::selectMachineFunction(llvm::MachineFunction&) /workspace/feature-reflect/llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp:225:5 #18 0x5a7a8f5cf70c operator() /workspace/feature-reflect/llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp:145:59 #19 0x5a7a8f5cf70c ~scope_exit /workspace/feature-reflect/llvm/include/llvm/ADT/ScopeExit.h:46:19 #20 0x5a7a8f5cf70c llvm::InstructionSelect::runOnMachineFunction(llvm::MachineFunction&) /workspace/feature-reflect/llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp:157:1 #21 0x5a7a8f5cf70c llvm::InstructionSelect::runOnMachineFunction(llvm::MachineFunction&) /workspace/feature-reflect/llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp:134:6 #22 0x5a7a8dfbf72a llvm::MachineFunction
[clang] [llvm] [HLSL] Implement the `reflect` HLSL function (PR #122992)
https://github.com/Icohedron converted_to_draft https://github.com/llvm/llvm-project/pull/122992 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Implement the `reflect` HLSL function (PR #122992)
@@ -0,0 +1,195 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5 +// RUN: %clang_cc1 -finclude-default-header -triple \ +// RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \ +// RUN: -emit-llvm -O1 -o - | FileCheck %s +// RUN: %clang_cc1 -finclude-default-header -triple \ +// RUN: spirv-unknown-vulkan-compute %s -fnative-half-type \ +// RUN: -emit-llvm -O1 -o - | FileCheck %s --check-prefix=SPVCHECK + +// CHECK-LABEL: define noundef nofpclass(nan inf) half @_Z17test_reflect_halfDhDh( +// CHECK-SAME: half noundef nofpclass(nan inf) [[I:%.*]], half noundef nofpclass(nan inf) [[N:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT:[[MUL_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[I]], 0xH4000 +// CHECK-NEXT:[[TMP0:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[N]], [[N]] +// CHECK-NEXT:[[MUL2_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[TMP0]], [[MUL_I]] +// CHECK-NEXT:[[SUB_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn half [[I]], [[MUL2_I]] +// CHECK-NEXT:ret half [[SUB_I]] +// +// SPVCHECK-LABEL: define spir_func noundef nofpclass(nan inf) half @_Z17test_reflect_halfDhDh( +// SPVCHECK-SAME: half noundef nofpclass(nan inf) [[I:%.*]], half noundef nofpclass(nan inf) [[N:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { +// SPVCHECK-NEXT: [[ENTRY:.*:]] +// SPVCHECK-NEXT:[[MUL_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[I]], 0xH4000 +// SPVCHECK-NEXT:[[TMP0:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[N]], [[N]] +// SPVCHECK-NEXT:[[MUL2_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[TMP0]], [[MUL_I]] +// SPVCHECK-NEXT:[[SUB_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn half [[I]], [[MUL2_I]] +// SPVCHECK-NEXT:ret half [[SUB_I]] +// +half test_reflect_half(half I, half N) { +return reflect(I, N); +} + +// CHECK-LABEL: define noundef nofpclass(nan inf) <2 x half> @_Z18test_reflect_half2Dv2_DhS_( +// CHECK-SAME: <2 x half> noundef nofpclass(nan inf) [[I:%.*]], <2 x half> noundef nofpclass(nan inf) [[N:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT:[[HLSL_DOT_I:%.*]] = tail call reassoc nnan ninf nsz arcp afn half @llvm.dx.fdot.v2f16(<2 x half> [[I]], <2 x half> [[N]]) +// CHECK-NEXT:[[TMP0:%.*]] = extractelement <2 x half> [[I]], i64 0 +// CHECK-NEXT:[[TMP1:%.*]] = extractelement <2 x half> [[N]], i64 0 +// CHECK-NEXT:[[TMP2:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[TMP1]], 0xH4000 +// CHECK-NEXT:[[TMP3:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[TMP2]], [[HLSL_DOT_I]] +// CHECK-NEXT:[[CAST_VTRUNC_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn half [[TMP0]], [[TMP3]] +// CHECK-NEXT:[[SPLAT_SPLATINSERT:%.*]] = insertelement <2 x half> poison, half [[CAST_VTRUNC_I]], i64 0 +// CHECK-NEXT:[[SPLAT_SPLAT:%.*]] = shufflevector <2 x half> [[SPLAT_SPLATINSERT]], <2 x half> poison, <2 x i32> zeroinitializer +// CHECK-NEXT:ret <2 x half> [[SPLAT_SPLAT]] +// +// SPVCHECK-LABEL: define spir_func noundef nofpclass(nan inf) <2 x half> @_Z18test_reflect_half2Dv2_DhS_( +// SPVCHECK-SAME: <2 x half> noundef nofpclass(nan inf) [[I:%.*]], <2 x half> noundef nofpclass(nan inf) [[N:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SPVCHECK-NEXT: [[ENTRY:.*:]] +// SPVCHECK-NEXT:[[SPV_REFLECT_I:%.*]] = tail call reassoc nnan ninf nsz arcp afn <2 x half> @llvm.spv.reflect.v2f16(<2 x half> [[I]], <2 x half> [[N]]) +// SPVCHECK-NEXT:[[SPLAT_SPLAT:%.*]] = shufflevector <2 x half> [[SPV_REFLECT_I]], <2 x half> poison, <2 x i32> zeroinitializer Icohedron wrote: I am unsure where the vector splat is coming from. https://github.com/llvm/llvm-project/pull/122992 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Implement the `reflect` HLSL function (PR #122992)
@@ -0,0 +1,195 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5 +// RUN: %clang_cc1 -finclude-default-header -triple \ +// RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \ +// RUN: -emit-llvm -O1 -o - | FileCheck %s +// RUN: %clang_cc1 -finclude-default-header -triple \ +// RUN: spirv-unknown-vulkan-compute %s -fnative-half-type \ +// RUN: -emit-llvm -O1 -o - | FileCheck %s --check-prefix=SPVCHECK + +// CHECK-LABEL: define noundef nofpclass(nan inf) half @_Z17test_reflect_halfDhDh( +// CHECK-SAME: half noundef nofpclass(nan inf) [[I:%.*]], half noundef nofpclass(nan inf) [[N:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT:[[MUL_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[I]], 0xH4000 +// CHECK-NEXT:[[TMP0:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[N]], [[N]] +// CHECK-NEXT:[[MUL2_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[TMP0]], [[MUL_I]] +// CHECK-NEXT:[[SUB_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn half [[I]], [[MUL2_I]] +// CHECK-NEXT:ret half [[SUB_I]] +// +// SPVCHECK-LABEL: define spir_func noundef nofpclass(nan inf) half @_Z17test_reflect_halfDhDh( +// SPVCHECK-SAME: half noundef nofpclass(nan inf) [[I:%.*]], half noundef nofpclass(nan inf) [[N:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { +// SPVCHECK-NEXT: [[ENTRY:.*:]] +// SPVCHECK-NEXT:[[MUL_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[I]], 0xH4000 +// SPVCHECK-NEXT:[[TMP0:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[N]], [[N]] +// SPVCHECK-NEXT:[[MUL2_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[TMP0]], [[MUL_I]] +// SPVCHECK-NEXT:[[SUB_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn half [[I]], [[MUL2_I]] +// SPVCHECK-NEXT:ret half [[SUB_I]] +// +half test_reflect_half(half I, half N) { +return reflect(I, N); +} + +// CHECK-LABEL: define noundef nofpclass(nan inf) <2 x half> @_Z18test_reflect_half2Dv2_DhS_( +// CHECK-SAME: <2 x half> noundef nofpclass(nan inf) [[I:%.*]], <2 x half> noundef nofpclass(nan inf) [[N:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT:[[HLSL_DOT_I:%.*]] = tail call reassoc nnan ninf nsz arcp afn half @llvm.dx.fdot.v2f16(<2 x half> [[I]], <2 x half> [[N]]) +// CHECK-NEXT:[[TMP0:%.*]] = extractelement <2 x half> [[I]], i64 0 +// CHECK-NEXT:[[TMP1:%.*]] = extractelement <2 x half> [[N]], i64 0 +// CHECK-NEXT:[[TMP2:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[TMP1]], 0xH4000 Icohedron wrote: It seems like all the math operations except for the dot product are being performed on only the first elements of each input vector. https://github.com/llvm/llvm-project/pull/122992 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Implement the `reflect` HLSL function (PR #122992)
https://github.com/Icohedron ready_for_review https://github.com/llvm/llvm-project/pull/122992 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] [DXIL] Implement the AddUint64 HLSL function and the UAddc DXIL op (PR #127137)
https://github.com/Icohedron updated https://github.com/llvm/llvm-project/pull/127137 >From 4fae5642c6e8e305cdc687b4968ba5eabaa44b50 Mon Sep 17 00:00:00 2001 From: Icohedron Date: Mon, 27 Jan 2025 11:18:09 -0800 Subject: [PATCH 1/4] Add the AddUint64 HLSL builtin function - Defines the AddUint64 HLSL builtin function - Implements the UAddc DXIL op to lower AddUint64 to DXIL --- clang/include/clang/Basic/Builtins.td | 6 ++ .../clang/Basic/DiagnosticSemaKinds.td| 2 + clang/lib/CodeGen/CGBuiltin.cpp | 45 clang/lib/Headers/hlsl/hlsl_intrinsics.h | 21 ++ clang/lib/Sema/SemaHLSL.cpp | 47 .../test/CodeGenHLSL/builtins/AddUint64.hlsl | 71 +++ .../SemaHLSL/BuiltIns/AddUint64-errors.hlsl | 41 +++ llvm/lib/Target/DirectX/DXIL.td | 13 llvm/lib/Target/DirectX/DXILOpBuilder.cpp | 14 llvm/lib/Target/DirectX/DXILOpBuilder.h | 3 + llvm/lib/Target/DirectX/DXILOpLowering.cpp| 22 -- llvm/test/CodeGen/DirectX/UAddc.ll| 40 +++ llvm/test/CodeGen/DirectX/UAddc_errors.ll | 30 13 files changed, 348 insertions(+), 7 deletions(-) create mode 100644 clang/test/CodeGenHLSL/builtins/AddUint64.hlsl create mode 100644 clang/test/SemaHLSL/BuiltIns/AddUint64-errors.hlsl create mode 100644 llvm/test/CodeGen/DirectX/UAddc.ll create mode 100644 llvm/test/CodeGen/DirectX/UAddc_errors.ll diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 29939242596ba..2433427a89429 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -4753,6 +4753,12 @@ def GetDeviceSideMangledName : LangBuiltin<"CUDA_LANG"> { } // HLSL +def HLSLAddUint64: LangBuiltin<"HLSL_LANG"> { + let Spellings = ["__builtin_hlsl_adduint64"]; + let Attributes = [NoThrow, Const]; + let Prototype = "void(...)"; +} + def HLSLResourceGetPointer : LangBuiltin<"HLSL_LANG"> { let Spellings = ["__builtin_hlsl_resource_getpointer"]; let Attributes = [NoThrow]; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 2fce5e88ba8a0..e78339ee924ff 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -10655,6 +10655,8 @@ def err_second_argument_to_cwsc_not_pointer : Error< def err_vector_incorrect_num_elements : Error< "%select{too many|too few}0 elements in vector %select{initialization|operand}3 (expected %1 elements, have %2)">; +def err_invalid_even_odd_vector_element_count : Error< + "invalid element count of %0 in vector %select{initialization|operand}4 (expected an %select{even|odd}3 element count in the range of %1 and %2)">; def err_altivec_empty_initializer : Error<"expected initializer">; def err_invalid_neon_type_code : Error< diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 361e4c4bf2e2e..5322b38458b26 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -19445,6 +19445,51 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, return nullptr; switch (BuiltinID) { + case Builtin::BI__builtin_hlsl_adduint64: { +Value *OpA = EmitScalarExpr(E->getArg(0)); +Value *OpB = EmitScalarExpr(E->getArg(1)); +assert(E->getArg(0)->getType()->hasIntegerRepresentation() && + E->getArg(1)->getType()->hasIntegerRepresentation() && + "AddUint64 operands must have an integer representation"); +assert(((E->getArg(0)->getType()->castAs()->getNumElements() == + 2 && + E->getArg(1)->getType()->castAs()->getNumElements() == + 2) || +(E->getArg(0)->getType()->castAs()->getNumElements() == + 4 && + E->getArg(1)->getType()->castAs()->getNumElements() == + 4)) && + "input vectors must have 2 or 4 elements each"); + +llvm::Value *Result = PoisonValue::get(OpA->getType()); +uint64_t NumElements = +E->getArg(0)->getType()->castAs()->getNumElements(); +for (uint64_t i = 0; i < NumElements / 2; ++i) { + + // Obtain low and high words of inputs A and B + llvm::Value *LowA = Builder.CreateExtractElement(OpA, 2 * i + 0); + llvm::Value *HighA = Builder.CreateExtractElement(OpA, 2 * i + 1); + llvm::Value *LowB = Builder.CreateExtractElement(OpB, 2 * i + 0); + llvm::Value *HighB = Builder.CreateExtractElement(OpB, 2 * i + 1); + + // Use an uadd_with_overflow to compute the sum of low words and obtain a + // carry value + llvm::Value *Carry; + llvm::Value *LowSum = EmitOverflowIntrinsic( + *this, llvm::Intrinsic::uadd_with_overflow, LowA, LowB, Carry); + llvm::Value *ZExtCarry = Builder.CreateZExt(Carry, HighA->getType()); + + // Sum the high words and the carry
[clang] [HLSL] Implement the 'and' HLSL function (PR #127098)
https://github.com/Icohedron updated https://github.com/llvm/llvm-project/pull/127098 >From 5b093ca42fdc24f89bfccac25e6f2e17155432f6 Mon Sep 17 00:00:00 2001 From: Icohedron Date: Wed, 12 Feb 2025 21:24:00 + Subject: [PATCH 1/4] Implement the 'and' HLSL function --- clang/include/clang/Basic/Builtins.td| 6 +++ clang/lib/CodeGen/CGBuiltin.cpp | 5 +++ clang/lib/Headers/hlsl/hlsl_intrinsics.h | 16 +++ clang/lib/Sema/SemaHLSL.cpp | 11 + clang/test/CodeGenHLSL/builtins/and.hlsl | 45 clang/test/SemaHLSL/BuiltIns/and-errors.hlsl | 27 6 files changed, 110 insertions(+) create mode 100644 clang/test/CodeGenHLSL/builtins/and.hlsl create mode 100644 clang/test/SemaHLSL/BuiltIns/and-errors.hlsl diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 29939242596ba..de758d88f8f92 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -4765,6 +4765,12 @@ def HLSLAll : LangBuiltin<"HLSL_LANG"> { let Prototype = "bool(...)"; } +def HLSLAnd : LangBuiltin<"HLSL_LANG"> { + let Spellings = ["__builtin_hlsl_and"]; + let Attributes = [NoThrow, Const]; + let Prototype = "void(...)"; +} + def HLSLAny : LangBuiltin<"HLSL_LANG"> { let Spellings = ["__builtin_hlsl_any"]; let Attributes = [NoThrow, Const]; diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 361e4c4bf2e2e..82527cb5e1f7a 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -19463,6 +19463,11 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, CGM.getHLSLRuntime().getAllIntrinsic(), ArrayRef{Op0}, nullptr, "hlsl.all"); } + case Builtin::BI__builtin_hlsl_and: { +Value *Op0 = EmitScalarExpr(E->getArg(0)); +Value *Op1 = EmitScalarExpr(E->getArg(1)); +return Builder.CreateAnd(Op0, Op1, "hlsl.and"); + } case Builtin::BI__builtin_hlsl_any: { Value *Op0 = EmitScalarExpr(E->getArg(0)); return Builder.CreateIntrinsic( diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index d1f5fdff8b600..7016b45d1c641 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -249,6 +249,22 @@ bool all(double3); _HLSL_BUILTIN_ALIAS(__builtin_hlsl_all) bool all(double4); +//===--===// +// and builtins +//===--===// + +// \fn bool and(bool x, bool y) +// \brief Logically ands two boolean vectors elementwise and produces a bool vector output. + +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_and) +bool and(bool x, bool y); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_and) +bool2 and(bool2 x, bool2 y); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_and) +bool3 and(bool3 x, bool3 y); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_and) +bool4 and(bool4 x, bool4 y); + //===--===// // any builtins //===--===// diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index 4abd870ad6aaa..7297fb3a9e4d0 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -2245,6 +2245,17 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { break; } + case Builtin::BI__builtin_hlsl_and: { +if (SemaRef.checkArgCount(TheCall, 2)) + return true; +if (CheckVectorElementCallArgs(&SemaRef, TheCall)) + return true; +ExprResult A = TheCall->getArg(0); +QualType ArgTyA = A.get()->getType(); +// return type is the same as the input type +TheCall->setType(ArgTyA); +break; + } case Builtin::BI__builtin_hlsl_all: case Builtin::BI__builtin_hlsl_any: { if (SemaRef.checkArgCount(TheCall, 1)) diff --git a/clang/test/CodeGenHLSL/builtins/and.hlsl b/clang/test/CodeGenHLSL/builtins/and.hlsl new file mode 100644 index 0..60295f192f5cc --- /dev/null +++ b/clang/test/CodeGenHLSL/builtins/and.hlsl @@ -0,0 +1,45 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5 +// RUN: %clang_cc1 -finclude-default-header -triple \ +// RUN: dxil-pc-shadermodel6.3-library %s \ +// RUN: -emit-llvm -O1 -o - | FileCheck %s + +// CHECK-LABEL: define noundef i1 @_Z15test_and_scalarbb( +// CHECK-SAME: i1 noundef [[X:%.*]], i1 noundef [[Y:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT:[[HLSL_AND:%.*]] = and i1 [[X]], [[Y]] +// CHECK-NEXT:ret i1 [[HLSL_AND]] +// +bool test_and_scalar(bool x, bool y) { + return and(x, y); +} + +// CHECK-LABEL: define noundef <2 x i1> @_Z14test_and_bool2Dv2_bS_( +// CHECK-SAME: <2 x i1> noundef [[X:%.*]], <2 x i1> noundef [[Y:%.
[clang] [HLSL] Implement the 'and' HLSL function (PR #127098)
@@ -2079,6 +2079,14 @@ static bool CheckFloatingOrIntRepresentation(Sema *S, CallExpr *TheCall) { checkAllSignedTypes); } +static bool CheckBoolRepresentation(Sema *S, CallExpr *TheCall) { + auto checkAllBoolTypes = [](clang::QualType PassedType) -> bool { +return !PassedType->hasIntegerRepresentation(); Icohedron wrote: `clang::QualType` does not have a `hasBooleanRepresentation();` function. I assume `hasIntegerRepresentation()` should work just fine. https://github.com/llvm/llvm-project/pull/127098 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] [DXIL] Implement the AddUint64 HLSL function and the UAddc DXIL op (PR #127137)
@@ -2229,6 +2241,41 @@ static bool CheckResourceHandle( // returning an ExprError bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { switch (BuiltinID) { + case Builtin::BI__builtin_hlsl_adduint64: { +if (SemaRef.checkArgCount(TheCall, 2)) + return true; +if (CheckVectorElementCallArgs(&SemaRef, TheCall)) + return true; +if (CheckUnsignedIntRepresentations(&SemaRef, TheCall)) + return true; + +// CheckVectorElementCallArgs(...) guarantees both args are the same type. +assert(TheCall->getArg(0)->getType() == TheCall->getArg(1)->getType() && + "Both args must be of the same type"); + +// ensure both args are vectors +auto *VTy = TheCall->getArg(0)->getType()->getAs(); +if (!VTy) { + SemaRef.Diag(TheCall->getBeginLoc(), diag::err_vec_builtin_non_vector) + << "AddUint64" << /*all*/ 1; + return true; +} + +// ensure both args have 2 elements, or both args have 4 elements +int NumElementsArg = VTy->getNumElements(); +if (NumElementsArg != 2 && NumElementsArg != 4) { + SemaRef.Diag(TheCall->getBeginLoc(), + diag::err_invalid_even_odd_vector_element_count) + << NumElementsArg << 2 << 4 << /*even*/ 0 << /*operand*/ 1; + return true; +} + Icohedron wrote: Nevermind. I found a way thanks to @bob80905 ```c++ // ensure arg integers are 32-bits CharUnits CharSize = SemaRef.getASTContext().getTypeSizeInChars(VTy->getElementType()); if (CharSize.getQuantity() != 4) { SemaRef.Diag(...); return true; } ``` https://github.com/llvm/llvm-project/pull/127137 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [HLSL] Implement the 'and' HLSL function (PR #127098)
@@ -2245,6 +2245,17 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { break; } + case Builtin::BI__builtin_hlsl_and: { +if (SemaRef.checkArgCount(TheCall, 2)) + return true; +if (CheckVectorElementCallArgs(&SemaRef, TheCall)) + return true; +ExprResult A = TheCall->getArg(0); Icohedron wrote: I think it's just difference in wording. I'm pretty sure we are talking about the same thing? If you pass a non-bool type into `__builtin_hlsl_and` then it will be implicitly converted to a bool. Hence "any type that can be implicitly cast to a bool (vector) are allowed to be passed" into it. https://github.com/llvm/llvm-project/pull/127098 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [HLSL] Implement the 'and' HLSL function (PR #127098)
@@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -finclude-default-header -triple \ +// RUN: dxil-pc-shadermodel6.3-library %s \ +// RUN: -emit-llvm -O1 -verify + +bool test_too_few_arg(bool a) { + return __builtin_hlsl_and(a); + // expected-error@-1 {{too few arguments to function call, expected 2, have 1}} +} + +bool test_too_many_arg(bool a) { + return __builtin_hlsl_and(a, a, a); + // expected-error@-1 {{too many arguments to function call, expected 2, have 3}} +} + +bool2 test_mismatched_args(bool2 a, bool3 b) { + return __builtin_hlsl_and(a, b); + // expected-error@-1 {{all arguments to '__builtin_hlsl_and' must have the same type}} +} + +struct S { + bool a; +}; + +bool test_invalid_type_conversion(S s) { + return __builtin_hlsl_and(s, s); Icohedron wrote: Actually this is a good catch. The error message is worded strangely-- it implies that `__builtin_hlsl_and` is trying to return a struct of type `S` and is failing because `S` can't be converted to a bool. I will fix this by adding a check to SemaHLSL that the argument type has a bool representation, and emitting a better error message. https://github.com/llvm/llvm-project/pull/127098 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [HLSL] Implement the 'and' HLSL function (PR #127098)
@@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -finclude-default-header -triple \ +// RUN: dxil-pc-shadermodel6.3-library %s \ +// RUN: -emit-llvm -O1 -verify + +bool test_too_few_arg(bool a) { + return __builtin_hlsl_and(a); + // expected-error@-1 {{too few arguments to function call, expected 2, have 1}} +} + +bool test_too_many_arg(bool a) { + return __builtin_hlsl_and(a, a, a); + // expected-error@-1 {{too many arguments to function call, expected 2, have 3}} +} + +bool2 test_mismatched_args(bool2 a, bool3 b) { + return __builtin_hlsl_and(a, b); + // expected-error@-1 {{all arguments to '__builtin_hlsl_and' must have the same type}} +} + +struct S { + bool a; +}; + +bool test_invalid_type_conversion(S s) { + return __builtin_hlsl_and(s, s); Icohedron wrote: Though I thought there would be something to catch errors like this when the argument type doesn't match any of the ones declared in `hlsl_intrinsics.h` https://github.com/llvm/llvm-project/pull/127098 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [HLSL] Implement the 'and' HLSL function (PR #127098)
https://github.com/Icohedron edited https://github.com/llvm/llvm-project/pull/127098 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [HLSL] Implement the 'and' HLSL function (PR #127098)
https://github.com/Icohedron edited https://github.com/llvm/llvm-project/pull/127098 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [HLSL] Implement the 'and' HLSL function (PR #127098)
https://github.com/Icohedron edited https://github.com/llvm/llvm-project/pull/127098 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [HLSL] Implement the 'and' HLSL function (PR #127098)
https://github.com/Icohedron edited https://github.com/llvm/llvm-project/pull/127098 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [HLSL] Implement the 'and' HLSL function (PR #127098)
https://github.com/Icohedron edited https://github.com/llvm/llvm-project/pull/127098 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [HLSL] Implement the 'and' HLSL function (PR #127098)
@@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -finclude-default-header -triple \ +// RUN: dxil-pc-shadermodel6.3-library %s \ +// RUN: -emit-llvm -O1 -verify + +bool test_too_few_arg(bool a) { + return __builtin_hlsl_and(a); + // expected-error@-1 {{too few arguments to function call, expected 2, have 1}} +} + +bool test_too_many_arg(bool a) { + return __builtin_hlsl_and(a, a, a); + // expected-error@-1 {{too many arguments to function call, expected 2, have 3}} +} + +bool2 test_mismatched_args(bool2 a, bool3 b) { + return __builtin_hlsl_and(a, b); + // expected-error@-1 {{all arguments to '__builtin_hlsl_and' must have the same type}} +} + +struct S { + bool a; +}; + +bool test_invalid_type_conversion(S s) { + return __builtin_hlsl_and(s, s); Icohedron wrote: Actually, there is something like that, but it seems `__builtin_hlsl_and` is triggering something else. The `D3DCOLORtoUBYTE` function doesn't have any SemaHLSL and [yet has a similar test which emits a more accurate error message](https://github.com/llvm/llvm-project/blob/main/clang/test/SemaHLSL/BuiltIns/D3DCOLORtoUBYTE4-errors.hlsl#L28). Perhaps this is just because `D3DCOLORtoUBYTE` is a header-only implementation? https://github.com/llvm/llvm-project/pull/127098 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [HLSL] Implement the 'and' HLSL function (PR #127098)
https://github.com/Icohedron edited https://github.com/llvm/llvm-project/pull/127098 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] [DXIL] Implement the AddUint64 HLSL function and the UAddc DXIL op (PR #127137)
@@ -2229,6 +2241,41 @@ static bool CheckResourceHandle( // returning an ExprError bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { switch (BuiltinID) { + case Builtin::BI__builtin_hlsl_adduint64: { +if (SemaRef.checkArgCount(TheCall, 2)) + return true; +if (CheckVectorElementCallArgs(&SemaRef, TheCall)) + return true; +if (CheckUnsignedIntRepresentations(&SemaRef, TheCall)) + return true; + +// CheckVectorElementCallArgs(...) guarantees both args are the same type. +assert(TheCall->getArg(0)->getType() == TheCall->getArg(1)->getType() && + "Both args must be of the same type"); + +// ensure both args are vectors +auto *VTy = TheCall->getArg(0)->getType()->getAs(); +if (!VTy) { + SemaRef.Diag(TheCall->getBeginLoc(), diag::err_vec_builtin_non_vector) + << "AddUint64" << /*all*/ 1; + return true; +} + +// ensure both args have 2 elements, or both args have 4 elements +int NumElementsArg = VTy->getNumElements(); +if (NumElementsArg != 2 && NumElementsArg != 4) { + SemaRef.Diag(TheCall->getBeginLoc(), + diag::err_invalid_even_odd_vector_element_count) + << NumElementsArg << 2 << 4 << /*even*/ 0 << /*operand*/ 1; + return true; +} + Icohedron wrote: uint2: `AddUint64( A:{low, high}, B:{low, high} )` and the result is one pair of 32-bit integers (low, high) uint4: `AddUint64( A:{low0, high0, low1, high1}, B:{low0, high0, low1, high1} )` is equivalent to ``` AddUint64( A:{low0, high0}, B{low0, high0} ) AddUint64( A:{low1, high1}, B{low1, high1} ) ``` so the result would be two pairs of 32-bit integers, (low0, high0) and (low1, high1), stored as a uint4: (low0, high0, low1, high1) https://github.com/llvm/llvm-project/pull/127137 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] [DXIL] Implement the AddUint64 HLSL function and the UAddc DXIL op (PR #127137)
https://github.com/Icohedron edited https://github.com/llvm/llvm-project/pull/127137 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] [DXIL] Implement the AddUint64 HLSL function and the UAddc DXIL op (PR #127137)
https://github.com/Icohedron edited https://github.com/llvm/llvm-project/pull/127137 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [HLSL] Implement the 'and' HLSL function (PR #127098)
https://github.com/Icohedron updated https://github.com/llvm/llvm-project/pull/127098 >From 5b093ca42fdc24f89bfccac25e6f2e17155432f6 Mon Sep 17 00:00:00 2001 From: Icohedron Date: Wed, 12 Feb 2025 21:24:00 + Subject: [PATCH 1/4] Implement the 'and' HLSL function --- clang/include/clang/Basic/Builtins.td| 6 +++ clang/lib/CodeGen/CGBuiltin.cpp | 5 +++ clang/lib/Headers/hlsl/hlsl_intrinsics.h | 16 +++ clang/lib/Sema/SemaHLSL.cpp | 11 + clang/test/CodeGenHLSL/builtins/and.hlsl | 45 clang/test/SemaHLSL/BuiltIns/and-errors.hlsl | 27 6 files changed, 110 insertions(+) create mode 100644 clang/test/CodeGenHLSL/builtins/and.hlsl create mode 100644 clang/test/SemaHLSL/BuiltIns/and-errors.hlsl diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 29939242596ba..de758d88f8f92 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -4765,6 +4765,12 @@ def HLSLAll : LangBuiltin<"HLSL_LANG"> { let Prototype = "bool(...)"; } +def HLSLAnd : LangBuiltin<"HLSL_LANG"> { + let Spellings = ["__builtin_hlsl_and"]; + let Attributes = [NoThrow, Const]; + let Prototype = "void(...)"; +} + def HLSLAny : LangBuiltin<"HLSL_LANG"> { let Spellings = ["__builtin_hlsl_any"]; let Attributes = [NoThrow, Const]; diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 361e4c4bf2e2e..82527cb5e1f7a 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -19463,6 +19463,11 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, CGM.getHLSLRuntime().getAllIntrinsic(), ArrayRef{Op0}, nullptr, "hlsl.all"); } + case Builtin::BI__builtin_hlsl_and: { +Value *Op0 = EmitScalarExpr(E->getArg(0)); +Value *Op1 = EmitScalarExpr(E->getArg(1)); +return Builder.CreateAnd(Op0, Op1, "hlsl.and"); + } case Builtin::BI__builtin_hlsl_any: { Value *Op0 = EmitScalarExpr(E->getArg(0)); return Builder.CreateIntrinsic( diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index d1f5fdff8b600..7016b45d1c641 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -249,6 +249,22 @@ bool all(double3); _HLSL_BUILTIN_ALIAS(__builtin_hlsl_all) bool all(double4); +//===--===// +// and builtins +//===--===// + +// \fn bool and(bool x, bool y) +// \brief Logically ands two boolean vectors elementwise and produces a bool vector output. + +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_and) +bool and(bool x, bool y); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_and) +bool2 and(bool2 x, bool2 y); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_and) +bool3 and(bool3 x, bool3 y); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_and) +bool4 and(bool4 x, bool4 y); + //===--===// // any builtins //===--===// diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index 4abd870ad6aaa..7297fb3a9e4d0 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -2245,6 +2245,17 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { break; } + case Builtin::BI__builtin_hlsl_and: { +if (SemaRef.checkArgCount(TheCall, 2)) + return true; +if (CheckVectorElementCallArgs(&SemaRef, TheCall)) + return true; +ExprResult A = TheCall->getArg(0); +QualType ArgTyA = A.get()->getType(); +// return type is the same as the input type +TheCall->setType(ArgTyA); +break; + } case Builtin::BI__builtin_hlsl_all: case Builtin::BI__builtin_hlsl_any: { if (SemaRef.checkArgCount(TheCall, 1)) diff --git a/clang/test/CodeGenHLSL/builtins/and.hlsl b/clang/test/CodeGenHLSL/builtins/and.hlsl new file mode 100644 index 0..60295f192f5cc --- /dev/null +++ b/clang/test/CodeGenHLSL/builtins/and.hlsl @@ -0,0 +1,45 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5 +// RUN: %clang_cc1 -finclude-default-header -triple \ +// RUN: dxil-pc-shadermodel6.3-library %s \ +// RUN: -emit-llvm -O1 -o - | FileCheck %s + +// CHECK-LABEL: define noundef i1 @_Z15test_and_scalarbb( +// CHECK-SAME: i1 noundef [[X:%.*]], i1 noundef [[Y:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT:[[HLSL_AND:%.*]] = and i1 [[X]], [[Y]] +// CHECK-NEXT:ret i1 [[HLSL_AND]] +// +bool test_and_scalar(bool x, bool y) { + return and(x, y); +} + +// CHECK-LABEL: define noundef <2 x i1> @_Z14test_and_bool2Dv2_bS_( +// CHECK-SAME: <2 x i1> noundef [[X:%.*]], <2 x i1> noundef [[Y:%.
[clang] [HLSL] Implement the 'and' HLSL function (PR #127098)
@@ -2245,6 +2245,17 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { break; } + case Builtin::BI__builtin_hlsl_and: { +if (SemaRef.checkArgCount(TheCall, 2)) + return true; +if (CheckVectorElementCallArgs(&SemaRef, TheCall)) + return true; +ExprResult A = TheCall->getArg(0); Icohedron wrote: Currently, any type that can be implicitly cast to a bool (vector) are allowed to be passed to the `and` HLSL builtin function. Should that be disallowed? Or is the check you mention just something to reinforce / make more clear in SemaHLSL.cpp that the `and` builtin operates only with bools? https://github.com/llvm/llvm-project/pull/127098 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] [DXIL] Implement the AddUint64 HLSL function and the UAddc DXIL op (PR #127137)
@@ -10655,6 +10655,8 @@ def err_second_argument_to_cwsc_not_pointer : Error< def err_vector_incorrect_num_elements : Error< "%select{too many|too few}0 elements in vector %select{initialization|operand}3 (expected %1 elements, have %2)">; +def err_invalid_even_odd_vector_element_count : Error< + "invalid element count of %0 in vector %select{initialization|operand}4 (expected an %select{even|odd}3 element count in the range of %1 and %2)">; Icohedron wrote: "a vector whose total size is a multiple of 64-bits" could also mean `uint16_t4` ;) But with a check for 32-bits in the integer arguments as a separate error message, it would be sufficient. Or perhaps, do you think the AddUint64 function should be generalized to accept any vector of unsigned integers whose total size is a multiple of 64-bits? Like `uint16_t4`, or potentially `uint32_t` vectors longer than 4 in the future? https://github.com/llvm/llvm-project/pull/127137 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] [DXIL] Implement the AddUint64 HLSL function and the UAddc DXIL op (PR #127137)
@@ -2229,6 +2241,41 @@ static bool CheckResourceHandle( // returning an ExprError bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { switch (BuiltinID) { + case Builtin::BI__builtin_hlsl_adduint64: { +if (SemaRef.checkArgCount(TheCall, 2)) + return true; +if (CheckVectorElementCallArgs(&SemaRef, TheCall)) + return true; +if (CheckUnsignedIntRepresentations(&SemaRef, TheCall)) + return true; + +// CheckVectorElementCallArgs(...) guarantees both args are the same type. +assert(TheCall->getArg(0)->getType() == TheCall->getArg(1)->getType() && + "Both args must be of the same type"); + +// ensure both args are vectors +auto *VTy = TheCall->getArg(0)->getType()->getAs(); +if (!VTy) { + SemaRef.Diag(TheCall->getBeginLoc(), diag::err_vec_builtin_non_vector) + << "AddUint64" << /*all*/ 1; + return true; +} + +// ensure both args have 2 elements, or both args have 4 elements +int NumElementsArg = VTy->getNumElements(); +if (NumElementsArg != 2 && NumElementsArg != 4) { + SemaRef.Diag(TheCall->getBeginLoc(), + diag::err_invalid_even_odd_vector_element_count) + << NumElementsArg << 2 << 4 << /*even*/ 0 << /*operand*/ 1; + return true; +} + Icohedron wrote: Indeed, a `uint16_t2` does slip by without diagnostics. @inbelic did suggest to check that the input integers are 32-bits, but neither of us were able to figure out how to access integer bit count from a `clang::QualType`. Perhaps you would know how it could be done? https://github.com/llvm/llvm-project/pull/127137 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] [DXIL] Implement the AddUint64 HLSL function and the UAddc DXIL op (PR #127137)
https://github.com/Icohedron updated https://github.com/llvm/llvm-project/pull/127137 >From 4fae5642c6e8e305cdc687b4968ba5eabaa44b50 Mon Sep 17 00:00:00 2001 From: Icohedron Date: Mon, 27 Jan 2025 11:18:09 -0800 Subject: [PATCH 1/3] Add the AddUint64 HLSL builtin function - Defines the AddUint64 HLSL builtin function - Implements the UAddc DXIL op to lower AddUint64 to DXIL --- clang/include/clang/Basic/Builtins.td | 6 ++ .../clang/Basic/DiagnosticSemaKinds.td| 2 + clang/lib/CodeGen/CGBuiltin.cpp | 45 clang/lib/Headers/hlsl/hlsl_intrinsics.h | 21 ++ clang/lib/Sema/SemaHLSL.cpp | 47 .../test/CodeGenHLSL/builtins/AddUint64.hlsl | 71 +++ .../SemaHLSL/BuiltIns/AddUint64-errors.hlsl | 41 +++ llvm/lib/Target/DirectX/DXIL.td | 13 llvm/lib/Target/DirectX/DXILOpBuilder.cpp | 14 llvm/lib/Target/DirectX/DXILOpBuilder.h | 3 + llvm/lib/Target/DirectX/DXILOpLowering.cpp| 22 -- llvm/test/CodeGen/DirectX/UAddc.ll| 40 +++ llvm/test/CodeGen/DirectX/UAddc_errors.ll | 30 13 files changed, 348 insertions(+), 7 deletions(-) create mode 100644 clang/test/CodeGenHLSL/builtins/AddUint64.hlsl create mode 100644 clang/test/SemaHLSL/BuiltIns/AddUint64-errors.hlsl create mode 100644 llvm/test/CodeGen/DirectX/UAddc.ll create mode 100644 llvm/test/CodeGen/DirectX/UAddc_errors.ll diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 29939242596ba..2433427a89429 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -4753,6 +4753,12 @@ def GetDeviceSideMangledName : LangBuiltin<"CUDA_LANG"> { } // HLSL +def HLSLAddUint64: LangBuiltin<"HLSL_LANG"> { + let Spellings = ["__builtin_hlsl_adduint64"]; + let Attributes = [NoThrow, Const]; + let Prototype = "void(...)"; +} + def HLSLResourceGetPointer : LangBuiltin<"HLSL_LANG"> { let Spellings = ["__builtin_hlsl_resource_getpointer"]; let Attributes = [NoThrow]; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 2fce5e88ba8a0..e78339ee924ff 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -10655,6 +10655,8 @@ def err_second_argument_to_cwsc_not_pointer : Error< def err_vector_incorrect_num_elements : Error< "%select{too many|too few}0 elements in vector %select{initialization|operand}3 (expected %1 elements, have %2)">; +def err_invalid_even_odd_vector_element_count : Error< + "invalid element count of %0 in vector %select{initialization|operand}4 (expected an %select{even|odd}3 element count in the range of %1 and %2)">; def err_altivec_empty_initializer : Error<"expected initializer">; def err_invalid_neon_type_code : Error< diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 361e4c4bf2e2e..5322b38458b26 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -19445,6 +19445,51 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, return nullptr; switch (BuiltinID) { + case Builtin::BI__builtin_hlsl_adduint64: { +Value *OpA = EmitScalarExpr(E->getArg(0)); +Value *OpB = EmitScalarExpr(E->getArg(1)); +assert(E->getArg(0)->getType()->hasIntegerRepresentation() && + E->getArg(1)->getType()->hasIntegerRepresentation() && + "AddUint64 operands must have an integer representation"); +assert(((E->getArg(0)->getType()->castAs()->getNumElements() == + 2 && + E->getArg(1)->getType()->castAs()->getNumElements() == + 2) || +(E->getArg(0)->getType()->castAs()->getNumElements() == + 4 && + E->getArg(1)->getType()->castAs()->getNumElements() == + 4)) && + "input vectors must have 2 or 4 elements each"); + +llvm::Value *Result = PoisonValue::get(OpA->getType()); +uint64_t NumElements = +E->getArg(0)->getType()->castAs()->getNumElements(); +for (uint64_t i = 0; i < NumElements / 2; ++i) { + + // Obtain low and high words of inputs A and B + llvm::Value *LowA = Builder.CreateExtractElement(OpA, 2 * i + 0); + llvm::Value *HighA = Builder.CreateExtractElement(OpA, 2 * i + 1); + llvm::Value *LowB = Builder.CreateExtractElement(OpB, 2 * i + 0); + llvm::Value *HighB = Builder.CreateExtractElement(OpB, 2 * i + 1); + + // Use an uadd_with_overflow to compute the sum of low words and obtain a + // carry value + llvm::Value *Carry; + llvm::Value *LowSum = EmitOverflowIntrinsic( + *this, llvm::Intrinsic::uadd_with_overflow, LowA, LowB, Carry); + llvm::Value *ZExtCarry = Builder.CreateZExt(Carry, HighA->getType()); + + // Sum the high words and the carry
[clang] [llvm] [HLSL] [DXIL] Implement the AddUint64 HLSL function and the UAddc DXIL op (PR #127137)
@@ -2229,6 +2241,41 @@ static bool CheckResourceHandle( // returning an ExprError bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { switch (BuiltinID) { + case Builtin::BI__builtin_hlsl_adduint64: { +if (SemaRef.checkArgCount(TheCall, 2)) + return true; +if (CheckVectorElementCallArgs(&SemaRef, TheCall)) + return true; +if (CheckUnsignedIntRepresentations(&SemaRef, TheCall)) + return true; + +// CheckVectorElementCallArgs(...) guarantees both args are the same type. +assert(TheCall->getArg(0)->getType() == TheCall->getArg(1)->getType() && + "Both args must be of the same type"); + +// ensure both args are vectors +auto *VTy = TheCall->getArg(0)->getType()->getAs(); +if (!VTy) { + SemaRef.Diag(TheCall->getBeginLoc(), diag::err_vec_builtin_non_vector) + << "AddUint64" << /*all*/ 1; + return true; +} + +// ensure both args have 2 elements, or both args have 4 elements +int NumElementsArg = VTy->getNumElements(); +if (NumElementsArg != 2 && NumElementsArg != 4) { + SemaRef.Diag(TheCall->getBeginLoc(), + diag::err_invalid_even_odd_vector_element_count) + << NumElementsArg << 2 << 4 << /*even*/ 0 << /*operand*/ 1; + return true; +} + Icohedron wrote: The 4-element vector size version of AddUint64 is the same as the 2-element vector size version of AddUint64 performed twice. AddUint64 returns a uint2 when its args are uint2, and AddUint64 returns a uint4 when its args are uint4. https://github.com/llvm/llvm-project/pull/127137 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [HLSL] Implement the 'and' HLSL function (PR #127098)
https://github.com/Icohedron edited https://github.com/llvm/llvm-project/pull/127098 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [HLSL] Implement the 'and' HLSL function (PR #127098)
@@ -2245,6 +2245,36 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { break; } + case Builtin::BI__builtin_hlsl_and: { +if (SemaRef.checkArgCount(TheCall, 2)) + return true; +if (CheckVectorElementCallArgs(&SemaRef, TheCall)) + return true; + +// CheckVectorElementCallArgs(...) guarantees both args are the same type. +assert(TheCall->getArg(0)->getType() == TheCall->getArg(1)->getType() && + "Both args must be of the same type"); + +// check that the arguments are bools or, if vectors, +// vectors of bools +QualType ArgTy = TheCall->getArg(0)->getType(); +if (const auto *VecTy = ArgTy->getAs()) { + ArgTy = VecTy->getElementType(); +} +if (!getASTContext().hasSameUnqualifiedType(ArgTy, Icohedron wrote: I did try that. I had defined the following function: ```c++ static bool CheckBoolRepresentation(Sema *S, CallExpr *TheCall) { auto checkAllBoolTypes = [](clang::QualType PassedType) -> bool { return !PassedType->isBooleanType(); }; return CheckAllArgTypesAreCorrect(S, TheCall, S->Context.BoolTy, checkAllBoolTypes); } ``` and when I tried to use it, I got a strange errors when running the test ``` TEST 'Clang :: CodeGenHLSL/builtins/and.hlsl' FAILED *** * Exit Code: 2 Command Output (stderr): -- TEST 'Clang :: CodeGenHLSL/builtins/and.hlsl' FAILED *** * Exit Code: 2 Command Output (stderr): -- RUN: at line 2: /workspace/feature-and/build/bin/clang -cc1 -internal-isystem /workspace/feature-and/build/lib/clang/21/include -nostdsysteminc -finclude-default-header -tripledxil-pc-shadermodel6.3-library /workspace/feature-and/clang/test/CodeGenHLSL/builtins/and.hlsl-emit-llvm -O1 -o - | /workspace/feature-and/build/bin/FileCheck /workspace/feature-and/clang/test/CodeGenHLSL/builtins/and.hlsl + /workspace/feature-and/build/bin/clang -cc1 -internal-isystem /workspace/feature-and/build/lib/clang/21/include -nostdsysteminc -finclude-default-header -triple dxil-pc-shadermodel6.3-library /workspace/feature-and/clang/test/CodeGenHLSL/builtins/and.hlsl -emit-llvm -O1 -o - + /workspace/feature-and/build/bin/FileCheck /workspace/feature-and/clang/test/CodeGenHLSL/builtins/and.hlsl /workspace/feature-and/clang/test/CodeGenHLSL/builtins/and.hlsl:23:14: error: passing 'bool2' (aka 'vector') to parameter of incompatible type '__attribute__((__vector_size__(2 * sizeof(bool bool' (vector of 2 'bool' values) 23 | return and(x, y); | ^ /workspace/feature-and/clang/test/CodeGenHLSL/builtins/and.hlsl:33:14: error: passing 'bool3' (aka 'vector') to parameter of incompatible type '__attribute__((__vector_size__(3 * sizeof(bool bool' (vector of 3 'bool' values) 33 | return and(x, y); | ^ /workspace/feature-and/clang/test/CodeGenHLSL/builtins/and.hlsl:43:14: error: passing 'bool4' (aka 'vector') to parameter of incompatible type '__attribute__((__vector_size__(4 * sizeof(bool bool' (vector of 4 'bool' values) 43 | return and(x, y); | ^ /workspace/feature-and/clang/test/CodeGenHLSL/builtins/and.hlsl:55:14: error: passing 'vector' (vector of 4 'bool' values) to parameter of incompatible type '__attribute__((__vector_size__(4 * sizeof(bool bool' (vector of 4 'bool' values) 55 | return and(x, y); | ^ /workspace/feature-and/clang/test/CodeGenHLSL/builtins/and.hlsl:67:14: error: passing 'vector' (vector of 4 'bool' values) to parameter of incompatible type '__attribute__((__vector_size__(4 * sizeof(bool bool' (vector of 4 'bool' values) 67 | return and(x, y); | ^ 5 errors generated. FileCheck error: '' is empty. FileCheck command line: /workspace/feature-and/build/bin/FileCheck /workspace/feature-and/clang/test/CodeGenHLSL/builtins/and.hlsl -- ``` https://github.com/llvm/llvm-project/pull/127098 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [HLSL] Implement the 'and' HLSL function (PR #127098)
https://github.com/Icohedron edited https://github.com/llvm/llvm-project/pull/127098 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits