[clang] [llvm] [HLSL] Implement elementwise firstbitlow builtin (PR #116858)
Ashley Coleman via llvm-commits
llvm-commits at lists.llvm.org
Wed Jan 8 08:58:34 PST 2025
================
@@ -3178,98 +3178,74 @@ bool SPIRVInstructionSelector::selectFirstBitSet64Overflow(
Register ResVReg, const SPIRVType *ResType, MachineInstr &I,
Register SrcReg, unsigned BitSetOpcode, bool SwapPrimarySide) const {
+ // SPIR-V only allow vecs of size 2,3,4. Calling with a larger vec requires
+ // creating a param reg and return reg with an invalid vec size. If that is
+ // resolved then this function is valid for vectors of any component size.
unsigned ComponentCount = GR.getScalarOrVectorComponentCount(ResType);
- SPIRVType *BaseType = GR.retrieveScalarOrVectorIntType(ResType);
- bool ZeroAsNull = STI.isOpenCLEnv();
- Register ConstIntZero =
- GR.getOrCreateConstInt(0, I, BaseType, TII, ZeroAsNull);
- unsigned LeftComponentCount = ComponentCount / 2;
- unsigned RightComponentCount = ComponentCount - LeftComponentCount;
- bool LeftIsVector = LeftComponentCount > 1;
+ assert(ComponentCount < 5 && "Vec 5+ will generate invalid SPIR-V ops");
- // Split the SrcReg in half into 2 smaller vec registers
- // (ie i64x4 -> i64x2, i64x2)
+ bool ZeroAsNull = STI.isOpenCLEnv();
MachineIRBuilder MIRBuilder(I);
- SPIRVType *OpType = GR.getOrCreateSPIRVIntegerType(64, MIRBuilder);
- SPIRVType *LeftVecOpType;
- SPIRVType *LeftVecResType;
- if (LeftIsVector) {
- LeftVecOpType =
- GR.getOrCreateSPIRVVectorType(OpType, LeftComponentCount, MIRBuilder);
- LeftVecResType =
- GR.getOrCreateSPIRVVectorType(BaseType, LeftComponentCount, MIRBuilder);
- } else {
- LeftVecOpType = OpType;
- LeftVecResType = BaseType;
- }
-
- SPIRVType *RightVecOpType =
- GR.getOrCreateSPIRVVectorType(OpType, RightComponentCount, MIRBuilder);
- SPIRVType *RightVecResType =
- GR.getOrCreateSPIRVVectorType(BaseType, RightComponentCount, MIRBuilder);
+ SPIRVType *BaseType = GR.retrieveScalarOrVectorIntType(ResType);
+ SPIRVType *I64Type = GR.getOrCreateSPIRVIntegerType(64, MIRBuilder);
+ SPIRVType *I64x2Type = GR.getOrCreateSPIRVVectorType(I64Type, 2, MIRBuilder);
+ SPIRVType *Vec2ResType =
+ GR.getOrCreateSPIRVVectorType(BaseType, 2, MIRBuilder);
- Register LeftSideIn =
- MRI->createVirtualRegister(GR.getRegClass(LeftVecOpType));
- Register RightSideIn =
- MRI->createVirtualRegister(GR.getRegClass(RightVecOpType));
+ std::vector<Register> PartialRegs;
- bool Result;
+ // Loops 0, 2, 4, ... but stops one loop early when ComponentCount is odd
+ unsigned CurrentComponent = 0;
+ for (; CurrentComponent + 1 < ComponentCount; CurrentComponent += 2) {
+ Register SubVecReg = MRI->createVirtualRegister(GR.getRegClass(I64x2Type));
- // Extract the left half from the SrcReg into LeftSideIn
- // accounting for the special case when it only has one element
- if (LeftIsVector) {
auto MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(),
TII.get(SPIRV::OpVectorShuffle))
- .addDef(LeftSideIn)
- .addUse(GR.getSPIRVTypeID(LeftVecOpType))
+ .addDef(SubVecReg)
+ .addUse(GR.getSPIRVTypeID(I64x2Type))
.addUse(SrcReg)
// Per the spec, repeat the vector if only one vec is needed
.addUse(SrcReg);
- for (unsigned J = 0; J < LeftComponentCount; J++) {
- MIB.addImm(J);
- }
+ MIB.addImm(CurrentComponent);
+ MIB.addImm(CurrentComponent + 1);
- Result = MIB.constrainAllUses(TII, TRI, RBI);
- } else {
- Result =
- selectOpWithSrcs(LeftSideIn, LeftVecOpType, I, {SrcReg, ConstIntZero},
- SPIRV::OpVectorExtractDynamic);
- }
+ if (!MIB.constrainAllUses(TII, TRI, RBI))
+ return false;
- // Extract the right half from the SrcReg into RightSideIn.
- // Right will always be a vector since the only time one element is left is
- // when Component == 3, and in that case Left is one element.
- auto MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(),
- TII.get(SPIRV::OpVectorShuffle))
- .addDef(RightSideIn)
- .addUse(GR.getSPIRVTypeID(RightVecOpType))
- .addUse(SrcReg)
- // Per the spec, repeat the vector if only one vec is needed
- .addUse(SrcReg);
+ Register SubVecBitSetReg =
----------------
V-FEXrt wrote:
uhh I think so? Its hard to give this thing a precise name.
This is the register that holds the firstbitlow/high result for each of the sub/split vectors extracted from the input vector
https://github.com/llvm/llvm-project/pull/116858
More information about the llvm-commits
mailing list