diff options
Diffstat (limited to 'llvm/lib/Target/SPIRV/SPIRVUtils.cpp')
| -rw-r--r-- | llvm/lib/Target/SPIRV/SPIRVUtils.cpp | 218 |
1 files changed, 209 insertions, 9 deletions
diff --git a/llvm/lib/Target/SPIRV/SPIRVUtils.cpp b/llvm/lib/Target/SPIRV/SPIRVUtils.cpp index ddc66f98829a..768efb96a53e 100644 --- a/llvm/lib/Target/SPIRV/SPIRVUtils.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVUtils.cpp @@ -80,6 +80,16 @@ std::string getStringImm(const MachineInstr &MI, unsigned StartIndex) { return getSPIRVStringOperand(MI, StartIndex); } +std::string getStringValueFromReg(Register Reg, MachineRegisterInfo &MRI) { + MachineInstr *Def = getVRegDef(MRI, Reg); + assert(Def && Def->getOpcode() == TargetOpcode::G_GLOBAL_VALUE && + "Expected G_GLOBAL_VALUE"); + const GlobalValue *GV = Def->getOperand(1).getGlobal(); + Value *V = GV->getOperand(0); + const ConstantDataArray *CDA = cast<ConstantDataArray>(V); + return CDA->getAsCString().str(); +} + void addNumImm(const APInt &Imm, MachineInstrBuilder &MIB) { const auto Bitwidth = Imm.getBitWidth(); if (Bitwidth == 1) @@ -146,6 +156,30 @@ void buildOpDecorate(Register Reg, MachineInstr &I, const SPIRVInstrInfo &TII, finishBuildOpDecorate(MIB, DecArgs, StrImm); } +void buildOpMemberDecorate(Register Reg, MachineIRBuilder &MIRBuilder, + SPIRV::Decoration::Decoration Dec, uint32_t Member, + const std::vector<uint32_t> &DecArgs, + StringRef StrImm) { + auto MIB = MIRBuilder.buildInstr(SPIRV::OpMemberDecorate) + .addUse(Reg) + .addImm(Member) + .addImm(static_cast<uint32_t>(Dec)); + finishBuildOpDecorate(MIB, DecArgs, StrImm); +} + +void buildOpMemberDecorate(Register Reg, MachineInstr &I, + const SPIRVInstrInfo &TII, + SPIRV::Decoration::Decoration Dec, uint32_t Member, + const std::vector<uint32_t> &DecArgs, + StringRef StrImm) { + MachineBasicBlock &MBB = *I.getParent(); + auto MIB = BuildMI(MBB, I, I.getDebugLoc(), TII.get(SPIRV::OpMemberDecorate)) + .addUse(Reg) + .addImm(Member) + .addImm(static_cast<uint32_t>(Dec)); + finishBuildOpDecorate(MIB, DecArgs, StrImm); +} + void buildOpSpirvDecorations(Register Reg, MachineIRBuilder &MIRBuilder, const MDNode *GVarMD) { for (unsigned I = 0, E = GVarMD->getNumOperands(); I != E; ++I) { @@ -236,6 +270,10 @@ addressSpaceToStorageClass(unsigned AddrSpace, const SPIRVSubtarget &STI) { return SPIRV::StorageClass::CodeSectionINTEL; case 10: return SPIRV::StorageClass::Private; + case 11: + return SPIRV::StorageClass::StorageBuffer; + case 12: + return SPIRV::StorageClass::Uniform; default: report_fatal_error("Unknown address space"); } @@ -319,6 +357,10 @@ MachineInstr *getDefInstrMaybeConstant(Register &ConstReg, } else if (ConstInstr->getOpcode() == SPIRV::ASSIGN_TYPE) { ConstReg = ConstInstr->getOperand(1).getReg(); return MRI->getVRegDef(ConstReg); + } else if (ConstInstr->getOpcode() == TargetOpcode::G_CONSTANT || + ConstInstr->getOpcode() == TargetOpcode::G_FCONSTANT) { + ConstReg = ConstInstr->getOperand(0).getReg(); + return ConstInstr; } return MRI->getVRegDef(ConstReg); } @@ -685,8 +727,7 @@ bool sortBlocks(Function &F) { Order.reserve(F.size()); ReversePostOrderTraversal<Function *> RPOT(&F); - for (BasicBlock *BB : RPOT) - Order.push_back(BB); + llvm::append_range(Order, RPOT); assert(&*F.begin() == Order[0]); BasicBlock *LastBlock = &*F.begin(); @@ -738,9 +779,12 @@ void setRegClassType(Register Reg, SPIRVType *SpvType, SPIRVGlobalRegistry *GR, // no valid assigned class, set register LLT type and class according to the // SPIR-V type. void setRegClassType(Register Reg, const Type *Ty, SPIRVGlobalRegistry *GR, - MachineIRBuilder &MIRBuilder, bool Force) { - setRegClassType(Reg, GR->getOrCreateSPIRVType(Ty, MIRBuilder), GR, - MIRBuilder.getMRI(), MIRBuilder.getMF(), Force); + MachineIRBuilder &MIRBuilder, + SPIRV::AccessQualifier::AccessQualifier AccessQual, + bool EmitIR, bool Force) { + setRegClassType(Reg, + GR->getOrCreateSPIRVType(Ty, MIRBuilder, AccessQual, EmitIR), + GR, MIRBuilder.getMRI(), MIRBuilder.getMF(), Force); } // Create a virtual register and assign SPIR-V type to the register. Set @@ -764,10 +808,22 @@ Register createVirtualRegister(SPIRVType *SpvType, SPIRVGlobalRegistry *GR, // Create a SPIR-V type, virtual register and assign SPIR-V type to the // register. Set register LLT type and class according to the SPIR-V type. -Register createVirtualRegister(const Type *Ty, SPIRVGlobalRegistry *GR, - MachineIRBuilder &MIRBuilder) { - return createVirtualRegister(GR->getOrCreateSPIRVType(Ty, MIRBuilder), GR, - MIRBuilder); +Register createVirtualRegister( + const Type *Ty, SPIRVGlobalRegistry *GR, MachineIRBuilder &MIRBuilder, + SPIRV::AccessQualifier::AccessQualifier AccessQual, bool EmitIR) { + return createVirtualRegister( + GR->getOrCreateSPIRVType(Ty, MIRBuilder, AccessQual, EmitIR), GR, + MIRBuilder); +} + +CallInst *buildIntrWithMD(Intrinsic::ID IntrID, ArrayRef<Type *> Types, + Value *Arg, Value *Arg2, ArrayRef<Constant *> Imms, + IRBuilder<> &B) { + SmallVector<Value *, 4> Args; + Args.push_back(Arg2); + Args.push_back(buildMD(Arg)); + llvm::append_range(Args, Imms); + return B.CreateIntrinsic(IntrID, {Types}, Args); } // Return true if there is an opaque pointer type nested in the argument. @@ -795,4 +851,148 @@ bool isSpvIntrinsic(const Value *Arg) { return false; } +// Function to create continued instructions for SPV_INTEL_long_composites +// extension +SmallVector<MachineInstr *, 4> +createContinuedInstructions(MachineIRBuilder &MIRBuilder, unsigned Opcode, + unsigned MinWC, unsigned ContinuedOpcode, + ArrayRef<Register> Args, Register ReturnRegister, + Register TypeID) { + + SmallVector<MachineInstr *, 4> Instructions; + constexpr unsigned MaxWordCount = UINT16_MAX; + const size_t NumElements = Args.size(); + size_t MaxNumElements = MaxWordCount - MinWC; + size_t SPIRVStructNumElements = NumElements; + + if (NumElements > MaxNumElements) { + // Do adjustments for continued instructions which always had only one + // minumum word count. + SPIRVStructNumElements = MaxNumElements; + MaxNumElements = MaxWordCount - 1; + } + + auto MIB = + MIRBuilder.buildInstr(Opcode).addDef(ReturnRegister).addUse(TypeID); + + for (size_t I = 0; I < SPIRVStructNumElements; ++I) + MIB.addUse(Args[I]); + + Instructions.push_back(MIB.getInstr()); + + for (size_t I = SPIRVStructNumElements; I < NumElements; + I += MaxNumElements) { + auto MIB = MIRBuilder.buildInstr(ContinuedOpcode); + for (size_t J = I; J < std::min(I + MaxNumElements, NumElements); ++J) + MIB.addUse(Args[J]); + Instructions.push_back(MIB.getInstr()); + } + return Instructions; +} + +SmallVector<unsigned, 1> getSpirvLoopControlOperandsFromLoopMetadata(Loop *L) { + unsigned LC = SPIRV::LoopControl::None; + // Currently used only to store PartialCount value. Later when other + // LoopControls are added - this map should be sorted before making + // them loop_merge operands to satisfy 3.23. Loop Control requirements. + std::vector<std::pair<unsigned, unsigned>> MaskToValueMap; + if (getBooleanLoopAttribute(L, "llvm.loop.unroll.disable")) { + LC |= SPIRV::LoopControl::DontUnroll; + } else { + if (getBooleanLoopAttribute(L, "llvm.loop.unroll.enable") || + getBooleanLoopAttribute(L, "llvm.loop.unroll.full")) { + LC |= SPIRV::LoopControl::Unroll; + } + std::optional<int> Count = + getOptionalIntLoopAttribute(L, "llvm.loop.unroll.count"); + if (Count && Count != 1) { + LC |= SPIRV::LoopControl::PartialCount; + MaskToValueMap.emplace_back( + std::make_pair(SPIRV::LoopControl::PartialCount, *Count)); + } + } + SmallVector<unsigned, 1> Result = {LC}; + for (auto &[Mask, Val] : MaskToValueMap) + Result.push_back(Val); + return Result; +} + +const std::set<unsigned> &getTypeFoldingSupportedOpcodes() { + // clang-format off + static const std::set<unsigned> TypeFoldingSupportingOpcs = { + TargetOpcode::G_ADD, + TargetOpcode::G_FADD, + TargetOpcode::G_STRICT_FADD, + TargetOpcode::G_SUB, + TargetOpcode::G_FSUB, + TargetOpcode::G_STRICT_FSUB, + TargetOpcode::G_MUL, + TargetOpcode::G_FMUL, + TargetOpcode::G_STRICT_FMUL, + TargetOpcode::G_SDIV, + TargetOpcode::G_UDIV, + TargetOpcode::G_FDIV, + TargetOpcode::G_STRICT_FDIV, + TargetOpcode::G_SREM, + TargetOpcode::G_UREM, + TargetOpcode::G_FREM, + TargetOpcode::G_STRICT_FREM, + TargetOpcode::G_FNEG, + TargetOpcode::G_CONSTANT, + TargetOpcode::G_FCONSTANT, + TargetOpcode::G_AND, + TargetOpcode::G_OR, + TargetOpcode::G_XOR, + TargetOpcode::G_SHL, + TargetOpcode::G_ASHR, + TargetOpcode::G_LSHR, + TargetOpcode::G_SELECT, + TargetOpcode::G_EXTRACT_VECTOR_ELT, + }; + // clang-format on + return TypeFoldingSupportingOpcs; +} + +bool isTypeFoldingSupported(unsigned Opcode) { + return getTypeFoldingSupportedOpcodes().count(Opcode) > 0; +} + +// Traversing [g]MIR accounting for pseudo-instructions. +MachineInstr *passCopy(MachineInstr *Def, const MachineRegisterInfo *MRI) { + return (Def->getOpcode() == SPIRV::ASSIGN_TYPE || + Def->getOpcode() == TargetOpcode::COPY) + ? MRI->getVRegDef(Def->getOperand(1).getReg()) + : Def; +} + +MachineInstr *getDef(const MachineOperand &MO, const MachineRegisterInfo *MRI) { + if (MachineInstr *Def = MRI->getVRegDef(MO.getReg())) + return passCopy(Def, MRI); + return nullptr; +} + +MachineInstr *getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI) { + if (MachineInstr *Def = getDef(MO, MRI)) { + if (Def->getOpcode() == TargetOpcode::G_CONSTANT || + Def->getOpcode() == SPIRV::OpConstantI) + return Def; + } + return nullptr; +} + +int64_t foldImm(const MachineOperand &MO, const MachineRegisterInfo *MRI) { + if (MachineInstr *Def = getImm(MO, MRI)) { + if (Def->getOpcode() == SPIRV::OpConstantI) + return Def->getOperand(2).getImm(); + if (Def->getOpcode() == TargetOpcode::G_CONSTANT) + return Def->getOperand(1).getCImm()->getZExtValue(); + } + llvm_unreachable("Unexpected integer constant pattern"); +} + +unsigned getArrayComponentCount(const MachineRegisterInfo *MRI, + const MachineInstr *ResType) { + return foldImm(ResType->getOperand(2), MRI); +} + } // namespace llvm |
