Skip to content

Commit 13a095c

Browse files
Codegen builtin
1 parent 1335a11 commit 13a095c

File tree

11 files changed

+166
-13
lines changed

11 files changed

+166
-13
lines changed

clang/include/clang/Basic/Builtins.td

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4788,6 +4788,12 @@ def HLSLStep: LangBuiltin<"HLSL_LANG"> {
47884788
let Prototype = "void(...)";
47894789
}
47904790

4791+
def HLSLAsUintSplitDouble: LangBuiltin<"HLSL_LANG"> {
4792+
let Spellings = ["__builtin_hlsl_asuint_splitdouble"];
4793+
let Attributes = [NoThrow, Const];
4794+
let Prototype = "void(...)";
4795+
}
4796+
47914797
// Builtins for XRay.
47924798
def XRayCustomEvent : Builtin {
47934799
let Spellings = ["__xray_customevent"];

clang/lib/CodeGen/CGBuiltin.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18824,6 +18824,44 @@ case Builtin::BI__builtin_hlsl_elementwise_isinf: {
1882418824
retType, CGM.getHLSLRuntime().getSignIntrinsic(),
1882518825
ArrayRef<Value *>{Op0}, nullptr, "hlsl.sign");
1882618826
}
18827+
// This should only be called when targeting DXIL
18828+
case Builtin::BI__builtin_hlsl_asuint_splitdouble: {
18829+
18830+
assert((E->getArg(0)->getType()->hasFloatingRepresentation() &&
18831+
E->getArg(1)->getType()->hasUnsignedIntegerRepresentation() &&
18832+
E->getArg(2)->getType()->hasUnsignedIntegerRepresentation()) &&
18833+
"asuint operands types mismatch");
18834+
18835+
Value *Op0 = EmitScalarExpr(E->getArg(0));
18836+
const HLSLOutArgExpr *OutArg1 = dyn_cast<HLSLOutArgExpr>(E->getArg(1));
18837+
const HLSLOutArgExpr *OutArg2 = dyn_cast<HLSLOutArgExpr>(E->getArg(2));
18838+
18839+
CallArgList Args;
18840+
LValue Op1TmpLValue = EmitHLSLOutArgExpr(OutArg1, Args, OutArg1->getType());
18841+
LValue Op2TmpLValue = EmitHLSLOutArgExpr(OutArg2, Args, OutArg2->getType());
18842+
18843+
llvm::Type *retType = llvm::StructType::get(Int32Ty, Int32Ty);
18844+
if (Op0->getType()->isVectorTy()) {
18845+
auto *XVecTy = E->getArg(0)->getType()->getAs<VectorType>();
18846+
18847+
llvm::VectorType *i32VecTy = llvm::VectorType::get(
18848+
Int32Ty, ElementCount::getFixed(XVecTy->getNumElements()));
18849+
18850+
retType = llvm::StructType::get(i32VecTy, i32VecTy);
18851+
}
18852+
18853+
CallInst *CI =
18854+
Builder.CreateIntrinsic(retType, llvm::Intrinsic::dx_asuint_splitdouble,
18855+
{Op0}, nullptr, "hlsl.asuint");
18856+
18857+
Value *arg0 = Builder.CreateExtractValue(CI, 0);
18858+
Value *arg1 = Builder.CreateExtractValue(CI, 1);
18859+
18860+
Builder.CreateStore(arg0, Op1TmpLValue.getAddress());
18861+
auto *s = Builder.CreateStore(arg1, Op2TmpLValue.getAddress());
18862+
EmitWritebacks(*this, Args);
18863+
return s;
18864+
}
1882718865
}
1882818866
return nullptr;
1882918867
}

clang/lib/CodeGen/CGCall.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4681,6 +4681,11 @@ void CallArg::copyInto(CodeGenFunction &CGF, Address Addr) const {
46814681
IsUsed = true;
46824682
}
46834683

4684+
void CodeGenFunction::EmitWritebacks(CodeGenFunction &CGF,
4685+
const CallArgList &args) {
4686+
emitWritebacks(CGF, args);
4687+
}
4688+
46844689
void CodeGenFunction::EmitCallArg(CallArgList &args, const Expr *E,
46854690
QualType type) {
46864691
DisableDebugLocationUpdates Dis(*this, E);

clang/lib/CodeGen/CGExpr.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "CGObjCRuntime.h"
2020
#include "CGOpenMPRuntime.h"
2121
#include "CGRecordLayout.h"
22+
#include "CGValue.h"
2223
#include "CodeGenFunction.h"
2324
#include "CodeGenModule.h"
2425
#include "ConstantEmitter.h"
@@ -28,6 +29,7 @@
2829
#include "clang/AST/DeclObjC.h"
2930
#include "clang/AST/NSAPI.h"
3031
#include "clang/AST/StmtVisitor.h"
32+
#include "clang/AST/Type.h"
3133
#include "clang/Basic/Builtins.h"
3234
#include "clang/Basic/CodeGenOptions.h"
3335
#include "clang/Basic/SourceManager.h"
@@ -5458,9 +5460,8 @@ LValue CodeGenFunction::EmitOpaqueValueLValue(const OpaqueValueExpr *e) {
54585460
return getOrCreateOpaqueLValueMapping(e);
54595461
}
54605462

5461-
void CodeGenFunction::EmitHLSLOutArgExpr(const HLSLOutArgExpr *E,
5462-
CallArgList &Args, QualType Ty) {
5463-
5463+
std::pair<LValue, LValue>
5464+
CodeGenFunction::EmitHLSLOutArgLValues(const HLSLOutArgExpr *E, QualType Ty) {
54645465
// Emitting the casted temporary through an opaque value.
54655466
LValue BaseLV = EmitLValue(E->getArgLValue());
54665467
OpaqueValueMappingData::bind(*this, E->getOpaqueArgLValue(), BaseLV);
@@ -5474,6 +5475,13 @@ void CodeGenFunction::EmitHLSLOutArgExpr(const HLSLOutArgExpr *E,
54745475
TempLV);
54755476

54765477
OpaqueValueMappingData::bind(*this, E->getCastedTemporary(), TempLV);
5478+
return std::make_pair(BaseLV, TempLV);
5479+
}
5480+
5481+
LValue CodeGenFunction::EmitHLSLOutArgExpr(const HLSLOutArgExpr *E,
5482+
CallArgList &Args, QualType Ty) {
5483+
5484+
auto [BaseLV, TempLV] = EmitHLSLOutArgLValues(E, Ty);
54775485

54785486
llvm::Value *Addr = TempLV.getAddress().getBasePointer();
54795487
llvm::Type *ElTy = ConvertTypeForMem(TempLV.getType());
@@ -5486,6 +5494,7 @@ void CodeGenFunction::EmitHLSLOutArgExpr(const HLSLOutArgExpr *E,
54865494
Args.addWriteback(BaseLV, TmpAddr, nullptr, E->getWritebackCast(),
54875495
LifetimeSize);
54885496
Args.add(RValue::get(TmpAddr, *this), Ty);
5497+
return TempLV;
54895498
}
54905499

54915500
LValue

clang/lib/CodeGen/CodeGenFunction.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4296,8 +4296,11 @@ class CodeGenFunction : public CodeGenTypeCache {
42964296
LValue EmitCastLValue(const CastExpr *E);
42974297
LValue EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *E);
42984298
LValue EmitOpaqueValueLValue(const OpaqueValueExpr *e);
4299-
void EmitHLSLOutArgExpr(const HLSLOutArgExpr *E, CallArgList &Args,
4300-
QualType Ty);
4299+
4300+
std::pair<LValue, LValue> EmitHLSLOutArgLValues(const HLSLOutArgExpr *E,
4301+
QualType Ty);
4302+
LValue EmitHLSLOutArgExpr(const HLSLOutArgExpr *E, CallArgList &Args,
4303+
QualType Ty);
43014304

43024305
Address EmitExtVectorElementLValue(LValue V);
43034306

@@ -5145,6 +5148,9 @@ class CodeGenFunction : public CodeGenTypeCache {
51455148
SourceLocation ArgLoc, AbstractCallee AC,
51465149
unsigned ParmNum);
51475150

5151+
/// EmitWriteback - Emit callbacks for function.
5152+
void EmitWritebacks(CodeGenFunction &CGF, const CallArgList &args);
5153+
51485154
/// EmitCallArg - Emit a single call argument.
51495155
void EmitCallArg(CallArgList &args, const Expr *E, QualType ArgType);
51505156

clang/lib/Headers/hlsl/hlsl_intrinsics.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,26 @@ template <typename T> _HLSL_INLINE uint asuint(T F) {
423423
return __detail::bit_cast<uint, T>(F);
424424
}
425425

426+
//===----------------------------------------------------------------------===//
427+
// asuint splitdouble builtins
428+
//===----------------------------------------------------------------------===//
429+
430+
/// \fn void asuint(double D, out uint lowbits, out int highbits)
431+
/// \brief Split and interprets the lowbits and highbits of double D into uints.
432+
/// \param D The input double.
433+
/// \param lowbits The output lowbits of D.
434+
/// \param highbits The highbits lowbits D.
435+
#if __is_target_arch(dxil)
436+
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_asuint_splitdouble)
437+
void asuint(double, out uint, out uint);
438+
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_asuint_splitdouble)
439+
void asuint(double2, out uint2, out uint2);
440+
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_asuint_splitdouble)
441+
void asuint(double3, out uint3, out uint3);
442+
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_asuint_splitdouble)
443+
void asuint(double4, out uint4, out uint4);
444+
#endif
445+
426446
//===----------------------------------------------------------------------===//
427447
// atan builtins
428448
//===----------------------------------------------------------------------===//

clang/lib/Sema/SemaHLSL.cpp

Lines changed: 48 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1467,18 +1467,27 @@ bool CheckVectorElementCallArgs(Sema *S, CallExpr *TheCall) {
14671467
return true;
14681468
}
14691469

1470+
bool CheckArgTypeIsCorrect(
1471+
Sema *S, Expr *Arg, QualType ExpectedType,
1472+
llvm::function_ref<bool(clang::QualType PassedType)> Check) {
1473+
QualType PassedType = Arg->getType();
1474+
if (Check(PassedType)) {
1475+
if (auto *VecTyA = PassedType->getAs<VectorType>())
1476+
ExpectedType = S->Context.getVectorType(
1477+
ExpectedType, VecTyA->getNumElements(), VecTyA->getVectorKind());
1478+
S->Diag(Arg->getBeginLoc(), diag::err_typecheck_convert_incompatible)
1479+
<< PassedType << ExpectedType << 1 << 0 << 0;
1480+
return true;
1481+
}
1482+
return false;
1483+
}
1484+
14701485
bool CheckArgsTypesAreCorrect(
14711486
Sema *S, CallExpr *TheCall, QualType ExpectedType,
14721487
llvm::function_ref<bool(clang::QualType PassedType)> Check) {
14731488
for (unsigned i = 0; i < TheCall->getNumArgs(); ++i) {
1474-
QualType PassedType = TheCall->getArg(i)->getType();
1475-
if (Check(PassedType)) {
1476-
if (auto *VecTyA = PassedType->getAs<VectorType>())
1477-
ExpectedType = S->Context.getVectorType(
1478-
ExpectedType, VecTyA->getNumElements(), VecTyA->getVectorKind());
1479-
S->Diag(TheCall->getArg(0)->getBeginLoc(),
1480-
diag::err_typecheck_convert_incompatible)
1481-
<< PassedType << ExpectedType << 1 << 0 << 0;
1489+
Expr *Arg = TheCall->getArg(i);
1490+
if (CheckArgTypeIsCorrect(S, Arg, ExpectedType, Check)) {
14821491
return true;
14831492
}
14841493
}
@@ -1762,6 +1771,37 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
17621771
return true;
17631772
break;
17641773
}
1774+
case Builtin::BI__builtin_hlsl_asuint_splitdouble: {
1775+
if (SemaRef.checkArgCount(TheCall, 3))
1776+
return true;
1777+
1778+
// Expr *Op0 = TheCall->getArg(0);
1779+
1780+
// auto CheckIsNotDouble = [](clang::QualType PassedType) -> bool {
1781+
// return !PassedType->isDoubleType();
1782+
// };
1783+
1784+
// if (CheckArgTypeIsCorrect(&SemaRef, Op0, SemaRef.Context.DoubleTy,
1785+
// CheckIsNotDouble)) {
1786+
// return true;
1787+
// }
1788+
1789+
// Expr *Op1 = TheCall->getArg(1);
1790+
// Expr *Op2 = TheCall->getArg(2);
1791+
1792+
// auto CheckIsNotUint = [](clang::QualType PassedType) -> bool {
1793+
// return !PassedType->isUnsignedIntegerType();
1794+
// };
1795+
1796+
// if (CheckArgTypeIsCorrect(&SemaRef, Op1, SemaRef.Context.UnsignedIntTy,
1797+
// CheckIsNotUint) ||
1798+
// CheckArgTypeIsCorrect(&SemaRef, Op2, SemaRef.Context.UnsignedIntTy,
1799+
// CheckIsNotUint)) {
1800+
// return true;
1801+
// }
1802+
1803+
break;
1804+
}
17651805
case Builtin::BI__builtin_elementwise_acos:
17661806
case Builtin::BI__builtin_elementwise_asin:
17671807
case Builtin::BI__builtin_elementwise_atan:
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s -fnative-half-type -emit-llvm -O0 -o - | FileCheck %s
2+
3+
// CHECK: define {{.*}}test_scalar{{.*}}(double {{.*}} [[VAL1:%.*]], i32 {{.*}} [[VAL2:%.*]], i32 {{.*}} [[VAL3:%.*]]){{.*}}
4+
// CHECK: [[VALD:%.*]] = load double, ptr [[VAL1]].addr{{.*}}
5+
// CHECK: call { i32, i32 } @llvm.dx.asuint.splitdouble.{{.*}}(double [[VALD]])
6+
float fn(double D) {
7+
uint A, B;
8+
asuint(D, A, B);
9+
return A + B;
10+
}

llvm/include/llvm/IR/IntrinsicsDirectX.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,4 +88,9 @@ def int_dx_rsqrt : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]
8888
def int_dx_wave_is_first_lane : DefaultAttrsIntrinsic<[llvm_i1_ty], [], [IntrConvergent]>;
8989
def int_dx_sign : DefaultAttrsIntrinsic<[LLVMScalarOrSameVectorWidth<0, llvm_i32_ty>], [llvm_any_ty], [IntrNoMem]>;
9090
def int_dx_step : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty, LLVMMatchType<0>], [IntrNoMem]>;
91+
92+
def int_dx_asuint_splitdouble : DefaultAttrsIntrinsic<
93+
[llvm_anyint_ty, LLVMMatchType<0>],
94+
[LLVMScalarOrSameVectorWidth<0, llvm_double_ty>],
95+
[IntrNoMem, IntrWillReturn]>;
9196
}

llvm/lib/Target/DirectX/DXIL.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -778,6 +778,7 @@ def FlattenedThreadIdInGroup : DXILOp<96, flattenedThreadIdInGroup> {
778778
let stages = [Stages<DXIL1_0, [compute, mesh, amplification, node]>];
779779
let attributes = [Attributes<DXIL1_0, [ReadNone]>];
780780
}
781+
//
781782

782783
def AnnotateHandle : DXILOp<217, annotateHandle> {
783784
let Doc = "annotate handle with resource properties";

llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
#include "DXILIntrinsicExpansion.h"
1414
#include "DirectX.h"
15+
#include "llvm-c/Core.h"
1516
#include "llvm/ADT/STLExtras.h"
1617
#include "llvm/ADT/SmallVector.h"
1718
#include "llvm/Analysis/DXILResource.h"
@@ -346,6 +347,15 @@ static Value *expandStepIntrinsic(CallInst *Orig) {
346347
return Builder.CreateSelect(Cond, Zero, One);
347348
}
348349

350+
// static Value *expandSplitdoubleIntrinsic(CallInst *Orig) {
351+
// Value *X = Orig->getOperand(0);
352+
// Type *Ty = X->getType();
353+
// IRBuilder<> Builder(Orig);
354+
355+
// Builder.CreateIntrinsic()
356+
357+
// }
358+
349359
static Intrinsic::ID getMaxForClamp(Type *ElemTy,
350360
Intrinsic::ID ClampIntrinsic) {
351361
if (ClampIntrinsic == Intrinsic::dx_uclamp)
@@ -459,6 +469,9 @@ static bool expandIntrinsic(Function &F, CallInst *Orig) {
459469
break;
460470
case Intrinsic::dx_step:
461471
Result = expandStepIntrinsic(Orig);
472+
break;
473+
// case Intrinsic::dx_asuint_splitdouble:
474+
// Result = expandSplitdoubleIntrinsic(Orig);
462475
}
463476
if (Result) {
464477
Orig->replaceAllUsesWith(Result);

0 commit comments

Comments
 (0)