Skip to content

Commit 4fae564

Browse files
committed
Add the AddUint64 HLSL builtin function
- Defines the AddUint64 HLSL builtin function - Implements the UAddc DXIL op to lower AddUint64 to DXIL
1 parent 37ed2e6 commit 4fae564

File tree

13 files changed

+348
-7
lines changed

13 files changed

+348
-7
lines changed

clang/include/clang/Basic/Builtins.td

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4753,6 +4753,12 @@ def GetDeviceSideMangledName : LangBuiltin<"CUDA_LANG"> {
47534753
}
47544754

47554755
// HLSL
4756+
def HLSLAddUint64: LangBuiltin<"HLSL_LANG"> {
4757+
let Spellings = ["__builtin_hlsl_adduint64"];
4758+
let Attributes = [NoThrow, Const];
4759+
let Prototype = "void(...)";
4760+
}
4761+
47564762
def HLSLResourceGetPointer : LangBuiltin<"HLSL_LANG"> {
47574763
let Spellings = ["__builtin_hlsl_resource_getpointer"];
47584764
let Attributes = [NoThrow];

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10655,6 +10655,8 @@ def err_second_argument_to_cwsc_not_pointer : Error<
1065510655

1065610656
def err_vector_incorrect_num_elements : Error<
1065710657
"%select{too many|too few}0 elements in vector %select{initialization|operand}3 (expected %1 elements, have %2)">;
10658+
def err_invalid_even_odd_vector_element_count : Error<
10659+
"invalid element count of %0 in vector %select{initialization|operand}4 (expected an %select{even|odd}3 element count in the range of %1 and %2)">;
1065810660
def err_altivec_empty_initializer : Error<"expected initializer">;
1065910661

1066010662
def err_invalid_neon_type_code : Error<

clang/lib/CodeGen/CGBuiltin.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19445,6 +19445,51 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
1944519445
return nullptr;
1944619446

1944719447
switch (BuiltinID) {
19448+
case Builtin::BI__builtin_hlsl_adduint64: {
19449+
Value *OpA = EmitScalarExpr(E->getArg(0));
19450+
Value *OpB = EmitScalarExpr(E->getArg(1));
19451+
assert(E->getArg(0)->getType()->hasIntegerRepresentation() &&
19452+
E->getArg(1)->getType()->hasIntegerRepresentation() &&
19453+
"AddUint64 operands must have an integer representation");
19454+
assert(((E->getArg(0)->getType()->castAs<VectorType>()->getNumElements() ==
19455+
2 &&
19456+
E->getArg(1)->getType()->castAs<VectorType>()->getNumElements() ==
19457+
2) ||
19458+
(E->getArg(0)->getType()->castAs<VectorType>()->getNumElements() ==
19459+
4 &&
19460+
E->getArg(1)->getType()->castAs<VectorType>()->getNumElements() ==
19461+
4)) &&
19462+
"input vectors must have 2 or 4 elements each");
19463+
19464+
llvm::Value *Result = PoisonValue::get(OpA->getType());
19465+
uint64_t NumElements =
19466+
E->getArg(0)->getType()->castAs<VectorType>()->getNumElements();
19467+
for (uint64_t i = 0; i < NumElements / 2; ++i) {
19468+
19469+
// Obtain low and high words of inputs A and B
19470+
llvm::Value *LowA = Builder.CreateExtractElement(OpA, 2 * i + 0);
19471+
llvm::Value *HighA = Builder.CreateExtractElement(OpA, 2 * i + 1);
19472+
llvm::Value *LowB = Builder.CreateExtractElement(OpB, 2 * i + 0);
19473+
llvm::Value *HighB = Builder.CreateExtractElement(OpB, 2 * i + 1);
19474+
19475+
// Use an uadd_with_overflow to compute the sum of low words and obtain a
19476+
// carry value
19477+
llvm::Value *Carry;
19478+
llvm::Value *LowSum = EmitOverflowIntrinsic(
19479+
*this, llvm::Intrinsic::uadd_with_overflow, LowA, LowB, Carry);
19480+
llvm::Value *ZExtCarry = Builder.CreateZExt(Carry, HighA->getType());
19481+
19482+
// Sum the high words and the carry
19483+
llvm::Value *HighSum = Builder.CreateAdd(HighA, HighB);
19484+
llvm::Value *HighSumPlusCarry = Builder.CreateAdd(HighSum, ZExtCarry);
19485+
19486+
// Insert the low and high word sums into the result vector
19487+
Result = Builder.CreateInsertElement(Result, LowSum, 2 * i + 0);
19488+
Result = Builder.CreateInsertElement(Result, HighSumPlusCarry, 2 * i + 1,
19489+
"hlsl.AddUint64");
19490+
}
19491+
return Result;
19492+
}
1944819493
case Builtin::BI__builtin_hlsl_resource_getpointer: {
1944919494
Value *HandleOp = EmitScalarExpr(E->getArg(0));
1945019495
Value *IndexOp = EmitScalarExpr(E->getArg(1));

clang/lib/Headers/hlsl/hlsl_intrinsics.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,27 @@ _HLSL_BUILTIN_ALIAS(__builtin_elementwise_acos)
138138
float4 acos(float4);
139139

140140
//===----------------------------------------------------------------------===//
141+
// AddUint64 builtins
142+
//===----------------------------------------------------------------------===//
143+
144+
/// \fn T AddUint64(T a, T b)
145+
/// \brief Implements unsigned 64-bit integer addition using pairs of unsigned
146+
/// 32-bit integers.
147+
/// \param x [in] The first unsigned 32-bit integer pair(s)
148+
/// \param y [in] The second unsigned 32-bit integer pair(s)
149+
///
150+
/// This function takes one or two pairs (low, high) of unsigned 32-bit integer
151+
/// values and returns pairs (low, high) of unsigned 32-bit integer
152+
/// values representing the result of unsigned 64-bit integer addition.
153+
154+
_HLSL_AVAILABILITY(shadermodel, 6.0)
155+
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_adduint64)
156+
uint32_t2 AddUint64(uint32_t2, uint32_t2);
157+
_HLSL_AVAILABILITY(shadermodel, 6.0)
158+
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_adduint64)
159+
uint32_t4 AddUint64(uint32_t4, uint32_t4);
160+
161+
// //===----------------------------------------------------------------------===//
141162
// all builtins
142163
//===----------------------------------------------------------------------===//
143164

clang/lib/Sema/SemaHLSL.cpp

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2038,6 +2038,18 @@ static bool CheckAllArgsHaveFloatRepresentation(Sema *S, CallExpr *TheCall) {
20382038
checkAllFloatTypes);
20392039
}
20402040

2041+
static bool CheckUnsignedIntRepresentations(Sema *S, CallExpr *TheCall) {
2042+
auto checkUnsignedInteger = [](clang::QualType PassedType) -> bool {
2043+
clang::QualType BaseType =
2044+
PassedType->isVectorType()
2045+
? PassedType->getAs<clang::VectorType>()->getElementType()
2046+
: PassedType;
2047+
return !BaseType->isUnsignedIntegerType();
2048+
};
2049+
return CheckAllArgTypesAreCorrect(S, TheCall, S->Context.UnsignedIntTy,
2050+
checkUnsignedInteger);
2051+
}
2052+
20412053
static bool CheckFloatOrHalfRepresentations(Sema *S, CallExpr *TheCall) {
20422054
auto checkFloatorHalf = [](clang::QualType PassedType) -> bool {
20432055
clang::QualType BaseType =
@@ -2229,6 +2241,41 @@ static bool CheckResourceHandle(
22292241
// returning an ExprError
22302242
bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
22312243
switch (BuiltinID) {
2244+
case Builtin::BI__builtin_hlsl_adduint64: {
2245+
if (SemaRef.checkArgCount(TheCall, 2))
2246+
return true;
2247+
if (CheckVectorElementCallArgs(&SemaRef, TheCall))
2248+
return true;
2249+
if (CheckUnsignedIntRepresentations(&SemaRef, TheCall))
2250+
return true;
2251+
2252+
// CheckVectorElementCallArgs(...) guarantees both args are the same type.
2253+
assert(TheCall->getArg(0)->getType() == TheCall->getArg(1)->getType() &&
2254+
"Both args must be of the same type");
2255+
2256+
// ensure both args are vectors
2257+
auto *VTy = TheCall->getArg(0)->getType()->getAs<VectorType>();
2258+
if (!VTy) {
2259+
SemaRef.Diag(TheCall->getBeginLoc(), diag::err_vec_builtin_non_vector)
2260+
<< "AddUint64" << /*all*/ 1;
2261+
return true;
2262+
}
2263+
2264+
// ensure both args have 2 elements, or both args have 4 elements
2265+
int NumElementsArg = VTy->getNumElements();
2266+
if (NumElementsArg != 2 && NumElementsArg != 4) {
2267+
SemaRef.Diag(TheCall->getBeginLoc(),
2268+
diag::err_invalid_even_odd_vector_element_count)
2269+
<< NumElementsArg << 2 << 4 << /*even*/ 0 << /*operand*/ 1;
2270+
return true;
2271+
}
2272+
2273+
ExprResult A = TheCall->getArg(0);
2274+
QualType ArgTyA = A.get()->getType();
2275+
// return type is the same as the input type
2276+
TheCall->setType(ArgTyA);
2277+
break;
2278+
}
22322279
case Builtin::BI__builtin_hlsl_resource_getpointer: {
22332280
if (SemaRef.checkArgCount(TheCall, 2) ||
22342281
CheckResourceHandle(&SemaRef, TheCall, 0) ||
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5
2+
// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.3-library %s \
3+
// RUN: -emit-llvm -disable-llvm-passes -o - | \
4+
// RUN: FileCheck %s --check-prefixes=CHECK
5+
6+
7+
// CHECK-LABEL: define noundef <2 x i32> @_Z20test_AddUint64_uint2Dv2_jS_(
8+
// CHECK-SAME: <2 x i32> noundef [[A:%.*]], <2 x i32> noundef [[B:%.*]]) #[[ATTR0:[0-9]+]] {
9+
// CHECK-NEXT: [[ENTRY:.*:]]
10+
// CHECK-NEXT: [[A_ADDR:%.*]] = alloca <2 x i32>, align 8
11+
// CHECK-NEXT: [[B_ADDR:%.*]] = alloca <2 x i32>, align 8
12+
// CHECK-NEXT: store <2 x i32> [[A]], ptr [[A_ADDR]], align 8
13+
// CHECK-NEXT: store <2 x i32> [[B]], ptr [[B_ADDR]], align 8
14+
// CHECK-NEXT: [[A_LOAD:%.*]] = load <2 x i32>, ptr [[A_ADDR]], align 8
15+
// CHECK-NEXT: [[B_LOAD:%.*]] = load <2 x i32>, ptr [[B_ADDR]], align 8
16+
// CHECK-NEXT: [[LowA:%.*]] = extractelement <2 x i32> [[A_LOAD]], i64 0
17+
// CHECK-NEXT: [[HighA:%.*]] = extractelement <2 x i32> [[A_LOAD]], i64 1
18+
// CHECK-NEXT: [[LowB:%.*]] = extractelement <2 x i32> [[B_LOAD]], i64 0
19+
// CHECK-NEXT: [[HighB:%.*]] = extractelement <2 x i32> [[B_LOAD]], i64 1
20+
// CHECK-NEXT: [[UAddc:%.*]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[LowA]], i32 [[LowB]])
21+
// CHECK-NEXT: [[Carry:%.*]] = extractvalue { i32, i1 } [[UAddc]], 1
22+
// CHECK-NEXT: [[LowSum:%.*]] = extractvalue { i32, i1 } [[UAddc]], 0
23+
// CHECK-NEXT: [[CarryZExt:%.*]] = zext i1 [[Carry]] to i32
24+
// CHECK-NEXT: [[HighSum:%.*]] = add i32 [[HighA]], [[HighB]]
25+
// CHECK-NEXT: [[HighSumPlusCarry:%.*]] = add i32 [[HighSum]], [[CarryZExt]]
26+
// CHECK-NEXT: [[HLSL_ADDUINT64_UPTO0:%.*]] = insertelement <2 x i32> poison, i32 [[LowSum]], i64 0
27+
// CHECK-NEXT: [[HLSL_ADDUINT64:%.*]] = insertelement <2 x i32> [[HLSL_ADDUINT64_UPTO0]], i32 [[HighSumPlusCarry]], i64 1
28+
// CHECK-NEXT: ret <2 x i32> [[HLSL_ADDUINT64]]
29+
//
30+
uint2 test_AddUint64_uint2(uint2 a, uint2 b) {
31+
return AddUint64(a, b);
32+
}
33+
34+
// CHECK-LABEL: define noundef <4 x i32> @_Z20test_AddUint64_uint4Dv4_jS_(
35+
// CHECK-SAME: <4 x i32> noundef [[A:%.*]], <4 x i32> noundef [[B:%.*]]) #[[ATTR0]] {
36+
// CHECK-NEXT: [[ENTRY:.*:]]
37+
// CHECK-NEXT: [[A_ADDR:%.*]] = alloca <4 x i32>, align 16
38+
// CHECK-NEXT: [[B_ADDR:%.*]] = alloca <4 x i32>, align 16
39+
// CHECK-NEXT: store <4 x i32> [[A]], ptr [[A_ADDR]], align 16
40+
// CHECK-NEXT: store <4 x i32> [[B]], ptr [[B_ADDR]], align 16
41+
// CHECK-NEXT: [[A_LOAD:%.*]] = load <4 x i32>, ptr [[A_ADDR]], align 16
42+
// CHECK-NEXT: [[B_LOAD:%.*]] = load <4 x i32>, ptr [[B_ADDR]], align 16
43+
// CHECK-NEXT: [[LowA:%.*]] = extractelement <4 x i32> [[A_LOAD]], i64 0
44+
// CHECK-NEXT: [[HighA:%.*]] = extractelement <4 x i32> [[A_LOAD]], i64 1
45+
// CHECK-NEXT: [[LowB:%.*]] = extractelement <4 x i32> [[B_LOAD]], i64 0
46+
// CHECK-NEXT: [[HighB:%.*]] = extractelement <4 x i32> [[B_LOAD]], i64 1
47+
// CHECK-NEXT: [[UAddc:%.*]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[LowA]], i32 [[LowB]])
48+
// CHECK-NEXT: [[Carry:%.*]] = extractvalue { i32, i1 } [[UAddc]], 1
49+
// CHECK-NEXT: [[LowSum:%.*]] = extractvalue { i32, i1 } [[UAddc]], 0
50+
// CHECK-NEXT: [[CarryZExt:%.*]] = zext i1 [[Carry]] to i32
51+
// CHECK-NEXT: [[HighSum:%.*]] = add i32 [[HighA]], [[HighB]]
52+
// CHECK-NEXT: [[HighSumPlusCarry:%.*]] = add i32 [[HighSum]], [[CarryZExt]]
53+
// CHECK-NEXT: [[HLSL_ADDUINT64_UPTO0:%.*]] = insertelement <4 x i32> poison, i32 [[LowSum]], i64 0
54+
// CHECK-NEXT: [[HLSL_ADDUINT64_UPTO1:%.*]] = insertelement <4 x i32> [[HLSL_ADDUINT64_UPTO0]], i32 [[HighSumPlusCarry]], i64 1
55+
// CHECK-NEXT: [[LowA1:%.*]] = extractelement <4 x i32> [[A_LOAD]], i64 2
56+
// CHECK-NEXT: [[HighA1:%.*]] = extractelement <4 x i32> [[A_LOAD]], i64 3
57+
// CHECK-NEXT: [[LowB1:%.*]] = extractelement <4 x i32> [[B_LOAD]], i64 2
58+
// CHECK-NEXT: [[HighB1:%.*]] = extractelement <4 x i32> [[B_LOAD]], i64 3
59+
// CHECK-NEXT: [[UAddc1:%.*]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[LowA1]], i32 [[LowB1]])
60+
// CHECK-NEXT: [[Carry1:%.*]] = extractvalue { i32, i1 } [[UAddc1]], 1
61+
// CHECK-NEXT: [[LowSum1:%.*]] = extractvalue { i32, i1 } [[UAddc1]], 0
62+
// CHECK-NEXT: [[CarryZExt1:%.*]] = zext i1 [[Carry1]] to i32
63+
// CHECK-NEXT: [[HighSum1:%.*]] = add i32 [[HighA1]], [[HighB1]]
64+
// CHECK-NEXT: [[HighSumPlusCarry1:%.*]] = add i32 [[HighSum1]], [[CarryZExt1]]
65+
// CHECK-NEXT: [[HLSL_ADDUINT64_UPTO2:%.*]] = insertelement <4 x i32> [[HLSL_ADDUINT64_UPTO1]], i32 [[LowSum1]], i64 2
66+
// CHECK-NEXT: [[HLSL_ADDUINT64:%.*]] = insertelement <4 x i32> [[HLSL_ADDUINT64_UPTO2]], i32 [[HighSumPlusCarry1]], i64 3
67+
// CHECK-NEXT: ret <4 x i32> [[HLSL_ADDUINT64]]
68+
//
69+
uint4 test_AddUint64_uint4(uint4 a, uint4 b) {
70+
return AddUint64(a, b);
71+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify
2+
3+
uint2 test_too_few_arg() {
4+
return __builtin_hlsl_adduint64();
5+
// expected-error@-1 {{too few arguments to function call, expected 2, have 0}}
6+
}
7+
8+
uint4 test_too_many_arg(uint4 a) {
9+
return __builtin_hlsl_adduint64(a, a, a);
10+
// expected-error@-1 {{too many arguments to function call, expected 2, have 3}}
11+
}
12+
13+
uint2 test_mismatched_arg_types(uint2 a, uint4 b) {
14+
return __builtin_hlsl_adduint64(a, b);
15+
// expected-error@-1 {{all arguments to '__builtin_hlsl_adduint64' must have the same type}}
16+
}
17+
18+
uint2 test_bad_num_arg_elements(uint3 a, uint3 b) {
19+
return __builtin_hlsl_adduint64(a, b);
20+
// expected-error@-1 {{invalid element count of 3 in vector operand (expected an even element count in the range of 2 and 4)}}
21+
}
22+
23+
uint2 test_scalar_arg_type(uint a) {
24+
return __builtin_hlsl_adduint64(a, a);
25+
// expected-error@-1 {{all arguments to AddUint64 must be vectors}}
26+
}
27+
28+
uint2 test_signed_integer_args(int2 a, int2 b) {
29+
return __builtin_hlsl_adduint64(a, b);
30+
// expected-error@-1 {{passing 'int2' (aka 'vector<int, 2>') to parameter of incompatible type '__attribute__((__vector_size__(2 * sizeof(unsigned int)))) unsigned int' (vector of 2 'unsigned int' values)}}
31+
}
32+
33+
struct S {
34+
uint2 a;
35+
};
36+
37+
uint2 test_incorrect_arg_type(S a) {
38+
return __builtin_hlsl_adduint64(a, a);
39+
// expected-error@-1 {{passing 'S' to parameter of incompatible type 'unsigned int'}}
40+
}
41+

llvm/lib/Target/DirectX/DXIL.td

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ def HandleTy : DXILOpParamType;
5050
def ResBindTy : DXILOpParamType;
5151
def ResPropsTy : DXILOpParamType;
5252
def SplitDoubleTy : DXILOpParamType;
53+
def BinaryWithCarryTy : DXILOpParamType;
5354

5455
class DXILOpClass;
5556

@@ -738,6 +739,18 @@ def UMin : DXILOp<40, binary> {
738739
let attributes = [Attributes<DXIL1_0, [ReadNone]>];
739740
}
740741

742+
def UAddc : DXILOp<44, binaryWithCarryOrBorrow > {
743+
let Doc = "Unsigned 32-bit integer arithmetic add with carry. uaddc(a,b) = (a+b, a+b overflowed ? 1 : 0)";
744+
// TODO: This `let intrinsics = ...` line may be uncommented when
745+
// https://github.com/llvm/llvm-project/issues/113192 is fixed
746+
// let intrinsics = [IntrinSelect<int_uadd_with_overflow>];
747+
let arguments = [OverloadTy, OverloadTy];
748+
let result = BinaryWithCarryTy;
749+
let overloads = [Overloads<DXIL1_0, [Int32Ty]>];
750+
let stages = [Stages<DXIL1_0, [all_stages]>];
751+
let attributes = [Attributes<DXIL1_0, [ReadNone]>];
752+
}
753+
741754
def FMad : DXILOp<46, tertiary> {
742755
let Doc = "Floating point arithmetic multiply/add operation. fmad(m,a,b) = m "
743756
"* a + b.";

llvm/lib/Target/DirectX/DXILOpBuilder.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,14 @@ static StructType *getSplitDoubleType(LLVMContext &Context) {
230230
return StructType::create({Int32Ty, Int32Ty}, "dx.types.splitdouble");
231231
}
232232

233+
static StructType *getBinaryWithCarryType(LLVMContext &Context) {
234+
if (auto *ST = StructType::getTypeByName(Context, "dx.types.i32c"))
235+
return ST;
236+
Type *Int32Ty = Type::getInt32Ty(Context);
237+
Type *Int1Ty = Type::getInt1Ty(Context);
238+
return StructType::create({Int32Ty, Int1Ty}, "dx.types.i32c");
239+
}
240+
233241
static Type *getTypeFromOpParamType(OpParamType Kind, LLVMContext &Ctx,
234242
Type *OverloadTy) {
235243
switch (Kind) {
@@ -273,6 +281,8 @@ static Type *getTypeFromOpParamType(OpParamType Kind, LLVMContext &Ctx,
273281
return getResPropsType(Ctx);
274282
case OpParamType::SplitDoubleTy:
275283
return getSplitDoubleType(Ctx);
284+
case OpParamType::BinaryWithCarryTy:
285+
return getBinaryWithCarryType(Ctx);
276286
}
277287
llvm_unreachable("Invalid parameter kind");
278288
return nullptr;
@@ -539,6 +549,10 @@ StructType *DXILOpBuilder::getSplitDoubleType(LLVMContext &Context) {
539549
return ::getSplitDoubleType(Context);
540550
}
541551

552+
StructType *DXILOpBuilder::getBinaryWithCarryType(LLVMContext &Context) {
553+
return ::getBinaryWithCarryType(Context);
554+
}
555+
542556
StructType *DXILOpBuilder::getHandleType() {
543557
return ::getHandleType(IRB.getContext());
544558
}

llvm/lib/Target/DirectX/DXILOpBuilder.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ class DXILOpBuilder {
5353
/// Get the `%dx.types.splitdouble` type.
5454
StructType *getSplitDoubleType(LLVMContext &Context);
5555

56+
/// Get the `%dx.types.i32c` type.
57+
StructType *getBinaryWithCarryType(LLVMContext &Context);
58+
5659
/// Get the `%dx.types.Handle` type.
5760
StructType *getHandleType();
5861

0 commit comments

Comments
 (0)