Skip to content

Commit 489eadd

Browse files
authored
[HLSL] Implementation of the frac intrinsic (#83315)
This change implements the frontend for #70099 Builtins.td - add the frac builtin CGBuiltin.cpp - add the builtin to DirectX intrinsic mapping hlsl_intrinsics.h - add the frac api SemaChecking.cpp - add type checks for builtin IntrinsicsDirectX.td - add the frac intrinsic The backend changes for this are going to be very simple: f309a0e They were not included because llvm/lib/Target/DirectX/DXIL.td is going through a major refactor.
1 parent 856ce49 commit 489eadd

File tree

13 files changed

+337
-280
lines changed

13 files changed

+337
-280
lines changed

clang/include/clang/Basic/Builtins.td

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4536,6 +4536,12 @@ def HLSLDotProduct : LangBuiltin<"HLSL_LANG"> {
45364536
let Prototype = "void(...)";
45374537
}
45384538

4539+
def HLSLFrac : LangBuiltin<"HLSL_LANG"> {
4540+
let Spellings = ["__builtin_hlsl_elementwise_frac"];
4541+
let Attributes = [NoThrow, Const];
4542+
let Prototype = "void(...)";
4543+
}
4544+
45394545
def HLSLLerp : LangBuiltin<"HLSL_LANG"> {
45404546
let Spellings = ["__builtin_hlsl_lerp"];
45414547
let Attributes = [NoThrow, Const];

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10270,7 +10270,7 @@ def err_vec_builtin_non_vector_all : Error<
1027010270
"all arguments to %0 must be vectors">;
1027110271
def err_vec_builtin_incompatible_vector_all : Error<
1027210272
"all arguments to %0 must have vectors of the same type">;
10273-
10273+
1027410274
def err_vec_builtin_non_vector : Error<
1027510275
"first two arguments to %0 must be vectors">;
1027610276
def err_vec_builtin_incompatible_vector : Error<

clang/lib/CodeGen/CGBuiltin.cpp

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18020,14 +18020,7 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
1802018020
V = Builder.CreateFMul(S, V);
1802118021
return Builder.CreateFAdd(X, V, "dx.lerp");
1802218022
}
18023-
// DXC does this via casting to float should we do the same thing?
18024-
if (Xty->isIntegerTy()) {
18025-
auto V = Builder.CreateSub(Y, X);
18026-
V = Builder.CreateMul(S, V);
18027-
return Builder.CreateAdd(X, V, "dx.lerp");
18028-
}
18029-
// Bools should have been promoted
18030-
llvm_unreachable("Scalar Lerp is only supported on ints and floats.");
18023+
llvm_unreachable("Scalar Lerp is only supported on floats.");
1803118024
}
1803218025
// A VectorSplat should have happened
1803318026
assert(Xty->isVectorTy() && Yty->isVectorTy() && Sty->isVectorTy() &&
@@ -18041,12 +18034,24 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
1804118034
E->getArg(2)->getType()->getAs<VectorType>();
1804218035
// A HLSLVectorTruncation should have happend
1804318036
assert(XVecTy->getNumElements() == YVecTy->getNumElements() &&
18044-
SVecTy->getNumElements() &&
18037+
XVecTy->getNumElements() == SVecTy->getNumElements() &&
1804518038
"Lerp requires vectors to be of the same size.");
18039+
assert(XVecTy->getElementType()->isRealFloatingType() &&
18040+
XVecTy->getElementType() == YVecTy->getElementType() &&
18041+
XVecTy->getElementType() == SVecTy->getElementType() &&
18042+
"Lerp requires float vectors to be of the same type.");
1804618043
return Builder.CreateIntrinsic(
1804718044
/*ReturnType*/ Xty, Intrinsic::dx_lerp, ArrayRef<Value *>{X, Y, S},
1804818045
nullptr, "dx.lerp");
1804918046
}
18047+
case Builtin::BI__builtin_hlsl_elementwise_frac: {
18048+
Value *Op0 = EmitScalarExpr(E->getArg(0));
18049+
if (!E->getArg(0)->getType()->hasFloatingRepresentation())
18050+
llvm_unreachable("frac operand must have a float representation");
18051+
return Builder.CreateIntrinsic(
18052+
/*ReturnType*/ Op0->getType(), Intrinsic::dx_frac,
18053+
ArrayRef<Value *>{Op0}, nullptr, "dx.frac");
18054+
}
1805018055
}
1805118056
return nullptr;
1805218057
}

clang/lib/Headers/hlsl/hlsl_intrinsics.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,38 @@ double3 floor(double3);
317317
_HLSL_BUILTIN_ALIAS(__builtin_elementwise_floor)
318318
double4 floor(double4);
319319

320+
//===----------------------------------------------------------------------===//
321+
// frac builtins
322+
//===----------------------------------------------------------------------===//
323+
324+
/// \fn T frac(T x)
325+
/// \brief Returns the fractional (or decimal) part of x. \a x parameter.
326+
/// \param x The specified input value.
327+
///
328+
/// If \a the return value is greater than or equal to 0 and less than 1.
329+
330+
_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
331+
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_frac)
332+
half frac(half);
333+
_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
334+
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_frac)
335+
half2 frac(half2);
336+
_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
337+
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_frac)
338+
half3 frac(half3);
339+
_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
340+
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_frac)
341+
half4 frac(half4);
342+
343+
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_frac)
344+
float frac(float);
345+
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_frac)
346+
float2 frac(float2);
347+
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_frac)
348+
float3 frac(float3);
349+
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_frac)
350+
float4 frac(float4);
351+
320352
//===----------------------------------------------------------------------===//
321353
// lerp builtins
322354
//===----------------------------------------------------------------------===//

clang/lib/Sema/SemaChecking.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5246,6 +5246,23 @@ bool CheckVectorElementCallArgs(Sema *S, CallExpr *TheCall) {
52465246
return true;
52475247
}
52485248

5249+
bool CheckAllArgsHaveFloatRepresentation(Sema *S, CallExpr *TheCall) {
5250+
QualType ExpectedType = S->Context.FloatTy;
5251+
for (unsigned i = 0; i < TheCall->getNumArgs(); ++i) {
5252+
QualType PassedType = TheCall->getArg(i)->getType();
5253+
if (!PassedType->hasFloatingRepresentation()) {
5254+
if (auto *VecTyA = PassedType->getAs<VectorType>())
5255+
ExpectedType = S->Context.getVectorType(
5256+
ExpectedType, VecTyA->getNumElements(), VecTyA->getVectorKind());
5257+
S->Diag(TheCall->getArg(0)->getBeginLoc(),
5258+
diag::err_typecheck_convert_incompatible)
5259+
<< PassedType << ExpectedType << 1 << 0 << 0;
5260+
return true;
5261+
}
5262+
}
5263+
return false;
5264+
}
5265+
52495266
// Note: returning true in this case results in CheckBuiltinFunctionCall
52505267
// returning an ExprError
52515268
bool Sema::CheckHLSLBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
@@ -5259,13 +5276,22 @@ bool Sema::CheckHLSLBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
52595276
return true;
52605277
break;
52615278
}
5279+
case Builtin::BI__builtin_hlsl_elementwise_frac: {
5280+
if (PrepareBuiltinElementwiseMathOneArgCall(TheCall))
5281+
return true;
5282+
if (CheckAllArgsHaveFloatRepresentation(this, TheCall))
5283+
return true;
5284+
break;
5285+
}
52625286
case Builtin::BI__builtin_hlsl_lerp: {
52635287
if (checkArgCount(*this, TheCall, 3))
52645288
return true;
52655289
if (CheckVectorElementCallArgs(this, TheCall))
52665290
return true;
52675291
if (SemaBuiltinElementwiseTernaryMath(TheCall))
52685292
return true;
5293+
if (CheckAllArgsHaveFloatRepresentation(this, TheCall))
5294+
return true;
52695295
break;
52705296
}
52715297
}

0 commit comments

Comments
 (0)