Skip to content

Commit 3cdac06

Browse files
authored
[HLSL][SPIRV][DXIL] Implement dot4add_i8packed intrinsic (llvm#113623)
- create a clang built-in in Builtins.td - link dot4add_i8packed in hlsl_intrinsics.h - add lowering to spirv backend through expansion of operation as OPSDot is missing up to SPIRV 1.6 in SPIRVInstructionSelector.cpp - add lowering to spirv backend using OpSDot in applicable SPIRV version or if SPV_KHR_integer_dot_product is enabled - add dot4add_i8packed intrinsic to IntrinsicsDirectX.td and mapping to DXIL.td op Dot4AddI8Packed - add tests for HLSL intrinsic lowering to dx/spv intrinsic in dot4add_i8packed.hlsl - add tests for sema checks in dot4add_i8packed-errors.hlsl - add test of spir-v lowering in SPIRV/dot4add_i8packed.ll - add test to dxil lowering in DirectX/dot4add_i8packed.ll Resolves llvm#99220
1 parent 04aaa35 commit 3cdac06

File tree

18 files changed

+347
-27
lines changed

18 files changed

+347
-27
lines changed

clang/include/clang/Basic/Builtins.td

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

4795+
def HLSLDot4AddI8Packed : LangBuiltin<"HLSL_LANG"> {
4796+
let Spellings = ["__builtin_hlsl_dot4add_i8packed"];
4797+
let Attributes = [NoThrow, Const];
4798+
let Prototype = "int(unsigned int, unsigned int, int)";
4799+
}
4800+
47954801
def HLSLFrac : LangBuiltin<"HLSL_LANG"> {
47964802
let Spellings = ["__builtin_hlsl_elementwise_frac"];
47974803
let Attributes = [NoThrow, Const];

clang/lib/CodeGen/CGBuiltin.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18855,7 +18855,17 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
1885518855
/*ReturnType=*/T0->getScalarType(),
1885618856
getDotProductIntrinsic(CGM.getHLSLRuntime(), VecTy0->getElementType()),
1885718857
ArrayRef<Value *>{Op0, Op1}, nullptr, "hlsl.dot");
18858-
} break;
18858+
}
18859+
case Builtin::BI__builtin_hlsl_dot4add_i8packed: {
18860+
Value *A = EmitScalarExpr(E->getArg(0));
18861+
Value *B = EmitScalarExpr(E->getArg(1));
18862+
Value *C = EmitScalarExpr(E->getArg(2));
18863+
18864+
Intrinsic::ID ID = CGM.getHLSLRuntime().getDot4AddI8PackedIntrinsic();
18865+
return Builder.CreateIntrinsic(
18866+
/*ReturnType=*/C->getType(), ID, ArrayRef<Value *>{A, B, C}, nullptr,
18867+
"hlsl.dot4add.i8packed");
18868+
}
1885918869
case Builtin::BI__builtin_hlsl_lerp: {
1886018870
Value *X = EmitScalarExpr(E->getArg(0));
1886118871
Value *Y = EmitScalarExpr(E->getArg(1));

clang/lib/CodeGen/CGHLSLRuntime.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ class CGHLSLRuntime {
8989
GENERATE_HLSL_INTRINSIC_FUNCTION(FDot, fdot)
9090
GENERATE_HLSL_INTRINSIC_FUNCTION(SDot, sdot)
9191
GENERATE_HLSL_INTRINSIC_FUNCTION(UDot, udot)
92+
GENERATE_HLSL_INTRINSIC_FUNCTION(Dot4AddI8Packed, dot4add_i8packed)
9293
GENERATE_HLSL_INTRINSIC_FUNCTION(WaveIsFirstLane, wave_is_first_lane)
9394
GENERATE_HLSL_INTRINSIC_FUNCTION(WaveReadLaneAt, wave_readlane)
9495

clang/lib/Headers/hlsl/hlsl_intrinsics.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -934,6 +934,16 @@ uint64_t dot(uint64_t3, uint64_t3);
934934
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_dot)
935935
uint64_t dot(uint64_t4, uint64_t4);
936936

937+
//===----------------------------------------------------------------------===//
938+
// dot4add builtins
939+
//===----------------------------------------------------------------------===//
940+
941+
/// \fn int dot4add_i8packed(uint A, uint B, int C)
942+
943+
_HLSL_AVAILABILITY(shadermodel, 6.4)
944+
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_dot4add_i8packed)
945+
int dot4add_i8packed(unsigned int, unsigned int, int);
946+
937947
//===----------------------------------------------------------------------===//
938948
// exp builtins
939949
//===----------------------------------------------------------------------===//
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// RUN: %clang_cc1 -finclude-default-header -triple \
2+
// RUN: dxil-pc-shadermodel6.3-compute %s -emit-llvm -disable-llvm-passes -o - | \
3+
// RUN: FileCheck %s -DTARGET=dx
4+
// RUN: %clang_cc1 -finclude-default-header -triple \
5+
// RUN: spirv-pc-vulkan-compute %s -emit-llvm -disable-llvm-passes -o - | \
6+
// RUN: FileCheck %s -DTARGET=spv
7+
8+
// Test basic lowering to runtime function call.
9+
10+
// CHECK-LABEL: test
11+
int test(uint a, uint b, int c) {
12+
// CHECK: %[[RET:.*]] = call [[TY:i32]] @llvm.[[TARGET]].dot4add.i8packed([[TY]] %[[#]], [[TY]] %[[#]], [[TY]] %[[#]])
13+
// CHECK: ret [[TY]] %[[RET]]
14+
return dot4add_i8packed(a, b, c);
15+
}
16+
17+
// CHECK: declare [[TY]] @llvm.[[TARGET]].dot4add.i8packed([[TY]], [[TY]], [[TY]])
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -emit-llvm-only -disable-llvm-passes -verify
2+
3+
int test_too_few_arg0() {
4+
return __builtin_hlsl_dot4add_i8packed();
5+
// expected-error@-1 {{too few arguments to function call, expected 3, have 0}}
6+
}
7+
8+
int test_too_few_arg1(int p0) {
9+
return __builtin_hlsl_dot4add_i8packed(p0);
10+
// expected-error@-1 {{too few arguments to function call, expected 3, have 1}}
11+
}
12+
13+
int test_too_few_arg2(int p0) {
14+
return __builtin_hlsl_dot4add_i8packed(p0, p0);
15+
// expected-error@-1 {{too few arguments to function call, expected 3, have 2}}
16+
}
17+
18+
int test_too_many_arg(int p0) {
19+
return __builtin_hlsl_dot4add_i8packed(p0, p0, p0, p0);
20+
// expected-error@-1 {{too many arguments to function call, expected 3, have 4}}
21+
}
22+
23+
struct S { float f; };
24+
25+
int test_expr_struct_type_check(S p0, int p1) {
26+
return __builtin_hlsl_dot4add_i8packed(p0, p1, p1);
27+
// expected-error@-1 {{no viable conversion from 'S' to 'unsigned int'}}
28+
}

llvm/docs/SPIRVUsage.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,8 @@ list of supported SPIR-V extensions, sorted alphabetically by their extension na
179179
- Provides additional information to a compiler, similar to the llvm.assume and llvm.expect intrinsics.
180180
* - ``SPV_KHR_float_controls``
181181
- Provides new execution modes to control floating-point computations by overriding an implementation’s default behavior for rounding modes, denormals, signed zero, and infinities.
182+
* - ``SPV_KHR_integer_dot_product``
183+
- Adds instructions for dot product operations on integer vectors with optional accumulation. Integer vectors includes 4-component vector of 8 bit integers and 4-component vectors of 8 bit integers packed into 32-bit integers.
182184
* - ``SPV_KHR_linkonce_odr``
183185
- Allows to use the LinkOnceODR linkage type that lets a function or global variable to be merged with other functions or global variables of the same name when linkage occurs.
184186
* - ``SPV_KHR_no_integer_wrap_decoration``

llvm/include/llvm/IR/IntrinsicsDirectX.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ def int_dx_udot :
6969
DefaultAttrsIntrinsic<[LLVMVectorElementType<0>],
7070
[llvm_anyint_ty, LLVMScalarOrSameVectorWidth<0, LLVMVectorElementType<0>>],
7171
[IntrNoMem, Commutative] >;
72+
def int_dx_dot4add_i8packed : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
7273

7374
def int_dx_frac : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]>;
7475
def int_dx_degrees : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty], [IntrNoMem]>;

llvm/include/llvm/IR/IntrinsicsSPIRV.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ let TargetPrefix = "spv" in {
8383
DefaultAttrsIntrinsic<[LLVMVectorElementType<0>],
8484
[llvm_anyint_ty, LLVMScalarOrSameVectorWidth<0, LLVMVectorElementType<0>>],
8585
[IntrNoMem, Commutative] >;
86+
def int_spv_dot4add_i8packed : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
8687
def int_spv_wave_is_first_lane : DefaultAttrsIntrinsic<[llvm_i1_ty], [], [IntrConvergent]>;
8788
def int_spv_wave_readlane : DefaultAttrsIntrinsic<[llvm_any_ty], [LLVMMatchType<0>, llvm_i32_ty], [IntrConvergent, IntrNoMem]>;
8889
def int_spv_sign : DefaultAttrsIntrinsic<[LLVMScalarOrSameVectorWidth<0, llvm_i32_ty>], [llvm_any_ty], [IntrNoMem]>;

llvm/lib/Target/DirectX/DXIL.td

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -788,6 +788,16 @@ def SplitDouble : DXILOp<102, splitDouble> {
788788
let attributes = [Attributes<DXIL1_0, [ReadNone]>];
789789
}
790790

791+
def Dot4AddI8Packed : DXILOp<163, dot4AddPacked> {
792+
let Doc = "signed dot product of 4 x i8 vectors packed into i32, with "
793+
"accumulate to i32";
794+
let LLVMIntrinsic = int_dx_dot4add_i8packed;
795+
let arguments = [Int32Ty, Int32Ty, Int32Ty];
796+
let result = Int32Ty;
797+
let attributes = [Attributes<DXIL1_0, [ReadNone]>];
798+
let stages = [Stages<DXIL1_0, [all_stages]>];
799+
}
800+
791801
def AnnotateHandle : DXILOp<216, annotateHandle> {
792802
let Doc = "annotate handle with resource properties";
793803
let arguments = [HandleTy, ResPropsTy];

llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ static const std::map<std::string, SPIRV::Extension::Extension>
5656
SPIRV::Extension::Extension::SPV_KHR_expect_assume},
5757
{"SPV_KHR_bit_instructions",
5858
SPIRV::Extension::Extension::SPV_KHR_bit_instructions},
59+
{"SPV_KHR_integer_dot_product",
60+
SPIRV::Extension::Extension::SPV_KHR_integer_dot_product},
5961
{"SPV_KHR_linkonce_odr",
6062
SPIRV::Extension::Extension::SPV_KHR_linkonce_odr},
6163
{"SPV_INTEL_inline_assembly",

llvm/lib/Target/SPIRV/SPIRVInstrInfo.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,9 @@ defm OpISubBorrow: BinOpTypedGen<"OpISubBorrow", 150, subc, 0, 1>;
524524
def OpUMulExtended: BinOp<"OpUMulExtended", 151>;
525525
def OpSMulExtended: BinOp<"OpSMulExtended", 152>;
526526

527+
def OpSDot: BinOp<"OpSDot", 4450>;
528+
def OpUDot: BinOp<"OpUDot", 4451>;
529+
527530
// 3.42.14 Bit Instructions
528531

529532
defm OpShiftRightLogical: BinOpTypedGen<"OpShiftRightLogical", 194, srl, 0, 1>;

llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp

Lines changed: 125 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,13 @@ class SPIRVInstructionSelector : public InstructionSelector {
164164
bool selectIntegerDot(Register ResVReg, const SPIRVType *ResType,
165165
MachineInstr &I) const;
166166

167+
template <bool Signed>
168+
bool selectDot4AddPacked(Register ResVReg, const SPIRVType *ResType,
169+
MachineInstr &I) const;
170+
template <bool Signed>
171+
bool selectDot4AddPackedExpansion(Register ResVReg, const SPIRVType *ResType,
172+
MachineInstr &I) const;
173+
167174
void renderImm32(MachineInstrBuilder &MIB, const MachineInstr &I,
168175
int OpIdx) const;
169176
void renderFImm64(MachineInstrBuilder &MIB, const MachineInstr &I,
@@ -1646,7 +1653,7 @@ bool SPIRVInstructionSelector::selectIntegerDot(Register ResVReg,
16461653
// Multiply the vectors, then sum the results
16471654
Register Vec0 = I.getOperand(2).getReg();
16481655
Register Vec1 = I.getOperand(3).getReg();
1649-
Register TmpVec = MRI->createVirtualRegister(&SPIRV::IDRegClass);
1656+
Register TmpVec = MRI->createVirtualRegister(GR.getRegClass(ResType));
16501657
SPIRVType *VecType = GR.getSPIRVTypeForVReg(Vec0);
16511658

16521659
bool Result = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpIMulV))
@@ -1660,18 +1667,18 @@ bool SPIRVInstructionSelector::selectIntegerDot(Register ResVReg,
16601667
GR.getScalarOrVectorComponentCount(VecType) > 1 &&
16611668
"dot product requires a vector of at least 2 components");
16621669

1663-
Register Res = MRI->createVirtualRegister(&SPIRV::IDRegClass);
1664-
Result |= BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpCompositeExtract))
1670+
Register Res = MRI->createVirtualRegister(GR.getRegClass(ResType));
1671+
Result &= BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpCompositeExtract))
16651672
.addDef(Res)
16661673
.addUse(GR.getSPIRVTypeID(ResType))
16671674
.addUse(TmpVec)
16681675
.addImm(0)
16691676
.constrainAllUses(TII, TRI, RBI);
16701677

16711678
for (unsigned i = 1; i < GR.getScalarOrVectorComponentCount(VecType); i++) {
1672-
Register Elt = MRI->createVirtualRegister(&SPIRV::IDRegClass);
1679+
Register Elt = MRI->createVirtualRegister(GR.getRegClass(ResType));
16731680

1674-
Result |=
1681+
Result &=
16751682
BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpCompositeExtract))
16761683
.addDef(Elt)
16771684
.addUse(GR.getSPIRVTypeID(ResType))
@@ -1680,10 +1687,10 @@ bool SPIRVInstructionSelector::selectIntegerDot(Register ResVReg,
16801687
.constrainAllUses(TII, TRI, RBI);
16811688

16821689
Register Sum = i < GR.getScalarOrVectorComponentCount(VecType) - 1
1683-
? MRI->createVirtualRegister(&SPIRV::IDRegClass)
1690+
? MRI->createVirtualRegister(GR.getRegClass(ResType))
16841691
: ResVReg;
16851692

1686-
Result |= BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpIAddS))
1693+
Result &= BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpIAddS))
16871694
.addDef(Sum)
16881695
.addUse(GR.getSPIRVTypeID(ResType))
16891696
.addUse(Res)
@@ -1695,6 +1702,112 @@ bool SPIRVInstructionSelector::selectIntegerDot(Register ResVReg,
16951702
return Result;
16961703
}
16971704

1705+
template <bool Signed>
1706+
bool SPIRVInstructionSelector::selectDot4AddPacked(Register ResVReg,
1707+
const SPIRVType *ResType,
1708+
MachineInstr &I) const {
1709+
assert(I.getNumOperands() == 5);
1710+
assert(I.getOperand(2).isReg());
1711+
assert(I.getOperand(3).isReg());
1712+
assert(I.getOperand(4).isReg());
1713+
MachineBasicBlock &BB = *I.getParent();
1714+
1715+
auto DotOp = Signed ? SPIRV::OpSDot : SPIRV::OpUDot;
1716+
Register Dot = MRI->createVirtualRegister(GR.getRegClass(ResType));
1717+
bool Result = BuildMI(BB, I, I.getDebugLoc(), TII.get(DotOp))
1718+
.addDef(Dot)
1719+
.addUse(GR.getSPIRVTypeID(ResType))
1720+
.addUse(I.getOperand(2).getReg())
1721+
.addUse(I.getOperand(3).getReg())
1722+
.constrainAllUses(TII, TRI, RBI);
1723+
1724+
Result &= BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpIAddS))
1725+
.addDef(ResVReg)
1726+
.addUse(GR.getSPIRVTypeID(ResType))
1727+
.addUse(Dot)
1728+
.addUse(I.getOperand(4).getReg())
1729+
.constrainAllUses(TII, TRI, RBI);
1730+
1731+
return Result;
1732+
}
1733+
1734+
// Since pre-1.6 SPIRV has no DotProductInput4x8BitPacked implementation,
1735+
// extract the elements of the packed inputs, multiply them and add the result
1736+
// to the accumulator.
1737+
template <bool Signed>
1738+
bool SPIRVInstructionSelector::selectDot4AddPackedExpansion(
1739+
Register ResVReg, const SPIRVType *ResType, MachineInstr &I) const {
1740+
assert(I.getNumOperands() == 5);
1741+
assert(I.getOperand(2).isReg());
1742+
assert(I.getOperand(3).isReg());
1743+
assert(I.getOperand(4).isReg());
1744+
MachineBasicBlock &BB = *I.getParent();
1745+
1746+
bool Result = false;
1747+
1748+
// Acc = C
1749+
Register Acc = I.getOperand(4).getReg();
1750+
SPIRVType *EltType = GR.getOrCreateSPIRVIntegerType(8, I, TII);
1751+
auto ExtractOp =
1752+
Signed ? SPIRV::OpBitFieldSExtract : SPIRV::OpBitFieldUExtract;
1753+
1754+
// Extract the i8 element, multiply and add it to the accumulator
1755+
for (unsigned i = 0; i < 4; i++) {
1756+
// A[i]
1757+
Register AElt = MRI->createVirtualRegister(&SPIRV::IDRegClass);
1758+
Result |= BuildMI(BB, I, I.getDebugLoc(), TII.get(ExtractOp))
1759+
.addDef(AElt)
1760+
.addUse(GR.getSPIRVTypeID(ResType))
1761+
.addUse(I.getOperand(2).getReg())
1762+
.addUse(GR.getOrCreateConstInt(i * 8, I, EltType, TII))
1763+
.addUse(GR.getOrCreateConstInt(8, I, EltType, TII))
1764+
.constrainAllUses(TII, TRI, RBI);
1765+
1766+
// B[i]
1767+
Register BElt = MRI->createVirtualRegister(&SPIRV::IDRegClass);
1768+
Result |= BuildMI(BB, I, I.getDebugLoc(), TII.get(ExtractOp))
1769+
.addDef(BElt)
1770+
.addUse(GR.getSPIRVTypeID(ResType))
1771+
.addUse(I.getOperand(3).getReg())
1772+
.addUse(GR.getOrCreateConstInt(i * 8, I, EltType, TII))
1773+
.addUse(GR.getOrCreateConstInt(8, I, EltType, TII))
1774+
.constrainAllUses(TII, TRI, RBI);
1775+
1776+
// A[i] * B[i]
1777+
Register Mul = MRI->createVirtualRegister(&SPIRV::IDRegClass);
1778+
Result |= BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpIMulS))
1779+
.addDef(Mul)
1780+
.addUse(GR.getSPIRVTypeID(ResType))
1781+
.addUse(AElt)
1782+
.addUse(BElt)
1783+
.constrainAllUses(TII, TRI, RBI);
1784+
1785+
// Discard 24 highest-bits so that stored i32 register is i8 equivalent
1786+
Register MaskMul = MRI->createVirtualRegister(&SPIRV::IDRegClass);
1787+
Result |= BuildMI(BB, I, I.getDebugLoc(), TII.get(ExtractOp))
1788+
.addDef(MaskMul)
1789+
.addUse(GR.getSPIRVTypeID(ResType))
1790+
.addUse(Mul)
1791+
.addUse(GR.getOrCreateConstInt(0, I, EltType, TII))
1792+
.addUse(GR.getOrCreateConstInt(8, I, EltType, TII))
1793+
.constrainAllUses(TII, TRI, RBI);
1794+
1795+
// Acc = Acc + A[i] * B[i]
1796+
Register Sum =
1797+
i < 3 ? MRI->createVirtualRegister(&SPIRV::IDRegClass) : ResVReg;
1798+
Result |= BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpIAddS))
1799+
.addDef(Sum)
1800+
.addUse(GR.getSPIRVTypeID(ResType))
1801+
.addUse(Acc)
1802+
.addUse(MaskMul)
1803+
.constrainAllUses(TII, TRI, RBI);
1804+
1805+
Acc = Sum;
1806+
}
1807+
1808+
return Result;
1809+
}
1810+
16981811
/// Transform saturate(x) to clamp(x, 0.0f, 1.0f) as SPIRV
16991812
/// does not have a saturate builtin.
17001813
bool SPIRVInstructionSelector::selectSaturate(Register ResVReg,
@@ -2528,6 +2641,11 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg,
25282641
case Intrinsic::spv_udot:
25292642
case Intrinsic::spv_sdot:
25302643
return selectIntegerDot(ResVReg, ResType, I);
2644+
case Intrinsic::spv_dot4add_i8packed:
2645+
if (STI.canUseExtension(SPIRV::Extension::SPV_KHR_integer_dot_product) ||
2646+
STI.isAtLeastSPIRVVer(VersionTuple(1, 6)))
2647+
return selectDot4AddPacked<true>(ResVReg, ResType, I);
2648+
return selectDot4AddPackedExpansion<true>(ResVReg, ResType, I);
25312649
case Intrinsic::spv_all:
25322650
return selectAll(ResVReg, ResType, I);
25332651
case Intrinsic::spv_any:

0 commit comments

Comments
 (0)