28#include "llvm/IR/IntrinsicsSPIRV.h"
31#define DEBUG_TYPE "spirv-prelegalizer"
46void SPIRVPreLegalizerLegacy::getAnalysisUsage(
AnalysisUsage &AU)
const {
54 MI->eraseFromParent();
72 MI.getOperand(3).getMetadata()->getOperand(0))
77 GR->
add(GV,
MRI.getVRegDef(SrcReg));
80 RegsAlreadyAddedToDT[&
MI] =
Reg;
85 auto *BuildVec =
MRI.getVRegDef(SrcReg);
87 BuildVec->getOpcode() == TargetOpcode::G_BUILD_VECTOR);
88 GR->
add(Const, BuildVec);
89 for (
unsigned i = 0; i < ConstVec->getNumElements(); ++i) {
92 Constant *ElemConst = ConstVec->getElementAsConstant(i);
96 MRI.getVRegDef(BuildVec->getOperand(1 + i).getReg()));
98 BuildVec->getOperand(1 + i).setReg(ElemReg);
101 if (Const->getType()->isTargetExtTy()) {
105 GR->
add(Const, SrcMI);
106 if (SrcMI && (SrcMI->
getOpcode() == TargetOpcode::G_CONSTANT ||
107 SrcMI->
getOpcode() == TargetOpcode::G_IMPLICIT_DEF))
108 TargetExtConstTypes[SrcMI] = Const->getType();
109 if (Const->isNullValue()) {
113 Const->getType(), MIB, SPIRV::AccessQualifier::ReadWrite,
115 assert(SrcMI &&
"Expected source instruction to be valid");
122 RegsAlreadyAddedToDT[&
MI] =
Reg;
125 assert(
MI.getOperand(2).isReg() &&
"Reg operand is expected");
127 if (SrcMI &&
isSpvIntrinsic(*SrcMI, Intrinsic::spv_const_composite))
135 auto It = RegsAlreadyAddedToDT.
find(
MI);
136 if (It != RegsAlreadyAddedToDT.
end())
138 auto *RC =
MRI.getRegClassOrNull(
MI->getOperand(0).getReg());
139 if (!
MRI.getRegClassOrNull(
Reg) && RC)
141 MRI.replaceRegWith(
MI->getOperand(0).getReg(),
Reg);
156 const MDNode *MD =
MI.getOperand(2).getMetadata();
173 IE =
MRI->use_instr_end();
178 UseMI->getOperand(1).getReg() ==
Reg)
188 assert(ResType && OpType &&
"Operand types are expected");
192 if (!
MRI->getRegClassOrNull(ResVReg))
194 if (ResType == OpType)
225 "Expected destination SPIR-V type to have been assigned already.");
228 "Expected source SPIR-V type to have been assigned already.");
229 if (DstType == SrcType) {
237 if (
MI.getOpcode() != TargetOpcode::G_BITCAST)
242 MI.getOperand(1).getReg());
269 SPIRV::Extension::SPV_INTEL_function_pointers)
270 ? SPIRV::StorageClass::CodeSectionINTEL
285 AssignedPtrType->
getOpcode() == SPIRV::OpTypeUntypedPointerKHR
288 SPIRV::AccessQualifier::ReadWrite,
295 MRI->replaceRegWith(Def, Source);
326 assert(
MI &&
"Machine instr is expected");
327 if (
MI->getOperand(0).isReg()) {
332 switch (
MI->getOpcode()) {
333 case TargetOpcode::G_FCONSTANT:
334 case TargetOpcode::G_CONSTANT: {
335 Type *Ty =
MI->getOperand(1).getCImm()->getType();
337 Ty, MIB, SPIRV::AccessQualifier::ReadWrite,
true);
340 case TargetOpcode::G_GLOBAL_VALUE: {
343 unsigned AddrSpace =
Global->getType()->getAddressSpace();
348 ST.canUseExtension(SPIRV::Extension::SPV_INTEL_function_pointers))
353 Ty, MIB, SPIRV::AccessQualifier::ReadWrite,
true);
356 case TargetOpcode::G_ANYEXT:
357 case TargetOpcode::G_SEXT:
358 case TargetOpcode::G_ZEXT: {
359 if (
MI->getOperand(1).isReg()) {
361 MRI.getVRegDef(
MI->getOperand(1).getReg())) {
365 unsigned ExpectedBW =
366 std::max(
MRI.getType(
Reg).getScalarSizeInBits(), CurrentBW);
377 case TargetOpcode::G_PTRTOINT:
379 MRI.getType(
Reg).getScalarSizeInBits(), MIB);
381 case TargetOpcode::G_TRUNC:
382 case TargetOpcode::G_ADDRSPACE_CAST:
383 case TargetOpcode::G_PTR_ADD:
384 case TargetOpcode::COPY: {
397 if (SpvType.
isPointer() && RegType.isPointer() &&
399 RegType.getAddressSpace()) {
403 bool SkipCorrection =
404 MI->getOpcode() == TargetOpcode::G_GLOBAL_VALUE &&
406 SPIRV::StorageClass::CodeSectionINTEL;
407 if (!SkipCorrection) {
417 if (!
MRI.getRegClassOrNull(
Reg))
419 : &SPIRV::iIDRegClass);
434static std::optional<unsigned>
439 unsigned W = Ty.getScalarSizeInBits();
448 if (!RegType.isScalar())
450 unsigned CurrentWidth = RegType.getScalarSizeInBits();
452 if (NewWidth != CurrentWidth)
460 if (NewWidth != CurrentWidth) {
470 Def->getNextNode() ? Def->getNextNode()->getIterator() :
MBB.end();
472 while (DefIt !=
MBB.end() &&
473 (DefIt->isPHI() || DefIt->isDebugOrPseudoInstr()))
474 DefIt = std::next(DefIt);
482 assert((Ty || SpvType) &&
"Either LLVM or SPIRV type is expected.");
487 SPIRV::AccessQualifier::ReadWrite,
true);
488 if (!
MRI.getRegClassOrNull(Reg))
490 if (!
MRI.getType(Reg).isValid())
499 for (
auto &
Op :
MI.operands()) {
500 if (!
Op.isReg() ||
Op.isDef())
504 if (!SpvType && KnownResType) {
505 SpvType = KnownResType;
509 if (!
MRI.getRegClassOrNull(OpReg))
511 if (!
MRI.getType(OpReg).isValid())
528 switch (
MI.getOpcode()) {
529 case TargetOpcode::G_ASHR:
530 case TargetOpcode::G_SDIV:
531 case TargetOpcode::G_SREM:
532 case TargetOpcode::G_SITOFP:
533 case TargetOpcode::G_SMIN:
534 case TargetOpcode::G_SMAX:
536 case TargetOpcode::G_ICMP:
559 case TargetOpcode::G_CTLZ:
560 case TargetOpcode::G_CTLZ_ZERO_POISON:
561 case TargetOpcode::G_CTTZ:
562 case TargetOpcode::G_CTPOP:
572static NarrowWideningInfo
579 Info.OrigWidth.try_emplace(
Reg, *W);
585 if (std::optional<unsigned> W =
587 Info.BitCountWorklist.emplace_back(&
MI, *W);
592 bool NeedsRewrite =
false;
594 NeedsRewrite = RecordIfNarrow(MO.getReg()) || NeedsRewrite;
596 Info.SignSensitiveWorklist.push_back(&
MI);
598 RecordIfNarrow(
MI.getOperand(0).getReg());
620 auto SignExtendReg = [&](
Register Reg,
unsigned OldW,
626 Register SExted =
MRI.createGenericVirtualRegister(NewLLT);
643 MI.getOperand(0).setReg(Result);
655 auto It = Info.OrigWidth.find(
Reg);
656 if (It == Info.OrigWidth.end())
660 MI->substituteRegister(
Reg, SignExtendReg(
Reg, It->second, *
MI),
664 if (
auto It = Info.OrigWidth.find(Dst); It != Info.OrigWidth.end())
665 MaskResult(*
MI, It->second);
677 for (
auto [
MI, OldWidth] : Info.BitCountWorklist) {
688 bool HighBitsAlreadyZero =
691 auto ClearHighBits = [&](
unsigned Width) ->
Register {
692 if (HighBitsAlreadyZero)
700 switch (
MI->getOpcode()) {
701 case TargetOpcode::G_CTLZ_ZERO_POISON: {
709 case TargetOpcode::G_CTTZ: {
717 case TargetOpcode::G_CTPOP:
718 Input = ClearHighBits(OldWidth);
720 case TargetOpcode::G_CTLZ: {
722 Input = ClearHighBits(OldWidth);
726 MI->getOperand(0).setReg(
Count);
735 MI->getOperand(1).setReg(
Input);
751 bool IsExtendedInts =
753 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_integers) ||
754 ST->canUseExtension(SPIRV::Extension::SPV_KHR_bit_instructions) ||
755 ST->canUseExtension(SPIRV::Extension::SPV_INTEL_int4);
757 if (!IsExtendedInts) {
783 unsigned MIOp =
MI.getOpcode();
784 if (MIOp != TargetOpcode::G_TRUNC)
793 LLT DstTy =
MRI.getType(DstReg);
794 LLT SrcTy =
MRI.getType(SrcReg);
796 (SrcTy.isScalar() || SrcTy.isVector()) &&
797 "Expected scalar or vector G_TRUNC types");
799 "Expected matching scalar/vector G_TRUNC types");
802 "Expected equal vector element counts");
805 unsigned OriginalSrcWidth = SrcTy.getScalarSizeInBits();
814 if (OriginalDstWidth == NewDstWidth) {
815 MRI.setType(SrcReg, NewSrcTy);
819 MRI.setType(SrcReg, NewSrcTy);
820 MRI.setType(DstReg, NewDstTy);
830 Register MaskedReg =
MRI.createGenericVirtualRegister(NewSrcTy);
831 MIB.
buildAnd(MaskedReg, SrcReg, MaskReg);
833 if (NewSrcWidth == NewDstWidth) {
838 unsigned W = It->second;
842 MRI.replaceRegWith(DstReg, MaskedReg);
845 MI.getOperand(1).setReg(MaskedReg);
850 MI->eraseFromParent();
860 bool ReachedBegin =
false;
861 for (
auto MII = std::prev(
MBB->end()), Begin =
MBB->begin();
864 unsigned MIOp =
MI.getOpcode();
866 if (!IsExtendedInts) {
868 for (
auto &MOP :
MI.operands()) {
871 else if (MOP.isCImm())
881 if (SC == SPIRV::StorageClass::Function &&
883 ST->canUseExtension(SPIRV::Extension::SPV_INTEL_function_pointers))
884 SC = SPIRV::StorageClass::CodeSectionINTEL;
889 if (ST->canUseExtension(SPIRV::Extension::SPV_KHR_untyped_pointers) &&
892 ElementTy, MIB, SPIRV::AccessQualifier::ReadWrite,
906 assert(Def &&
"Expecting an instruction that defines the register");
908 if (Def->getOpcode() != TargetOpcode::G_GLOBAL_VALUE)
916 assert(Def &&
"Expecting an instruction that defines the register");
918 if (Def->getOpcode() != TargetOpcode::G_GLOBAL_VALUE)
920 if (Def->getOpcode() == TargetOpcode::COPY &&
isVector1(Ty))
924 }
else if (MIOp == TargetOpcode::FAKE_USE &&
MI.getNumOperands() > 0) {
929 for (
unsigned I = 1,
E =
MI.getNumOperands();
I !=
E && Def; ++
I)
943 }
else if (MIOp == TargetOpcode::G_CONSTANT ||
944 MIOp == TargetOpcode::G_FCONSTANT ||
945 MIOp == TargetOpcode::G_BUILD_VECTOR) {
951 if (MIOp == TargetOpcode::G_CONSTANT) {
952 auto TargetExtIt = TargetExtConstTypes.
find(&
MI);
953 Ty = TargetExtIt == TargetExtConstTypes.
end()
954 ?
MI.getOperand(1).getCImm()->getType()
955 : TargetExtIt->second;
968 }
else if (PrimaryReg !=
Reg &&
969 MRI.getType(
Reg) ==
MRI.getType(PrimaryReg)) {
970 auto *RCReg =
MRI.getRegClassOrNull(
Reg);
971 auto *RCPrimary =
MRI.getRegClassOrNull(PrimaryReg);
972 if (!RCReg || RCPrimary == RCReg) {
973 RegsAlreadyAddedToDT[&
MI] = PrimaryReg;
975 NeedAssignType =
false;
978 }
else if (MIOp == TargetOpcode::G_FCONSTANT) {
979 Ty =
MI.getOperand(1).getFPImm()->getType();
981 assert(MIOp == TargetOpcode::G_BUILD_VECTOR);
986 if (ElemMI->
getOpcode() == TargetOpcode::G_CONSTANT) {
988 }
else if (ElemMI->
getOpcode() == TargetOpcode::G_FCONSTANT) {
997 ElemTy,
MI.getNumExplicitOperands() -
MI.getNumExplicitDefs(),
1000 NeedAssignType =
false;
1004 }
else if (MIOp == TargetOpcode::G_GLOBAL_VALUE) {
1009 ReachedBegin =
true;
1015 auto It = RegsAlreadyAddedToDT.
find(
MI);
1016 if (It != RegsAlreadyAddedToDT.
end())
1017 MRI.replaceRegWith(
MI->getOperand(0).getReg(), It->second);
1025 switch (
MI.getOpcode()) {
1026 case TargetOpcode::G_TRUNC:
1027 case TargetOpcode::G_ANYEXT:
1028 case TargetOpcode::G_SEXT:
1029 case TargetOpcode::G_ZEXT:
1030 case TargetOpcode::G_PTRTOINT:
1031 case TargetOpcode::COPY:
1032 case TargetOpcode::G_ADDRSPACE_CAST:
1056 for (
unsigned Idx = StartOp, MISz =
MI->getNumOperands(); Idx != MISz;
1061 if (Idx == AsmDescOp && MO.
isImm()) {
1064 AsmDescOp += 1 +
F.getNumOperandRegisters();
1072 Ops->push_back(Idx);
1084 for (
unsigned i = 0, Sz = ToProcess.
size(); i + 1 < Sz; i += 2) {
1085 MachineInstr *I1 = ToProcess[i], *I2 = ToProcess[i + 1];
1089 if (!AsmTargetReg.
isValid()) {
1091 AsmTargetReg =
MRI.createGenericVirtualRegister(
LLT::scalar(32));
1092 MRI.setRegClass(AsmTargetReg, &SPIRV::iIDRegClass);
1096 GR->
add(AsmTargetMIB.getInstr(), AsmTargetMIB);
1100 const MDNode *IAMD = I1->getOperand(1).getMetadata();
1103 for (
const auto &ArgTy : FTy->params())
1105 ArgTy, MIRBuilder, SPIRV::AccessQualifier::ReadWrite,
true));
1108 SPIRV::AccessQualifier::ReadWrite,
true);
1110 FTy, RetType, ArgTypes, MIRBuilder);
1114 MRI.setRegClass(AsmReg, &SPIRV::iIDRegClass);
1115 auto AsmMIB = MIRBuilder.
buildInstr(SPIRV::OpAsmINTEL)
1127 GR->
add(AsmMIB.getInstr(), AsmMIB);
1134 .
addImm(
static_cast<uint32_t>(SPIRV::Decoration::SideEffectsINTEL));
1139 MRI.setRegClass(DefReg, &SPIRV::iIDRegClass);
1142 SPIRV::AccessQualifier::ReadWrite,
true);
1146 auto AsmCall = MIRBuilder.
buildInstr(SPIRV::OpAsmCallINTEL)
1150 for (
unsigned IntrIdx = 3; IntrIdx < I1->getNumOperands(); ++IntrIdx)
1151 AsmCall.
addUse(I1->getOperand(IntrIdx).getReg());
1158 if (
MRI.hasOneUse(DefReg)) {
1160 if (CopyMI.
getOpcode() == TargetOpcode::COPY) {
1162 if (
MRI.hasOneUse(CopyDst)) {
1164 if (TruncMI.
getOpcode() == TargetOpcode::G_TRUNC) {
1167 MRI.replaceRegWith(TruncReg, DefReg);
1186 MI.getOpcode() == TargetOpcode::INLINEASM)
1190 if (ToProcess.
size() == 0)
1193 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_inline_assembly))
1195 "following SPIR-V extension: SPV_INTEL_inline_assembly",
1214 MI.getOperand(2).getMetadata(), ST);
1216 Intrinsic::spv_assign_fpmaxerror_decoration)) {
1218 MI.getOperand(2).getMetadata()->getOperand(0));
1222 SPIRV::Decoration::FPMaxErrorDecorationINTEL,
1226 MI.getOperand(2).getImm(),
1227 MI.getOperand(3).getMetadata());
1246 return ConstantInt::get(Ctx, Val);
1253 assert(Ty.isValid() &&
"Expected a typed switch case value");
1254 Val =
APInt(Ty.getScalarSizeInBits(), 0);
1256 switch (Def->getOpcode()) {
1257 case SPIRV::OpConstantNull:
1258 case SPIRV::OpConstantI:
1262 for (
unsigned I = 2,
E = Def->getNumExplicitOperands();
I !=
E; ++
I) {
1270 return ConstantInt::get(Ctx, Val);
1290 for (
unsigned i = 3; i <
MI.getNumOperands(); i += 2) {
1299 while (
MI.getNumOperands() > 0)
1300 MI.removeOperand(0);
1301 for (
auto &MO : NewOperands)
1315 MI.getOpcode() == TargetOpcode::G_BRINDIRECT)
1331 BB2MBB[
MBB.getBasicBlock()] = &
MBB;
1353 for (
unsigned i = 0; i <
MI->getNumOperands(); ++i) {
1355 if (!
MI->getOperand(i).isReg()) {
1363 if (!BuildMBB || BuildMBB->
getOpcode() != TargetOpcode::G_BLOCK_ADDR) {
1368 assert(BuildMBB && BuildMBB->
getOpcode() == TargetOpcode::G_BLOCK_ADDR &&
1373 auto It = BB2MBB.
find(BB);
1374 if (It == BB2MBB.
end())
1376 "in a switch statement");
1380 ClearAddressTaken.
insert(ReferencedBlock);
1381 ToEraseMI.
insert(BuildMBB);
1386 while (
MI->getNumOperands() > 0)
1387 MI->removeOperand(0);
1388 for (
auto &MO : NewOps)
1394 Next =
MI->getNextNode();
1396 if (
Next &&
Next->getOpcode() == TargetOpcode::G_BRINDIRECT)
1405 Succ->setAddressTakenIRBlock(
nullptr);
1416 if (BlockAddrI->getOpcode() == TargetOpcode::G_BLOCK_ADDR) {
1418 BlockAddrI->getOperand(1).getBlockAddress());
1429 return MBB.getNextNode() !=
nullptr;
1433 if (!
MBB.canFallThrough())
1464 GR->setCurrentFunc(MF);
1490char SPIRVPreLegalizerLegacy::ID = 0;
1493 return new SPIRVPreLegalizerLegacy();
1496bool SPIRVPreLegalizerLegacy::runOnMachineFunction(
MachineFunction &MF) {
MachineInstrBuilder & UseMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file contains the simple types necessary to represent the attributes associated with functions a...
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Provides analysis for continuously CSEing during GISel passes.
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Provides analysis for querying information about KnownBits during GISel passes.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
Contains matchers for matching SSA Machine Instructions.
Register const TargetRegisterInfo * TRI
Promote Memory to Register
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.
MachineRegisterInfo & MRI
static std::optional< unsigned > getNarrowScalarWidth(Register Reg, const MachineRegisterInfo &MRI)
static Register collectInlineAsmInstrOperands(MachineInstr *MI, SmallVector< unsigned, 4 > *Ops=nullptr)
static void insertInlineAsm(MachineFunction &MF, SPIRVGlobalRegistry *GR, const SPIRVSubtarget &ST, MachineIRBuilder MIRBuilder)
static void cleanupHelperInstructions(MachineFunction &MF, SPIRVGlobalRegistry *GR)
static void insertInlineAsmProcess(MachineFunction &MF, SPIRVGlobalRegistry *GR, const SPIRVSubtarget &ST, MachineIRBuilder MIRBuilder, const SmallVector< MachineInstr * > &ToProcess)
static bool runPreLegalizer(MachineFunction &MF)
static NarrowWideningInfo recordNarrowOperandWidths(MachineFunction &MF, const MachineRegisterInfo &MRI)
static void removeImplicitFallthroughs(MachineFunction &MF, MachineIRBuilder MIB)
static unsigned widenBitWidthToNextPow2(unsigned BitWidth)
static void setInsertPtAfterDef(MachineIRBuilder &MIB, MachineInstr *Def)
static bool isWidthSensitiveBitCountOp(unsigned Opcode)
static bool isImplicitFallthrough(MachineBasicBlock &MBB)
static void insertSpirvDecorations(MachineFunction &MF, SPIRVGlobalRegistry *GR, MachineIRBuilder MIB)
static void insertBitcasts(MachineFunction &MF, SPIRVGlobalRegistry *GR, MachineIRBuilder MIB)
static void processInstrsWithTypeFolding(MachineFunction &MF, SPIRVGlobalRegistry *GR, MachineIRBuilder MIB)
static void processSwitchesConstants(MachineFunction &MF, SPIRVGlobalRegistry *GR, MachineIRBuilder MIB)
static void lowerBitcasts(MachineFunction &MF, SPIRVGlobalRegistry *GR, MachineIRBuilder MIB)
static MachineInstr * findAssignTypeInstr(Register Reg, MachineRegisterInfo *MRI)
static void widenCImmType(MachineOperand &MOP)
static void widenSignSensitiveOps(MachineFunction &MF, SPIRVGlobalRegistry *GR, MachineIRBuilder &MIB, MachineRegisterInfo &MRI, const NarrowWideningInfo &Info)
static void buildOpBitcast(SPIRVGlobalRegistry *GR, MachineIRBuilder &MIB, Register ResVReg, Register OpReg)
static void processBlockAddr(MachineFunction &MF, SPIRVGlobalRegistry *GR, MachineIRBuilder MIB)
static void widenBitCountOps(SPIRVGlobalRegistry *GR, MachineIRBuilder &MIB, MachineRegisterInfo &MRI, const NarrowWideningInfo &Info)
static void widenScalarType(Register Reg, MachineRegisterInfo &MRI)
static const ConstantInt * getSwitchCaseValue(Register Reg, const MachineRegisterInfo &MRI, LLVMContext &Ctx)
static void foldConstantsIntoIntrinsics(MachineFunction &MF, SPIRVGlobalRegistry *GR, MachineIRBuilder MIB)
static void addConstantsToTrack(MachineFunction &MF, SPIRVGlobalRegistry *GR, const SPIRVSubtarget &STI, DenseMap< MachineInstr *, Type * > &TargetExtConstTypes)
static SPIRVTypeInst propagateSPIRVType(MachineInstr *MI, SPIRVGlobalRegistry *GR, MachineRegisterInfo &MRI, MachineIRBuilder &MIB)
static bool isSignSensitiveOp(const MachineInstr &MI)
static void invalidateAndEraseMI(SPIRVGlobalRegistry *GR, MachineInstr *MI)
static void generateAssignInstrs(MachineFunction &MF, SPIRVGlobalRegistry *GR, MachineIRBuilder MIB, DenseMap< MachineInstr *, Type * > &TargetExtConstTypes)
APInt bitcastToAPInt() const
Class for arbitrary precision integers.
uint64_t getZExtValue() const
Get zero extended value.
LLVM_ABI APInt zextOrTrunc(unsigned width) const
Zero extend or truncate to width.
unsigned getBitWidth() const
Return the number of bits in the APInt.
APInt shl(unsigned shiftAmt) const
Left-shift function.
bool isSubsetOf(const APInt &RHS) const
This operation checks that all bits set in this APInt are also set in RHS.
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
static APInt getOneBitSet(unsigned numBits, unsigned BitNo)
Return an APInt with exactly one bit set in the result.
Represent the analysis usage information of a pass.
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
LLVM Basic Block Representation.
The address of a basic block.
BasicBlock * getBasicBlock() const
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
static LLVM_ABI Constant * getIntToPtr(Constant *C, Type *Ty, bool OnlyIfReduced=false)
ConstantFP - Floating Point Values [float, double].
const APFloat & getValueAPF() const
This is the shared class of boolean and integer constants.
unsigned getBitWidth() const
getBitWidth - Return the scalar bitwidth of this constant.
const APInt & getValue() const
Return the constant as an APInt value reference.
This is an important base class in LLVM.
LLVM_ABI void destroyConstant()
Called if some element of this constant is no longer valid.
iterator find(const_arg_type_t< KeyT > Val)
bool erase(const KeyT &Val)
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
constexpr unsigned getScalarSizeInBits() const
constexpr bool isScalar() const
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
constexpr bool isValid() const
constexpr uint16_t getNumElements() const
Returns the number of elements in a vector LLT.
constexpr bool isVector() const
constexpr ElementCount getElementCount() const
LLT changeElementSize(unsigned NewEltSize) const
If this type is a vector, return a vector with the same number of elements but the new element size.
This is an important class for using LLVM in a threaded context.
const MDOperand & getOperand(unsigned I) const
LLVM_ABI iterator getFirstNonPHI()
Returns a pointer to the first instruction in this block that is not a PHINode instruction.
MachineInstrBundleIterator< MachineInstr, true > reverse_iterator
MachineInstrBundleIterator< MachineInstr > iterator
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
const MachineBasicBlock & front() const
Helper class to build MachineInstr.
MachineInstrBuilder buildBr(MachineBasicBlock &Dest)
Build and insert G_BR Dest.
void setInsertPt(MachineBasicBlock &MBB, MachineBasicBlock::iterator II)
Set the insertion point before the specified position.
MachineInstrBuilder buildZExtInReg(const DstOp &Res, const SrcOp &Op, int64_t ImmOp)
Build and inserts Res = G_AND Op, LowBitsSet(ImmOp) Since there is no G_ZEXT_INREG like G_SEXT_INREG,...
MachineInstrBuilder buildAnd(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1)
Build and insert Res = G_AND Op0, Op1.
MachineInstrBuilder buildSub(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_SUB Op0, Op1.
MachineInstrBuilder buildShl(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
MachineInstrBuilder buildInstr(unsigned Opcode)
Build and insert <empty> = Opcode <empty>.
MachineInstrBuilder buildBuildVectorConstant(const DstOp &Res, ArrayRef< APInt > Ops)
Build and insert Res = G_BUILD_VECTOR Op0, ... where each OpN is built with G_CONSTANT.
MachineFunction & getMF()
Getter for the function we currently build.
void setInstrAndDebugLoc(MachineInstr &MI)
Set the insertion point to before MI, and set the debug loc to MI's loc.
MachineInstrBuilder buildBitcast(const DstOp &Dst, const SrcOp &Src)
Build and insert Dst = G_BITCAST Src.
MachineRegisterInfo * getMRI()
Getter for MRI.
MachineInstrBuilder buildOr(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_OR Op0, Op1.
MachineInstrBuilder buildCopy(const DstOp &Res, const SrcOp &Op)
Build and insert Res = COPY Op.
virtual MachineInstrBuilder buildConstant(const DstOp &Res, const ConstantInt &Val)
Build and insert Res = G_CONSTANT Val.
MachineInstrBuilder buildSExtInReg(const DstOp &Res, const SrcOp &Op, int64_t ImmOp)
Build and insert Res = G_SEXT_INREG Op, ImmOp.
const MachineInstrBuilder & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
Representation of each machine instruction.
mop_range defs()
Returns all explicit operands that are register definitions.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
LLVM_ABI void addOperand(MachineFunction &MF, const MachineOperand &Op)
Add the specified operand to the instruction.
LLVM_ABI void setDesc(const MCInstrDesc &TID)
Replace the instruction descriptor (thus opcode) of the current instruction with a new one.
const MachineOperand & getOperand(unsigned i) const
MachineOperand class - Representation of each machine instruction operand.
const ConstantInt * getCImm() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
const MDNode * getMetadata() const
static MachineOperand CreateCImm(const ConstantInt *CI)
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
bool isMetadata() const
isMetadata - Tests if this is a MO_Metadata operand.
const BlockAddress * getBlockAddress() const
void setCImm(const ConstantInt *CI)
bool isBlockAddress() const
isBlockAddress - Tests if this is a MO_BlockAddress operand.
Register getReg() const
getReg - Returns the register number.
const ConstantFP * getFPImm() const
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
static MachineOperand CreateMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
defusechain_instr_iterator< true, false, false, true > use_instr_iterator
use_instr_iterator/use_instr_begin/use_instr_end - Walk all uses of the specified register,...
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserve()
Mark an analysis as preserved.
Wrapper class representing virtual and physical registers.
constexpr bool isValid() const
void assignSPIRVTypeToVReg(SPIRVTypeInst Type, Register VReg, const MachineFunction &MF)
SPIRVTypeInst getOrCreateOpTypeFunctionWithArgs(const Type *Ty, SPIRVTypeInst RetType, const SmallVectorImpl< SPIRVTypeInst > &ArgTypes, MachineIRBuilder &MIRBuilder)
SPIRVTypeInst getOrCreateSPIRVPointerType(const Type *BaseType, MachineIRBuilder &MIRBuilder, SPIRV::StorageClass::StorageClass SC, bool ForceTyped=false)
const TargetRegisterClass * getRegClass(SPIRVTypeInst SpvType) const
unsigned getScalarOrVectorBitWidth(SPIRVTypeInst Type) const
void setUntypedPtrElementType(Register Reg, SPIRVTypeInst ElemType)
SPIRVTypeInst getOrCreateSPIRVIntegerType(unsigned BitWidth, MachineIRBuilder &MIRBuilder)
SPIRVTypeInst getOrCreateSPIRVVectorType(SPIRVTypeInst BaseType, unsigned NumElements, MachineIRBuilder &MIRBuilder, bool EmitIR)
unsigned getScalarOrVectorComponentCount(Register VReg) const
const Type * getTypeForSPIRVType(SPIRVTypeInst Ty) const
bool isBitcastCompatible(SPIRVTypeInst Type1, SPIRVTypeInst Type2) const
LLT getRegType(SPIRVTypeInst SpvType) const
void invalidateMachineInstr(MachineInstr *MI)
Register getSPIRVTypeID(SPIRVTypeInst SpirvType) const
SPIRVTypeInst changePointerStorageClass(SPIRVTypeInst PtrType, SPIRV::StorageClass::StorageClass SC, MachineInstr &I)
void addGlobalObject(const Value *V, const MachineFunction *MF, Register R)
SPIRVTypeInst getOrCreateSPIRVType(const Type *Type, MachineInstr &I, SPIRV::AccessQualifier::AccessQualifier AQ, bool EmitIR)
SPIRVTypeInst getSPIRVTypeForVReg(Register VReg, const MachineFunction *MF=nullptr) const
Type * getDeducedGlobalValueType(const GlobalValue *Global)
void addValueAttrs(MachineInstr *Key, std::pair< Type *, std::string > Val)
void buildMemAliasingOpDecorate(Register Reg, MachineIRBuilder &MIRBuilder, uint32_t Dec, const MDNode *GVarMD)
SPIRV::StorageClass::StorageClass getPointerStorageClass(Register VReg) const
SPIRVTypeInst getUntypedPtrElementType(Register Reg) const
bool add(SPIRV::IRHandle Handle, const MachineInstr *MI)
Register find(SPIRV::IRHandle Handle, const MachineFunction *MF)
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
const SPIRVInstrInfo * getInstrInfo() const override
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
static LLVM_ABI TypedPointerType * get(Type *ElementType, unsigned AddressSpace)
This constructs a pointer to an object of the specified type in a numbered address space.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
static LLVM_ABI VectorType * get(Type *ElementType, ElementCount EC)
This static method is the primary way to construct an VectorType.
Pass manager infrastructure for declaring and invalidating analyses.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
operand_type_match m_Reg()
ConstantMatch< APInt > m_ICst(APInt &Cst)
bool mi_match(Reg R, const MachineRegisterInfo &MRI, Pattern &&P)
BinaryOp_match< LHS, RHS, TargetOpcode::G_AND, true > m_GAnd(const LHS &L, const RHS &R)
bind_ty< MachineInstr * > m_MInstr(MachineInstr *&MI)
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > dyn_extract(Y &&MD)
Extract a Value from Metadata, if any.
This is an optimization pass for GlobalISel generic memory operations.
StringMapEntry< Value * > ValueName
void addStringImm(StringRef Str, MCInst &Inst)
bool isTypeFoldingSupported(unsigned Opcode)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Register createVirtualRegister(SPIRVTypeInst SpvType, SPIRVGlobalRegistry *GR, MachineRegisterInfo *MRI, const MachineFunction &MF)
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
void updateRegType(Register Reg, Type *Ty, SPIRVTypeInst SpirvTy, SPIRVGlobalRegistry *GR, MachineIRBuilder &MIB, MachineRegisterInfo &MRI)
Helper external function for assigning a SPIRV type to a register, ensuring the register class and ty...
void buildOpDecorate(Register Reg, MachineIRBuilder &MIRBuilder, SPIRV::Decoration::Decoration Dec, ArrayRef< uint32_t > DecArgs, StringRef StrImm)
constexpr unsigned storageClassToAddressSpace(SPIRV::StorageClass::StorageClass SC)
uint64_t PowerOf2Ceil(uint64_t A)
Returns the power of two which is greater than or equal to the given value.
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
void buildOpName(Register Target, StringRef Name, MachineIRBuilder &MIRBuilder)
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
Type * toTypedPointer(Type *Ty)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
auto post_order(const T &G)
Post-order traversal of a graph.
MachineInstr * passCopy(MachineInstr *Def, const MachineRegisterInfo *MRI)
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
@ Global
Append to llvm.global_dtors.
SPIRV::StorageClass::StorageClass addressSpaceToStorageClass(unsigned AddrSpace, const SPIRVSubtarget &STI)
void buildOpSpirvDecorations(Register Reg, MachineIRBuilder &MIRBuilder, const MDNode *GVarMD, const SPIRVSubtarget &ST)
void processInstr(MachineInstr &MI, MachineIRBuilder &MIB, MachineRegisterInfo &MRI, SPIRVGlobalRegistry *GR, SPIRVTypeInst KnownResType)
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
DWARFExpression::Operation Op
constexpr unsigned BitWidth
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Type * getMDOperandAsType(const MDNode *N, unsigned I)
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
FunctionPass * createSPIRVPreLegalizerLegacyPass()
bool isSpvIntrinsic(const MachineInstr &MI, Intrinsic::ID IntrinsicID)
MachineInstr * getVRegDef(MachineRegisterInfo &MRI, Register Reg)
SmallVector< MachineInstr * > SignSensitiveWorklist
DenseMap< Register, unsigned > OrigWidth
SmallVector< std::pair< MachineInstr *, unsigned > > BitCountWorklist