@@ -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
@@ -2767,6 +2776,10 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg,
27672776 selectHandleFromBinding (ResVReg, ResType, I);
27682777 return true ;
27692778 }
2779+ case Intrinsic::spv_typedBufferLoad: {
2780+ selectReadImageIntrinsic (ResVReg, ResType, I);
2781+ return true ;
2782+ }
27702783 default : {
27712784 std::string DiagMsg;
27722785 raw_string_ostream OS (DiagMsg);
@@ -2803,6 +2816,83 @@ void SPIRVInstructionSelector::selectHandleFromBinding(Register &ResVReg,
28032816 .addUse (VarReg);
28042817}
28052818
2819+ void SPIRVInstructionSelector::selectReadImageIntrinsic (
2820+ Register &ResVReg, const SPIRVType *ResType, MachineInstr &I) const {
2821+
2822+ // If the load of the image is in a different basic block, then
2823+ // this will generate invalid code. A proper solution is to move
2824+ // the OpLoad from selectHandleFromBinding here. However, to do
2825+ // that we will need to change the return type of the intrinsic.
2826+ // We will do that when we can, but for now trying to move forward with other
2827+ // issues.
2828+ Register ImageReg = I.getOperand (2 ).getReg ();
2829+
2830+ SPIRVType *ReadType = getCorrespondingVec4Type (ResType, I);
2831+ Register ReadReg = MRI->createVirtualRegister (GR.getRegClass (ReadType));
2832+ BuildMI (*I.getParent (), I, I.getDebugLoc (), TII.get (SPIRV::OpImageRead))
2833+ .addDef (ReadReg)
2834+ .addUse (GR.getSPIRVTypeID (ReadType))
2835+ .addUse (ImageReg)
2836+ .addUse (I.getOperand (3 ).getReg ());
2837+
2838+ extractScalarOrVectorFromVector (ResVReg, ResType, ReadReg, I);
2839+ }
2840+
2841+ void SPIRVInstructionSelector::extractScalarOrVectorFromVector (
2842+ Register &ResultReg, const SPIRVType *ResType, Register &InputReg,
2843+ MachineInstr &InsertionPoint) const {
2844+ SPIRVType *InputType = GR.getResultType (InputReg);
2845+ assert (InputType->getOpcode () == SPIRV::OpTypeVector);
2846+
2847+ if (ResType->getOpcode () != SPIRV::OpTypeVector) {
2848+ assert (ResType == GR.getScalarOrVectorComponentType (InputType));
2849+ BuildMI (*InsertionPoint.getParent (), InsertionPoint,
2850+ InsertionPoint.getDebugLoc (), TII.get (SPIRV::OpCompositeExtract))
2851+ .addDef (ResultReg)
2852+ .addUse (GR.getSPIRVTypeID (ResType))
2853+ .addUse (InputReg)
2854+ .addImm (0 );
2855+ return ;
2856+ }
2857+
2858+ uint64_t InputSize = GR.getScalarOrVectorComponentCount (InputType);
2859+ uint64_t VectorSize = GR.getScalarOrVectorComponentCount (ResType);
2860+ if (VectorSize == InputSize) {
2861+ BuildMI (*InsertionPoint.getParent (), InsertionPoint,
2862+ InsertionPoint.getDebugLoc (), TII.get (SPIRV::OpCopyObject))
2863+ .addDef (ResultReg)
2864+ .addUse (GR.getSPIRVTypeID (ResType))
2865+ .addUse (InputReg);
2866+ return ;
2867+ }
2868+
2869+ assert (VectorSize < InputSize &&
2870+ " Cannot extract more element than there are in the input." );
2871+ SmallVector<Register> ComponentRegisters;
2872+ SPIRVType *ScalarType = GR.getScalarOrVectorComponentType (ResType);
2873+ const TargetRegisterClass *ScalarRegClass = GR.getRegClass (ScalarType);
2874+ for (uint64_t i = 0 ; i < VectorSize; i++) {
2875+ Register ComponentReg = MRI->createVirtualRegister (ScalarRegClass);
2876+ BuildMI (*InsertionPoint.getParent (), InsertionPoint,
2877+ InsertionPoint.getDebugLoc (), TII.get (SPIRV::OpCompositeExtract))
2878+ .addDef (ComponentReg)
2879+ .addUse (ScalarType->getOperand (0 ).getReg ())
2880+ .addUse (InputReg)
2881+ .addImm (i);
2882+ ComponentRegisters.emplace_back (ComponentReg);
2883+ }
2884+
2885+ MachineInstrBuilder MIB = BuildMI (*InsertionPoint.getParent (), InsertionPoint,
2886+ InsertionPoint.getDebugLoc (),
2887+ TII.get (SPIRV::OpCompositeConstruct))
2888+ .addDef (ResultReg)
2889+ .addUse (GR.getSPIRVTypeID (ResType));
2890+
2891+ for (Register ComponentReg : ComponentRegisters) {
2892+ MIB.addUse (ComponentReg);
2893+ }
2894+ }
2895+
28062896Register SPIRVInstructionSelector::buildPointerToResource (
28072897 const SPIRVType *ResType, uint32_t Set, uint32_t Binding,
28082898 uint32_t ArraySize, Register IndexReg, bool IsNonUniform,
@@ -3305,6 +3395,24 @@ bool SPIRVInstructionSelector::selectSpvThreadId(Register ResVReg,
33053395 return MIB.constrainAllUses (TII, TRI, RBI);
33063396}
33073397
3398+ SPIRVType *
3399+ SPIRVInstructionSelector::getCorrespondingVec4Type (const SPIRVType *Type,
3400+ MachineInstr &I) const {
3401+ MachineIRBuilder MIRBuilder (I);
3402+ if (Type->getOpcode () != SPIRV::OpTypeVector) {
3403+ return GR.getOrCreateSPIRVVectorType (Type, 4 , MIRBuilder);
3404+ }
3405+
3406+ uint64_t VectorSize = Type->getOperand (2 ).getImm ();
3407+ if (VectorSize == 4 ) {
3408+ return Type;
3409+ }
3410+
3411+ Register ScalarTypeReg = Type->getOperand (1 ).getReg ();
3412+ const SPIRVType *ScalarType = GR.getSPIRVTypeForVReg (ScalarTypeReg);
3413+ return GR.getOrCreateSPIRVVectorType (ScalarType, 4 , MIRBuilder);
3414+ }
3415+
33083416namespace llvm {
33093417InstructionSelector *
33103418createSPIRVInstructionSelector (const SPIRVTargetMachine &TM,
0 commit comments