https://github.com/joaosaffran updated https://github.com/llvm/llvm-project/pull/109331
>From 0059eb9640cad23ef2a7178c6b0eca327f5db6da Mon Sep 17 00:00:00 2001 From: Joao Saffran <jdereze...@microsoft.com> Date: Thu, 19 Sep 2024 00:13:51 +0000 Subject: [PATCH] adding clang codegen --- clang/include/clang/Basic/Builtins.td | 6 ++ clang/lib/CodeGen/CGBuiltin.cpp | 28 ++++++++++ clang/lib/CodeGen/CGExprScalar.cpp | 5 ++ clang/lib/CodeGen/CGHLSLRuntime.h | 1 - clang/lib/Headers/hlsl/hlsl_intrinsics.h | 20 +++++++ clang/lib/Sema/SemaHLSL.cpp | 56 ++++++++++++++++--- .../builtins/asuint-splitdouble.hlsl | 9 +++ llvm/include/llvm/IR/IntrinsicsDirectX.td | 5 ++ llvm/lib/Target/DirectX/DXIL.td | 1 + .../Target/DirectX/DXILIntrinsicExpansion.cpp | 13 +++++ 10 files changed, 135 insertions(+), 9 deletions(-) create mode 100644 clang/test/CodeGenHLSL/builtins/asuint-splitdouble.hlsl diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 8c5d7ad763bf97..b38957f6e3f15d 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -4788,6 +4788,12 @@ def HLSLStep: LangBuiltin<"HLSL_LANG"> { let Prototype = "void(...)"; } +def HLSLAsUintSplitDouble: LangBuiltin<"HLSL_LANG"> { + let Spellings = ["__builtin_hlsl_asuint_splitdouble"]; + let Attributes = [NoThrow, Const]; + let Prototype = "void(...)"; +} + // Builtins for XRay. def XRayCustomEvent : Builtin { let Spellings = ["__xray_customevent"]; diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index e2711f1ba70239..0c000645ffe234 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// #include "ABIInfo.h" +#include "Address.h" #include "CGCUDARuntime.h" #include "CGCXXABI.h" #include "CGHLSLRuntime.h" @@ -18824,6 +18825,33 @@ case Builtin::BI__builtin_hlsl_elementwise_isinf: { retType, CGM.getHLSLRuntime().getSignIntrinsic(), ArrayRef<Value *>{Op0}, nullptr, "hlsl.sign"); } + // This should only be called when targeting DXIL + case Builtin::BI__builtin_hlsl_asuint_splitdouble: { + + assert( (E->getArg(0)->getType()->isDoubleType() && + E->getArg(1)->getType()->isUnsignedIntegerType() && + E->getArg(2)->getType()->isUnsignedIntegerType()) || + "asuint operands types mismatch"); + + Value *Op0 = EmitScalarExpr(E->getArg(0)); + llvm::Type *retType = llvm::StructType::get(Int32Ty, Int32Ty); + if (Op0->getType()->isVectorTy()) { + auto *XVecTy = E->getArg(0)->getType()->getAs<VectorType>(); + + llvm::VectorType *i32VecTy = llvm::VectorType::get( + Int32Ty, ElementCount::getFixed(XVecTy->getNumElements())); + + retType = llvm::StructType::get(i32VecTy, i32VecTy); + } + + CallInst *CI = + Builder.CreateIntrinsic(retType, llvm::Intrinsic::dx_asuint_splitdouble, + {Op0}, nullptr, "hlsl.asuint"); + + Value* arg1 = Builder.CreateExtractValue(CI, 1); + auto addr = EmitPointerWithAlignment(E->getArg(1)); + return Builder.CreateStore(arg1,addr); + } } return nullptr; } diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 82caf65ac68d6b..7bcc61c74a9b1f 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -43,6 +43,7 @@ #include "llvm/IR/IntrinsicsPowerPC.h" #include "llvm/IR/MatrixBuilder.h" #include "llvm/IR/Module.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/TypeSize.h" #include <cstdarg> #include <optional> @@ -476,6 +477,10 @@ class ScalarExprEmitter return Visit(E->getSubExpr()); } + Value *VisitHLSLOutArgExpr(HLSLOutArgExpr *E){ + return Visit(E->getArgLValue()); + } + // Leaves. Value *VisitIntegerLiteral(const IntegerLiteral *E) { return Builder.getInt(E->getValue()); diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h index a8aabca7348ffb..74876657646d07 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.h +++ b/clang/lib/CodeGen/CGHLSLRuntime.h @@ -87,7 +87,6 @@ class CGHLSLRuntime { GENERATE_HLSL_INTRINSIC_FUNCTION(SDot, sdot) GENERATE_HLSL_INTRINSIC_FUNCTION(UDot, udot) GENERATE_HLSL_INTRINSIC_FUNCTION(WaveIsFirstLane, wave_is_first_lane) - //===----------------------------------------------------------------------===// // End of reserved area for HLSL intrinsic getters. //===----------------------------------------------------------------------===// diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index 6cd6a2caf19994..d48b60bab16d51 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -423,6 +423,26 @@ template <typename T> _HLSL_INLINE uint asuint(T F) { return __detail::bit_cast<uint, T>(F); } +//===----------------------------------------------------------------------===// +// asuint splitdouble builtins +//===----------------------------------------------------------------------===// + +/// \fn void asuint(double D, out uint lowbits, out int highbits) +/// \brief Split and interprets the lowbits and highbits of double D into uints. +/// \param D The input double. +/// \param lowbits The output lowbits of D. +/// \param highbits The highbits lowbits D. +#if __is_target_arch(dxil) +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_asuint_splitdouble) +void asuint(double, out uint, out uint); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_asuint_splitdouble) +void asuint(double2, out uint2, out uint2); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_asuint_splitdouble) +void asuint(double3, out uint3, out uint3); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_asuint_splitdouble) +void asuint(double4, out uint4, out uint4); +#endif + //===----------------------------------------------------------------------===// // atan builtins //===----------------------------------------------------------------------===// diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index 03b7c2edb605fe..f8c388dcc1df81 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -1467,18 +1467,27 @@ bool CheckVectorElementCallArgs(Sema *S, CallExpr *TheCall) { return true; } +bool CheckArgTypeIsCorrect( + Sema *S, Expr *Arg, QualType ExpectedType, + llvm::function_ref<bool(clang::QualType PassedType)> Check) { + QualType PassedType = Arg->getType(); + if (Check(PassedType)) { + if (auto *VecTyA = PassedType->getAs<VectorType>()) + ExpectedType = S->Context.getVectorType( + ExpectedType, VecTyA->getNumElements(), VecTyA->getVectorKind()); + S->Diag(Arg->getBeginLoc(), diag::err_typecheck_convert_incompatible) + << PassedType << ExpectedType << 1 << 0 << 0; + return true; + } + return false; +} + bool CheckArgsTypesAreCorrect( Sema *S, CallExpr *TheCall, QualType ExpectedType, llvm::function_ref<bool(clang::QualType PassedType)> Check) { for (unsigned i = 0; i < TheCall->getNumArgs(); ++i) { - QualType PassedType = TheCall->getArg(i)->getType(); - if (Check(PassedType)) { - if (auto *VecTyA = PassedType->getAs<VectorType>()) - ExpectedType = S->Context.getVectorType( - ExpectedType, VecTyA->getNumElements(), VecTyA->getVectorKind()); - S->Diag(TheCall->getArg(0)->getBeginLoc(), - diag::err_typecheck_convert_incompatible) - << PassedType << ExpectedType << 1 << 0 << 0; + Expr *Arg = TheCall->getArg(i); + if (CheckArgTypeIsCorrect(S, Arg, ExpectedType, Check)) { return true; } } @@ -1762,6 +1771,37 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { return true; break; } + case Builtin::BI__builtin_hlsl_asuint_splitdouble: { + if (SemaRef.checkArgCount(TheCall, 3)) + return true; + + Expr *Op0 = TheCall->getArg(0); + + auto CheckIsNotDouble = [](clang::QualType PassedType) -> bool { + return !PassedType->isDoubleType(); + }; + + if (CheckArgTypeIsCorrect(&SemaRef, Op0, SemaRef.Context.DoubleTy, + CheckIsNotDouble)) { + return true; + } + + Expr *Op1 = TheCall->getArg(1); + Expr *Op2 = TheCall->getArg(2); + + auto CheckIsNotUint = [](clang::QualType PassedType) -> bool { + return !PassedType->isUnsignedIntegerType(); + }; + + if (CheckArgTypeIsCorrect(&SemaRef, Op1, SemaRef.Context.UnsignedIntTy, + CheckIsNotUint) || + CheckArgTypeIsCorrect(&SemaRef, Op2, SemaRef.Context.UnsignedIntTy, + CheckIsNotUint)) { + return true; + } + + break; + } case Builtin::BI__builtin_elementwise_acos: case Builtin::BI__builtin_elementwise_asin: case Builtin::BI__builtin_elementwise_atan: diff --git a/clang/test/CodeGenHLSL/builtins/asuint-splitdouble.hlsl b/clang/test/CodeGenHLSL/builtins/asuint-splitdouble.hlsl new file mode 100644 index 00000000000000..1dc8017cfd9421 --- /dev/null +++ b/clang/test/CodeGenHLSL/builtins/asuint-splitdouble.hlsl @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s -fnative-half-type -emit-llvm -O0 -o - | FileCheck %s + +// CHECK: define {{.*}}test_scalar{{.*}}(double {{.*}} [[VAL1:%.*]], i32 {{.*}} [[VAL2:%.*]], i32 {{.*}} [[VAL3:%.*]]){{.*}} +// CHECK: [[VALD:%.*]] = load double, ptr [[VAL1]].addr{{.*}} +// CHECK: call { i32, i32 } @llvm.dx.asuint.splitdouble.{{.*}}(double [[VALD]]) +uint test_scalar(double d, uint lb, uint hb) { + asuint(d, lb, hb); + return lb; +} \ No newline at end of file diff --git a/llvm/include/llvm/IR/IntrinsicsDirectX.td b/llvm/include/llvm/IR/IntrinsicsDirectX.td index 3ce7b8b987ef86..d8092397881550 100644 --- a/llvm/include/llvm/IR/IntrinsicsDirectX.td +++ b/llvm/include/llvm/IR/IntrinsicsDirectX.td @@ -88,4 +88,9 @@ def int_dx_rsqrt : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>] def int_dx_wave_is_first_lane : DefaultAttrsIntrinsic<[llvm_i1_ty], [], [IntrConvergent]>; def int_dx_sign : DefaultAttrsIntrinsic<[LLVMScalarOrSameVectorWidth<0, llvm_i32_ty>], [llvm_any_ty], [IntrNoMem]>; def int_dx_step : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty, LLVMMatchType<0>], [IntrNoMem]>; + +def int_dx_asuint_splitdouble : DefaultAttrsIntrinsic< + [llvm_anyint_ty, LLVMMatchType<0>], + [LLVMScalarOrSameVectorWidth<0, llvm_double_ty>], + [IntrNoMem, IntrWillReturn]>; } diff --git a/llvm/lib/Target/DirectX/DXIL.td b/llvm/lib/Target/DirectX/DXIL.td index 9aa0af3e3a6b17..06c52da5fc07c8 100644 --- a/llvm/lib/Target/DirectX/DXIL.td +++ b/llvm/lib/Target/DirectX/DXIL.td @@ -778,6 +778,7 @@ def FlattenedThreadIdInGroup : DXILOp<96, flattenedThreadIdInGroup> { let stages = [Stages<DXIL1_0, [compute, mesh, amplification, node]>]; let attributes = [Attributes<DXIL1_0, [ReadNone]>]; } +// def AnnotateHandle : DXILOp<217, annotateHandle> { let Doc = "annotate handle with resource properties"; diff --git a/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp b/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp index dd73b895b14d37..2bc9ebc962e71a 100644 --- a/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp +++ b/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp @@ -12,6 +12,7 @@ #include "DXILIntrinsicExpansion.h" #include "DirectX.h" +#include "llvm-c/Core.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Analysis/DXILResource.h" @@ -346,6 +347,15 @@ static Value *expandStepIntrinsic(CallInst *Orig) { return Builder.CreateSelect(Cond, Zero, One); } +// static Value *expandSplitdoubleIntrinsic(CallInst *Orig) { +// Value *X = Orig->getOperand(0); +// Type *Ty = X->getType(); +// IRBuilder<> Builder(Orig); + +// Builder.CreateIntrinsic() + +// } + static Intrinsic::ID getMaxForClamp(Type *ElemTy, Intrinsic::ID ClampIntrinsic) { if (ClampIntrinsic == Intrinsic::dx_uclamp) @@ -459,6 +469,9 @@ static bool expandIntrinsic(Function &F, CallInst *Orig) { break; case Intrinsic::dx_step: Result = expandStepIntrinsic(Orig); + break; + // case Intrinsic::dx_asuint_splitdouble: + // Result = expandSplitdoubleIntrinsic(Orig); } if (Result) { Orig->replaceAllUsesWith(Result); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits