@@ -264,6 +264,9 @@ class SPIRVInstructionSelector : public InstructionSelector {
264264 void selectHandleFromBinding (Register &ResVReg, const SPIRVType *ResType,
265265 MachineInstr &I) const ;
266266
267+ void selectReadImageIntrinsic (Register &ResVReg, const SPIRVType *ResType,
268+ MachineInstr &I) const ;
269+
267270 // Utilities
268271 Register buildI32Constant (uint32_t Val, MachineInstr &I,
269272 const SPIRVType *ResType = nullptr ) const ;
@@ -288,6 +291,12 @@ class SPIRVInstructionSelector : public InstructionSelector {
288291 uint32_t Binding, uint32_t ArraySize,
289292 Register IndexReg, bool IsNonUniform,
290293 MachineIRBuilder MIRBuilder) const ;
294+ SPIRVType *getCorrespondingVec4Type (const SPIRVType *Type,
295+ MachineInstr &I) const ;
296+ void extractScalarOrVectorFromVector (Register &ResultReg,
297+ const SPIRVType *ResType,
298+ Register &InputReg,
299+ MachineInstr &InsertionPoint) const ;
291300};
292301
293302} // end anonymous namespace
@@ -2762,6 +2771,10 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg,
27622771 selectHandleFromBinding (ResVReg, ResType, I);
27632772 return true ;
27642773 }
2774+ case Intrinsic::spv_typedBufferLoad: {
2775+ selectReadImageIntrinsic (ResVReg, ResType, I);
2776+ return true ;
2777+ }
27652778 default : {
27662779 std::string DiagMsg;
27672780 raw_string_ostream OS (DiagMsg);
@@ -2798,6 +2811,83 @@ void SPIRVInstructionSelector::selectHandleFromBinding(Register &ResVReg,
27982811 .addUse (VarReg);
27992812}
28002813
2814+ void SPIRVInstructionSelector::selectReadImageIntrinsic (
2815+ Register &ResVReg, const SPIRVType *ResType, MachineInstr &I) const {
2816+
2817+ // If the load of the image is in a different basic block, then
2818+ // this will generate invalid code. A proper solution is to move
2819+ // the OpLoad from selectHandleFromBinding here. However, to do
2820+ // that we will need to change the return type of the intrinsic.
2821+ // We will do that when we can, but for now trying to move forward with other
2822+ // issues.
2823+ Register ImageReg = I.getOperand (2 ).getReg ();
2824+
2825+ SPIRVType *ReadType = getCorrespondingVec4Type (ResType, I);
2826+ Register ReadReg = MRI->createVirtualRegister (GR.getRegClass (ReadType));
2827+ BuildMI (*I.getParent (), I, I.getDebugLoc (), TII.get (SPIRV::OpImageRead))
2828+ .addDef (ReadReg)
2829+ .addUse (GR.getSPIRVTypeID (ReadType))
2830+ .addUse (ImageReg)
2831+ .addUse (I.getOperand (3 ).getReg ());
2832+
2833+ extractScalarOrVectorFromVector (ResVReg, ResType, ReadReg, I);
2834+ }
2835+
2836+ void SPIRVInstructionSelector::extractScalarOrVectorFromVector (
2837+ Register &ResultReg, const SPIRVType *ResType, Register &InputReg,
2838+ MachineInstr &InsertionPoint) const {
2839+ SPIRVType *InputType = GR.getResultType (InputReg);
2840+ assert (InputType->getOpcode () == SPIRV::OpTypeVector);
2841+
2842+ if (ResType->getOpcode () != SPIRV::OpTypeVector) {
2843+ assert (ResType == GR.getScalarOrVectorComponentType (InputType));
2844+ BuildMI (*InsertionPoint.getParent (), InsertionPoint,
2845+ InsertionPoint.getDebugLoc (), TII.get (SPIRV::OpCompositeExtract))
2846+ .addDef (ResultReg)
2847+ .addUse (GR.getSPIRVTypeID (ResType))
2848+ .addUse (InputReg)
2849+ .addImm (0 );
2850+ return ;
2851+ }
2852+
2853+ uint64_t InputSize = GR.getScalarOrVectorComponentCount (InputType);
2854+ uint64_t VectorSize = GR.getScalarOrVectorComponentCount (ResType);
2855+ if (VectorSize == InputSize) {
2856+ BuildMI (*InsertionPoint.getParent (), InsertionPoint,
2857+ InsertionPoint.getDebugLoc (), TII.get (SPIRV::OpCopyObject))
2858+ .addDef (ResultReg)
2859+ .addUse (GR.getSPIRVTypeID (ResType))
2860+ .addUse (InputReg);
2861+ return ;
2862+ }
2863+
2864+ assert (VectorSize < InputSize &&
2865+ " Cannot extract more element than there are in the input." );
2866+ SmallVector<Register> ComponentRegisters;
2867+ SPIRVType *ScalarType = GR.getScalarOrVectorComponentType (ResType);
2868+ const TargetRegisterClass *ScalarRegClass = GR.getRegClass (ScalarType);
2869+ for (uint64_t i = 0 ; i < VectorSize; i++) {
2870+ Register ComponentReg = MRI->createVirtualRegister (ScalarRegClass);
2871+ BuildMI (*InsertionPoint.getParent (), InsertionPoint,
2872+ InsertionPoint.getDebugLoc (), TII.get (SPIRV::OpCompositeExtract))
2873+ .addDef (ComponentReg)
2874+ .addUse (ScalarType->getOperand (0 ).getReg ())
2875+ .addUse (InputReg)
2876+ .addImm (i);
2877+ ComponentRegisters.emplace_back (ComponentReg);
2878+ }
2879+
2880+ MachineInstrBuilder MIB = BuildMI (*InsertionPoint.getParent (), InsertionPoint,
2881+ InsertionPoint.getDebugLoc (),
2882+ TII.get (SPIRV::OpCompositeConstruct))
2883+ .addDef (ResultReg)
2884+ .addUse (GR.getSPIRVTypeID (ResType));
2885+
2886+ for (Register ComponentReg : ComponentRegisters) {
2887+ MIB.addUse (ComponentReg);
2888+ }
2889+ }
2890+
28012891Register SPIRVInstructionSelector::buildPointerToResource (
28022892 const SPIRVType *ResType, uint32_t Set, uint32_t Binding,
28032893 uint32_t ArraySize, Register IndexReg, bool IsNonUniform,
@@ -3300,6 +3390,24 @@ bool SPIRVInstructionSelector::selectSpvThreadId(Register ResVReg,
33003390 return MIB.constrainAllUses (TII, TRI, RBI);
33013391}
33023392
3393+ SPIRVType *
3394+ SPIRVInstructionSelector::getCorrespondingVec4Type (const SPIRVType *Type,
3395+ MachineInstr &I) const {
3396+ MachineIRBuilder MIRBuilder (I);
3397+ if (Type->getOpcode () != SPIRV::OpTypeVector) {
3398+ return GR.getOrCreateSPIRVVectorType (Type, 4 , MIRBuilder);
3399+ }
3400+
3401+ uint64_t VectorSize = Type->getOperand (2 ).getImm ();
3402+ if (VectorSize == 4 ) {
3403+ return Type;
3404+ }
3405+
3406+ Register ScalarTypeReg = Type->getOperand (1 ).getReg ();
3407+ const SPIRVType *ScalarType = GR.getSPIRVTypeForVReg (ScalarTypeReg);
3408+ return GR.getOrCreateSPIRVVectorType (ScalarType, 4 , MIRBuilder);
3409+ }
3410+
33033411namespace llvm {
33043412InstructionSelector *
33053413createSPIRVInstructionSelector (const SPIRVTargetMachine &TM,
0 commit comments