aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Target/SPIRV/SPIRVUtils.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/SPIRV/SPIRVUtils.cpp')
-rw-r--r--llvm/lib/Target/SPIRV/SPIRVUtils.cpp218
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