Skip to content

Commit

Permalink
adding clang codegen
Browse files Browse the repository at this point in the history
  • Loading branch information
joaosaffran-zz committed Sep 19, 2024
1 parent 1335a11 commit 8f21239
Show file tree
Hide file tree
Showing 9 changed files with 137 additions and 10 deletions.
6 changes: 6 additions & 0 deletions clang/include/clang/Basic/Builtins.td
Original file line number Diff line number Diff line change
Expand Up @@ -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"];
Expand Down
36 changes: 35 additions & 1 deletion clang/lib/CodeGen/CGBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18824,6 +18824,40 @@ 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);
}

auto ptr = CreateMemTemp(E->getArg(1)->getType());
EmitAnyExprToMem(E->getArg(1), ptr, Qualifiers(), /*init*/ true);
Address x = EmitPointerWithAlignment(E->getArg(1));

CallInst *CI =
Builder.CreateIntrinsic(retType, llvm::Intrinsic::dx_asuint_splitdouble,
{Op0}, nullptr, "hlsl.asuint");

// Value* arg1 = Builder.CreateExtractValue(CI, 1);

// Address y = EmitPointerWithAlignment(E->getArg(2));
// Builder.CreateLoad(ptr);
// return Builder.CreateStore(arg1, ptr);
}
}
return nullptr;
}
Expand Down Expand Up @@ -22398,4 +22432,4 @@ Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID,

llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
return Builder.CreateCall(F, Ops, "");
}
}
1 change: 0 additions & 1 deletion clang/lib/CodeGen/CGHLSLRuntime.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
//===----------------------------------------------------------------------===//
Expand Down
20 changes: 20 additions & 0 deletions clang/lib/Headers/hlsl/hlsl_intrinsics.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
//===----------------------------------------------------------------------===//
Expand Down
56 changes: 48 additions & 8 deletions clang/lib/Sema/SemaHLSL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
Expand Down Expand Up @@ -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:
Expand Down
9 changes: 9 additions & 0 deletions clang/test/CodeGenHLSL/builtins/asuint-splitdouble.hlsl
Original file line number Diff line number Diff line change
@@ -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;
}
5 changes: 5 additions & 0 deletions llvm/include/llvm/IR/IntrinsicsDirectX.td
Original file line number Diff line number Diff line change
Expand Up @@ -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]>;
}
1 change: 1 addition & 0 deletions llvm/lib/Target/DirectX/DXIL.td
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down
13 changes: 13 additions & 0 deletions llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit 8f21239

Please sign in to comment.