[clang] [llvm] [HLSL] implement elementwise firstbithigh hlsl builtin (PR #111082)
Justin Bogner via cfe-commits
cfe-commits at lists.llvm.org
Tue Oct 22 11:41:02 PDT 2024
================
@@ -2626,6 +2671,148 @@ Register SPIRVInstructionSelector::buildPointerToResource(
MIRBuilder);
}
+bool SPIRVInstructionSelector::selectFirstBitHigh16(Register ResVReg,
+ const SPIRVType *ResType,
+ MachineInstr &I,
+ bool IsSigned) const {
+ unsigned Opcode = IsSigned ? SPIRV::OpSConvert : SPIRV::OpUConvert;
+ // zero or sign extend
+ Register ExtReg = MRI->createVirtualRegister(GR.getRegClass(ResType));
+ bool Result =
+ selectUnOpWithSrc(ExtReg, ResType, I, I.getOperand(2).getReg(), Opcode);
+ return Result & selectFirstBitHigh32(ResVReg, ResType, I, ExtReg, IsSigned);
+}
+
+bool SPIRVInstructionSelector::selectFirstBitHigh32(Register ResVReg,
+ const SPIRVType *ResType,
+ MachineInstr &I,
+ Register SrcReg,
+ bool IsSigned) const {
+ unsigned Opcode = IsSigned ? GL::FindSMsb : GL::FindUMsb;
+ return BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRV::OpExtInst))
+ .addDef(ResVReg)
+ .addUse(GR.getSPIRVTypeID(ResType))
+ .addImm(static_cast<uint32_t>(SPIRV::InstructionSet::GLSL_std_450))
+ .addImm(Opcode)
+ .addUse(SrcReg)
+ .constrainAllUses(TII, TRI, RBI);
+}
+
+bool SPIRVInstructionSelector::selectFirstBitHigh64(Register ResVReg,
+ const SPIRVType *ResType,
+ MachineInstr &I,
+ bool IsSigned) const {
+ Register OpReg = I.getOperand(2).getReg();
+ // 1. split our int64 into 2 pieces using a bitcast
+ unsigned count = GR.getScalarOrVectorComponentCount(ResType);
+ SPIRVType *baseType = GR.retrieveScalarOrVectorIntType(ResType);
+ MachineIRBuilder MIRBuilder(I);
+ SPIRVType *postCastT =
+ GR.getOrCreateSPIRVVectorType(baseType, 2 * count, MIRBuilder);
+ Register bitcastReg = MRI->createVirtualRegister(GR.getRegClass(postCastT));
+ bool Result =
+ selectUnOpWithSrc(bitcastReg, postCastT, I, OpReg, SPIRV::OpBitcast);
+
+ // 2. call firstbithigh
+ Register FBHReg = MRI->createVirtualRegister(GR.getRegClass(postCastT));
+ Result &= selectFirstBitHigh32(FBHReg, postCastT, I, bitcastReg, IsSigned);
+
+ // 3. check if result of each top 32 bits is == -1
+ // split result vector into vector of high bits and vector of low bits
+ // get high bits
+ // if ResType is a scalar we need a vector anyways because our code
+ // operates on vectors, even vectors of length one.
+ SPIRVType *VResType = ResType;
+ bool isScalarRes = ResType->getOpcode() != SPIRV::OpTypeVector;
+ if (isScalarRes)
+ VResType = GR.getOrCreateSPIRVVectorType(ResType, count, MIRBuilder);
+ // count should be one.
+
+ Register HighReg = MRI->createVirtualRegister(GR.getRegClass(VResType));
+ auto MIB =
+ BuildMI(*I.getParent(), I, I.getDebugLoc(),
+ TII.get(SPIRV::OpVectorShuffle))
+ .addDef(HighReg)
+ .addUse(GR.getSPIRVTypeID(VResType))
+ .addUse(FBHReg)
+ .addUse(
+ FBHReg); // this vector will not be selected from; could be empty
+ unsigned i;
+ for (i = 0; i < count * 2; i += 2) {
+ MIB.addImm(i);
+ }
----------------
bogner wrote:
Better to declare the variable in the for-loop scope so it's clear we aren't planning on using it again later. Also it's a bit confusing to have two variables named `i` and `I` in scope here - might be best to rename the `MachineInstr` to `MI` and/or to use some other placeholder like `J` here.
https://github.com/llvm/llvm-project/pull/111082
More information about the cfe-commits
mailing list