2222#include " SPIRVTargetMachine.h"
2323#include " SPIRVUtils.h"
2424#include " llvm/ADT/APFloat.h"
25+ #include " llvm/ADT/StringExtras.h"
2526#include " llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h"
2627#include " llvm/CodeGen/GlobalISel/GenericMachineInstrs.h"
2728#include " llvm/CodeGen/GlobalISel/InstructionSelector.h"
@@ -267,6 +268,9 @@ class SPIRVInstructionSelector : public InstructionSelector {
267268 bool selectHandleFromBinding (Register &ResVReg, const SPIRVType *ResType,
268269 MachineInstr &I) const ;
269270
271+ void selectReadImageIntrinsic (Register &ResVReg, const SPIRVType *ResType,
272+ MachineInstr &I) const ;
273+
270274 // Utilities
271275 std::pair<Register, bool >
272276 buildI32Constant (uint32_t Val, MachineInstr &I,
@@ -292,6 +296,9 @@ class SPIRVInstructionSelector : public InstructionSelector {
292296 uint32_t Binding, uint32_t ArraySize,
293297 Register IndexReg, bool IsNonUniform,
294298 MachineIRBuilder MIRBuilder) const ;
299+ SPIRVType *widenTypeToVec4 (const SPIRVType *Type, MachineInstr &I) const ;
300+ void extractSubvector (Register &ResVReg, const SPIRVType *ResType,
301+ Register &ReadReg, MachineInstr &InsertionPoint) const ;
295302};
296303
297304} // end anonymous namespace
@@ -2846,6 +2853,10 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg,
28462853 case Intrinsic::spv_handle_fromBinding: {
28472854 return selectHandleFromBinding (ResVReg, ResType, I);
28482855 }
2856+ case Intrinsic::spv_typedBufferLoad: {
2857+ selectReadImageIntrinsic (ResVReg, ResType, I);
2858+ return true ;
2859+ }
28492860 default : {
28502861 std::string DiagMsg;
28512862 raw_string_ostream OS (DiagMsg);
@@ -2883,6 +2894,83 @@ bool SPIRVInstructionSelector::selectHandleFromBinding(Register &ResVReg,
28832894 .constrainAllUses (TII, TRI, RBI);
28842895}
28852896
2897+ void SPIRVInstructionSelector::selectReadImageIntrinsic (
2898+ Register &ResVReg, const SPIRVType *ResType, MachineInstr &I) const {
2899+
2900+ // If the load of the image is in a different basic block, then
2901+ // this will generate invalid code. A proper solution is to move
2902+ // the OpLoad from selectHandleFromBinding here. However, to do
2903+ // that we will need to change the return type of the intrinsic.
2904+ // We will do that when we can, but for now trying to move forward with other
2905+ // issues.
2906+ Register ImageReg = I.getOperand (2 ).getReg ();
2907+ assert (MRI->getVRegDef (ImageReg)->getParent () == I.getParent () &&
2908+ " The image must be loaded in the same basic block as its use." );
2909+
2910+ uint64_t ResultSize = GR.getScalarOrVectorComponentCount (ResType);
2911+ if (ResultSize == 4 ) {
2912+ BuildMI (*I.getParent (), I, I.getDebugLoc (), TII.get (SPIRV::OpImageRead))
2913+ .addDef (ResVReg)
2914+ .addUse (GR.getSPIRVTypeID (ResType))
2915+ .addUse (ImageReg)
2916+ .addUse (I.getOperand (3 ).getReg ());
2917+ return ;
2918+ }
2919+
2920+ SPIRVType *ReadType = widenTypeToVec4 (ResType, I);
2921+ Register ReadReg = MRI->createVirtualRegister (GR.getRegClass (ReadType));
2922+ BuildMI (*I.getParent (), I, I.getDebugLoc (), TII.get (SPIRV::OpImageRead))
2923+ .addDef (ReadReg)
2924+ .addUse (GR.getSPIRVTypeID (ReadType))
2925+ .addUse (ImageReg)
2926+ .addUse (I.getOperand (3 ).getReg ());
2927+
2928+ if (ResultSize == 1 ) {
2929+ BuildMI (*I.getParent (), I, I.getDebugLoc (),
2930+ TII.get (SPIRV::OpCompositeExtract))
2931+ .addDef (ResVReg)
2932+ .addUse (GR.getSPIRVTypeID (ResType))
2933+ .addUse (ReadReg)
2934+ .addImm (0 );
2935+ return ;
2936+ }
2937+ extractSubvector (ResVReg, ResType, ReadReg, I);
2938+ }
2939+
2940+ void SPIRVInstructionSelector::extractSubvector (
2941+ Register &ResVReg, const SPIRVType *ResType, Register &ReadReg,
2942+ MachineInstr &InsertionPoint) const {
2943+ SPIRVType *InputType = GR.getResultType (ReadReg);
2944+ uint64_t InputSize = GR.getScalarOrVectorComponentCount (InputType);
2945+ uint64_t ResultSize = GR.getScalarOrVectorComponentCount (ResType);
2946+ assert (InputSize > 1 && " The input must be a vector." );
2947+ assert (ResultSize > 1 && " The result must be a vector." );
2948+ assert (ResultSize < InputSize &&
2949+ " Cannot extract more element than there are in the input." );
2950+ SmallVector<Register> ComponentRegisters;
2951+ SPIRVType *ScalarType = GR.getScalarOrVectorComponentType (ResType);
2952+ const TargetRegisterClass *ScalarRegClass = GR.getRegClass (ScalarType);
2953+ for (uint64_t I = 0 ; I < ResultSize; I++) {
2954+ Register ComponentReg = MRI->createVirtualRegister (ScalarRegClass);
2955+ BuildMI (*InsertionPoint.getParent (), InsertionPoint,
2956+ InsertionPoint.getDebugLoc (), TII.get (SPIRV::OpCompositeExtract))
2957+ .addDef (ComponentReg)
2958+ .addUse (ScalarType->getOperand (0 ).getReg ())
2959+ .addUse (ReadReg)
2960+ .addImm (I);
2961+ ComponentRegisters.emplace_back (ComponentReg);
2962+ }
2963+
2964+ MachineInstrBuilder MIB = BuildMI (*InsertionPoint.getParent (), InsertionPoint,
2965+ InsertionPoint.getDebugLoc (),
2966+ TII.get (SPIRV::OpCompositeConstruct))
2967+ .addDef (ResVReg)
2968+ .addUse (GR.getSPIRVTypeID (ResType));
2969+
2970+ for (Register ComponentReg : ComponentRegisters)
2971+ MIB.addUse (ComponentReg);
2972+ }
2973+
28862974Register SPIRVInstructionSelector::buildPointerToResource (
28872975 const SPIRVType *ResType, uint32_t Set, uint32_t Binding,
28882976 uint32_t ArraySize, Register IndexReg, bool IsNonUniform,
@@ -3384,6 +3472,21 @@ bool SPIRVInstructionSelector::selectSpvThreadId(Register ResVReg,
33843472 return Result && MIB.constrainAllUses (TII, TRI, RBI);
33853473}
33863474
3475+ SPIRVType *SPIRVInstructionSelector::widenTypeToVec4 (const SPIRVType *Type,
3476+ MachineInstr &I) const {
3477+ MachineIRBuilder MIRBuilder (I);
3478+ if (Type->getOpcode () != SPIRV::OpTypeVector)
3479+ return GR.getOrCreateSPIRVVectorType (Type, 4 , MIRBuilder);
3480+
3481+ uint64_t VectorSize = Type->getOperand (2 ).getImm ();
3482+ if (VectorSize == 4 )
3483+ return Type;
3484+
3485+ Register ScalarTypeReg = Type->getOperand (1 ).getReg ();
3486+ const SPIRVType *ScalarType = GR.getSPIRVTypeForVReg (ScalarTypeReg);
3487+ return GR.getOrCreateSPIRVVectorType (ScalarType, 4 , MIRBuilder);
3488+ }
3489+
33873490namespace llvm {
33883491InstructionSelector *
33893492createSPIRVInstructionSelector (const SPIRVTargetMachine &TM,
0 commit comments