Skip to content

Commit d192b64

Browse files
authored
[HLSL] implement the isinf intrinsic (#84927)
This change implements part 1 of 2 for #70095 - `hlsl_intrinsics.h` - add the `isinf` api - `Builtins.td` - add an hlsl builtin for `isinf`. - `CGBuiltin.cpp` add the ir generation for `isinf` intrinsic. - `SemaChecking.cpp` - add a non-math elementwise checks because this is a bool return. - `IntrinsicsDirectX.td` - add an `isinf` intrinsic. `DXIL.td` lowering is left, but changes need to be made there before we can support this case.
1 parent 2296403 commit d192b64

File tree

7 files changed

+146
-0
lines changed

7 files changed

+146
-0
lines changed

clang/include/clang/Basic/Builtins.td

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4572,6 +4572,12 @@ def HLSLFrac : LangBuiltin<"HLSL_LANG"> {
45724572
let Prototype = "void(...)";
45734573
}
45744574

4575+
def HLSLIsinf : LangBuiltin<"HLSL_LANG"> {
4576+
let Spellings = ["__builtin_hlsl_elementwise_isinf"];
4577+
let Attributes = [NoThrow, Const];
4578+
let Prototype = "void(...)";
4579+
}
4580+
45754581
def HLSLLerp : LangBuiltin<"HLSL_LANG"> {
45764582
let Spellings = ["__builtin_hlsl_lerp"];
45774583
let Attributes = [NoThrow, Const];

clang/lib/CodeGen/CGBuiltin.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18062,6 +18062,20 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
1806218062
/*ReturnType=*/Op0->getType(), Intrinsic::dx_frac,
1806318063
ArrayRef<Value *>{Op0}, nullptr, "dx.frac");
1806418064
}
18065+
case Builtin::BI__builtin_hlsl_elementwise_isinf: {
18066+
Value *Op0 = EmitScalarExpr(E->getArg(0));
18067+
llvm::Type *Xty = Op0->getType();
18068+
llvm::Type *retType = llvm::Type::getInt1Ty(this->getLLVMContext());
18069+
if (Xty->isVectorTy()) {
18070+
auto *XVecTy = E->getArg(0)->getType()->getAs<VectorType>();
18071+
retType = llvm::VectorType::get(
18072+
retType, ElementCount::getFixed(XVecTy->getNumElements()));
18073+
}
18074+
if (!E->getArg(0)->getType()->hasFloatingRepresentation())
18075+
llvm_unreachable("isinf operand must have a float representation");
18076+
return Builder.CreateIntrinsic(retType, Intrinsic::dx_isinf,
18077+
ArrayRef<Value *>{Op0}, nullptr, "dx.isinf");
18078+
}
1806518079
case Builtin::BI__builtin_hlsl_mad: {
1806618080
Value *M = EmitScalarExpr(E->getArg(0));
1806718081
Value *A = EmitScalarExpr(E->getArg(1));

clang/lib/Headers/hlsl/hlsl_intrinsics.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,39 @@ float3 frac(float3);
525525
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_frac)
526526
float4 frac(float4);
527527

528+
//===----------------------------------------------------------------------===//
529+
// isinf builtins
530+
//===----------------------------------------------------------------------===//
531+
532+
/// \fn T isinf(T x)
533+
/// \brief Determines if the specified value \a x is infinite.
534+
/// \param x The specified input value.
535+
///
536+
/// Returns a value of the same size as the input, with a value set
537+
/// to True if the x parameter is +INF or -INF. Otherwise, False.
538+
539+
_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
540+
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_isinf)
541+
bool isinf(half);
542+
_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
543+
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_isinf)
544+
bool2 isinf(half2);
545+
_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
546+
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_isinf)
547+
bool3 isinf(half3);
548+
_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
549+
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_isinf)
550+
bool4 isinf(half4);
551+
552+
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_isinf)
553+
bool isinf(float);
554+
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_isinf)
555+
bool2 isinf(float2);
556+
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_isinf)
557+
bool3 isinf(float3);
558+
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_isinf)
559+
bool4 isinf(float4);
560+
528561
//===----------------------------------------------------------------------===//
529562
// lerp builtins
530563
//===----------------------------------------------------------------------===//

clang/lib/Sema/SemaChecking.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5268,6 +5268,15 @@ bool CheckAllArgsHaveFloatRepresentation(Sema *S, CallExpr *TheCall) {
52685268
return false;
52695269
}
52705270

5271+
void SetElementTypeAsReturnType(Sema *S, CallExpr *TheCall,
5272+
QualType ReturnType) {
5273+
auto *VecTyA = TheCall->getArg(0)->getType()->getAs<VectorType>();
5274+
if (VecTyA)
5275+
ReturnType = S->Context.getVectorType(ReturnType, VecTyA->getNumElements(),
5276+
VectorKind::Generic);
5277+
TheCall->setType(ReturnType);
5278+
}
5279+
52715280
// Note: returning true in this case results in CheckBuiltinFunctionCall
52725281
// returning an ExprError
52735282
bool Sema::CheckHLSLBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
@@ -5286,6 +5295,14 @@ bool Sema::CheckHLSLBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
52865295
return true;
52875296
break;
52885297
}
5298+
case Builtin::BI__builtin_hlsl_elementwise_isinf: {
5299+
if (checkArgCount(*this, TheCall, 1))
5300+
return true;
5301+
if (CheckAllArgsHaveFloatRepresentation(this, TheCall))
5302+
return true;
5303+
SetElementTypeAsReturnType(this, TheCall, this->Context.BoolTy);
5304+
break;
5305+
}
52895306
case Builtin::BI__builtin_hlsl_elementwise_rsqrt:
52905307
case Builtin::BI__builtin_hlsl_elementwise_rcp:
52915308
case Builtin::BI__builtin_hlsl_elementwise_frac: {
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
2+
// RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \
3+
// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \
4+
// RUN: --check-prefixes=CHECK,NATIVE_HALF
5+
// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
6+
// RUN: dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \
7+
// RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF
8+
9+
// CHECK: define noundef i1 @
10+
// NATIVE_HALF: %dx.isinf = call i1 @llvm.dx.isinf.f16(
11+
// NO_HALF: %dx.isinf = call i1 @llvm.dx.isinf.f32(
12+
// CHECK: ret i1 %dx.isinf
13+
bool test_isinf_half(half p0) { return isinf(p0); }
14+
// CHECK: define noundef <2 x i1> @
15+
// NATIVE_HALF: %dx.isinf = call <2 x i1> @llvm.dx.isinf.v2f16
16+
// NO_HALF: %dx.isinf = call <2 x i1> @llvm.dx.isinf.v2f32(
17+
// CHECK: ret <2 x i1> %dx.isinf
18+
bool2 test_isinf_half2(half2 p0) { return isinf(p0); }
19+
// NATIVE_HALF: define noundef <3 x i1> @
20+
// NATIVE_HALF: %dx.isinf = call <3 x i1> @llvm.dx.isinf.v3f16
21+
// NO_HALF: %dx.isinf = call <3 x i1> @llvm.dx.isinf.v3f32(
22+
// CHECK: ret <3 x i1> %dx.isinf
23+
bool3 test_isinf_half3(half3 p0) { return isinf(p0); }
24+
// NATIVE_HALF: define noundef <4 x i1> @
25+
// NATIVE_HALF: %dx.isinf = call <4 x i1> @llvm.dx.isinf.v4f16
26+
// NO_HALF: %dx.isinf = call <4 x i1> @llvm.dx.isinf.v4f32(
27+
// CHECK: ret <4 x i1> %dx.isinf
28+
bool4 test_isinf_half4(half4 p0) { return isinf(p0); }
29+
30+
// CHECK: define noundef i1 @
31+
// CHECK: %dx.isinf = call i1 @llvm.dx.isinf.f32(
32+
// CHECK: ret i1 %dx.isinf
33+
bool test_isinf_float(float p0) { return isinf(p0); }
34+
// CHECK: define noundef <2 x i1> @
35+
// CHECK: %dx.isinf = call <2 x i1> @llvm.dx.isinf.v2f32
36+
// CHECK: ret <2 x i1> %dx.isinf
37+
bool2 test_isinf_float2(float2 p0) { return isinf(p0); }
38+
// CHECK: define noundef <3 x i1> @
39+
// CHECK: %dx.isinf = call <3 x i1> @llvm.dx.isinf.v3f32
40+
// CHECK: ret <3 x i1> %dx.isinf
41+
bool3 test_isinf_float3(float3 p0) { return isinf(p0); }
42+
// CHECK: define noundef <4 x i1> @
43+
// CHECK: %dx.isinf = call <4 x i1> @llvm.dx.isinf.v4f32
44+
// CHECK: ret <4 x i1> %dx.isinf
45+
bool4 test_isinf_float4(float4 p0) { return isinf(p0); }
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
2+
// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -verify-ignore-unexpected
3+
4+
bool test_too_few_arg() {
5+
return __builtin_hlsl_elementwise_isinf();
6+
// expected-error@-1 {{too few arguments to function call, expected 1, have 0}}
7+
}
8+
9+
bool2 test_too_many_arg(float2 p0) {
10+
return __builtin_hlsl_elementwise_isinf(p0, p0);
11+
// expected-error@-1 {{too many arguments to function call, expected 1, have 2}}
12+
}
13+
14+
bool builtin_bool_to_float_type_promotion(bool p1) {
15+
return __builtin_hlsl_elementwise_isinf(p1);
16+
// expected-error@-1 {passing 'bool' to parameter of incompatible type 'float'}}
17+
}
18+
19+
bool builtin_isinf_int_to_float_promotion(int p1) {
20+
return __builtin_hlsl_elementwise_isinf(p1);
21+
// expected-error@-1 {{passing 'int' to parameter of incompatible type 'float'}}
22+
}
23+
24+
bool2 builtin_isinf_int2_to_float2_promotion(int2 p1) {
25+
return __builtin_hlsl_elementwise_isinf(p1);
26+
// expected-error@-1 {{passing 'int2' (aka 'vector<int, 2>') to parameter of incompatible type '__attribute__((__vector_size__(2 * sizeof(float)))) float' (vector of 2 'float' values)}}
27+
}

llvm/include/llvm/IR/IntrinsicsDirectX.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ def int_dx_dot :
2929

3030
def int_dx_frac : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>;
3131

32+
def int_dx_isinf :
33+
DefaultAttrsIntrinsic<[LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>],
34+
[llvm_anyfloat_ty]>;
35+
3236
def int_dx_lerp :
3337
Intrinsic<[LLVMScalarOrSameVectorWidth<0, LLVMVectorElementType<0>>],
3438
[llvm_anyvector_ty, LLVMScalarOrSameVectorWidth<0, LLVMVectorElementType<0>>,LLVMScalarOrSameVectorWidth<0, LLVMVectorElementType<0>>],

0 commit comments

Comments
 (0)