21#define GET_TARGET_REGBANK_IMPL
23#include "MipsGenRegisterBank.inc"
82 case TargetOpcode::G_FPTOSI:
83 case TargetOpcode::G_FPTOUI:
84 case TargetOpcode::G_FCMP:
95 case TargetOpcode::G_SITOFP:
96 case TargetOpcode::G_UITOFP:
104 if (
MI->getOpcode() == TargetOpcode::G_LOAD ||
105 MI->getOpcode() == TargetOpcode::G_STORE) {
106 auto MMO = *
MI->memoperands_begin();
109 (!MMO->getSize().hasValue() ||
110 MMO->getAlign() < MMO->getSize().getValue())))
118 case TargetOpcode::G_LOAD:
119 case TargetOpcode::G_STORE:
120 case TargetOpcode::G_PHI:
121 case TargetOpcode::G_SELECT:
122 case TargetOpcode::G_IMPLICIT_DEF:
123 case TargetOpcode::G_UNMERGE_VALUES:
124 case TargetOpcode::G_MERGE_VALUES:
131void MipsRegisterBankInfo::AmbiguousRegDefUseContainer::addDefUses(
134 "Pointers are gprb, they should not be considered as ambiguous.\n");
138 if (NonCopyInstr->
getOpcode() == TargetOpcode::COPY &&
142 DefUses.push_back(skipCopiesOutgoing(&
UseMI));
146void MipsRegisterBankInfo::AmbiguousRegDefUseContainer::addUseDef(
149 "Pointers are gprb, they should not be considered as ambiguous.\n");
151 UseDefs.push_back(skipCopiesIncoming(
DefMI));
155MipsRegisterBankInfo::AmbiguousRegDefUseContainer::skipCopiesOutgoing(
160 while (
Ret->getOpcode() == TargetOpcode::COPY &&
161 !
Ret->getOperand(0).getReg().isPhysical() &&
162 MRI.hasOneUse(
Ret->getOperand(0).getReg())) {
163 Ret = &(*
MRI.use_instr_begin(
Ret->getOperand(0).getReg()));
169MipsRegisterBankInfo::AmbiguousRegDefUseContainer::skipCopiesIncoming(
174 while (
Ret->getOpcode() == TargetOpcode::COPY &&
175 !
Ret->getOperand(1).getReg().isPhysical())
176 Ret =
MRI.getVRegDef(
Ret->getOperand(1).getReg());
180MipsRegisterBankInfo::AmbiguousRegDefUseContainer::AmbiguousRegDefUseContainer(
183 "Not implemented for non Ambiguous opcode.\n");
187 if (
MI->getOpcode() == TargetOpcode::G_LOAD)
188 addDefUses(
MI->getOperand(0).getReg(),
MRI);
190 if (
MI->getOpcode() == TargetOpcode::G_STORE)
191 addUseDef(
MI->getOperand(0).getReg(),
MRI);
193 if (
auto *
PHI = dyn_cast<GPhi>(
MI)) {
194 addDefUses(
PHI->getReg(0),
MRI);
196 for (
unsigned I = 1;
I <
PHI->getNumIncomingValues(); ++
I)
197 addUseDef(
PHI->getIncomingValue(
I),
MRI);
200 if (
MI->getOpcode() == TargetOpcode::G_SELECT) {
201 addDefUses(
MI->getOperand(0).getReg(),
MRI);
203 addUseDef(
MI->getOperand(2).getReg(),
MRI);
204 addUseDef(
MI->getOperand(3).getReg(),
MRI);
207 if (
MI->getOpcode() == TargetOpcode::G_IMPLICIT_DEF)
208 addDefUses(
MI->getOperand(0).getReg(),
MRI);
210 if (
MI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES)
211 addUseDef(
MI->getOperand(
MI->getNumOperands() - 1).getReg(),
MRI);
213 if (
MI->getOpcode() == TargetOpcode::G_MERGE_VALUES)
214 addDefUses(
MI->getOperand(0).getReg(),
MRI);
217bool MipsRegisterBankInfo::TypeInfoForMF::visit(
219 InstType &AmbiguousTy) {
225 AmbiguousRegDefUseContainer DefUseContainer(
MI);
232 if (AmbiguousTy == InstType::Ambiguous &&
233 (
MI->getOpcode() == TargetOpcode::G_MERGE_VALUES ||
234 MI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES))
235 AmbiguousTy = InstType::AmbiguousWithMergeOrUnmerge;
238 if (visitAdjacentInstrs(
MI, DefUseContainer.getDefUses(),
true, AmbiguousTy))
242 if (visitAdjacentInstrs(
MI, DefUseContainer.getUseDefs(),
false, AmbiguousTy))
246 if (!WaitingForTypeOfMI) {
248 setTypes(
MI, AmbiguousTy);
259 addToWaitingQueue(WaitingForTypeOfMI,
MI);
263bool MipsRegisterBankInfo::TypeInfoForMF::visitAdjacentInstrs(
265 bool isDefUse, InstType &AmbiguousTy) {
266 while (!AdjacentInstrs.
empty()) {
271 setTypes(
MI, InstType::FloatingPoint);
277 if (AdjMI->
getOpcode() == TargetOpcode::COPY) {
278 setTypesAccordingToPhysicalRegister(
MI, AdjMI, isDefUse ? 0 : 1);
284 if ((!isDefUse && AdjMI->
getOpcode() == TargetOpcode::G_UNMERGE_VALUES) ||
285 (isDefUse && AdjMI->
getOpcode() == TargetOpcode::G_MERGE_VALUES) ||
287 setTypes(
MI, InstType::Integer);
293 if (!wasVisited(AdjMI) ||
294 getRecordedTypeForInstr(AdjMI) != InstType::NotDetermined) {
295 if (
visit(AdjMI,
MI, AmbiguousTy)) {
297 setTypes(
MI, getRecordedTypeForInstr(AdjMI));
305void MipsRegisterBankInfo::TypeInfoForMF::setTypes(
const MachineInstr *
MI,
307 changeRecordedTypeForInstr(
MI, InstTy);
309 setTypes(WaitingInstr, InstTy);
313void MipsRegisterBankInfo::TypeInfoForMF::setTypesAccordingToPhysicalRegister(
316 "Copies of non physical registers should not be considered here.\n");
326 if (Bank == &Mips::FPRBRegBank)
327 setTypes(
MI, InstType::FloatingPoint);
328 else if (Bank == &Mips::GPRBRegBank)
329 setTypes(
MI, InstType::Integer);
334MipsRegisterBankInfo::InstType
335MipsRegisterBankInfo::TypeInfoForMF::determineInstType(
const MachineInstr *
MI) {
336 InstType DefaultAmbiguousType = InstType::Ambiguous;
337 visit(
MI,
nullptr, DefaultAmbiguousType);
338 return getRecordedTypeForInstr(
MI);
341void MipsRegisterBankInfo::TypeInfoForMF::cleanupIfNewFunction(
343 if (MFName != FunctionName) {
344 MFName = std::string(FunctionName);
345 WaitingQueues.clear();
353 "MSA mapping not available on target without MSA.");
378 static TypeInfoForMF TI;
381 TI.cleanupIfNewFunction(
MI.getMF()->getName());
383 unsigned Opc =
MI.getOpcode();
387 if (
MI.getOpcode() != TargetOpcode::G_PHI) {
394 using namespace TargetOpcode;
396 unsigned NumOperands =
MI.getNumOperands();
403 LLT RegTy =
MRI.getType(
Op.getReg());
414 const LLT Op0Ty =
MRI.getType(
MI.getOperand(0).getReg());
416 InstType InstTy = InstType::Integer;
451 if (Op0Size == 128) {
458 InstTy = TI.determineInstType(&
MI);
460 if (isFloatingPoint_32or64(InstTy, Op0Size) ||
461 isAmbiguous_64(InstTy, Op0Size)) {
465 assert((isInteger_32(InstTy, Op0Size) ||
466 isAmbiguous_32(InstTy, Op0Size) ||
467 isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size)) &&
468 "Unexpected Inst type");
478 InstTy = TI.determineInstType(&
MI);
481 if (isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size)) {
484 TI.clearTypeInfoData(&
MI);
488 assert((isInteger_32(InstTy, Op0Size) ||
489 isFloatingPoint_32or64(InstTy, Op0Size) ||
490 isAmbiguous_32or64(InstTy, Op0Size)) &&
491 "Unexpected Inst type");
498 InstTy = TI.determineInstType(&
MI);
499 if (isFloatingPoint_32or64(InstTy, Op0Size) ||
500 isAmbiguous_64(InstTy, Op0Size)) {
506 assert((isInteger_32(InstTy, Op0Size) ||
507 isAmbiguous_32(InstTy, Op0Size) ||
508 isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size)) &&
509 "Unexpected Inst type");
517 case G_IMPLICIT_DEF: {
519 InstTy = TI.determineInstType(&
MI);
521 if (isFloatingPoint_32or64(InstTy, Op0Size))
524 assert((isInteger_32(InstTy, Op0Size) ||
525 isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size)) &&
526 "Unexpected Inst type");
530 case G_UNMERGE_VALUES: {
531 assert(
MI.getNumOperands() == 3 &&
"Unsupported G_UNMERGE_VALUES");
532 unsigned Op3Size =
MRI.getType(
MI.getOperand(2).getReg()).getSizeInBits();
533 InstTy = TI.determineInstType(&
MI);
534 assert((isAmbiguousWithMergeOrUnmerge_64(InstTy, Op3Size) ||
535 isFloatingPoint_64(InstTy, Op3Size)) &&
536 "Unexpected Inst type");
540 if (isAmbiguousWithMergeOrUnmerge_64(InstTy, Op3Size))
544 case G_MERGE_VALUES: {
545 InstTy = TI.determineInstType(&
MI);
546 assert((isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size) ||
547 isFloatingPoint_64(InstTy, Op0Size)) &&
548 "Unexpected Inst type");
552 if (isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size))
585 assert((Op0Size == 32) &&
"Unsupported integer size");
586 unsigned SizeFP =
MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
592 assert((
MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits() == 32) &&
593 "Unsupported integer size");
621 TI.clearTypeInfoData(&
MI);
634 assert(!
B.isObservingChanges());
635 B.setChangeObserver(*
this);
638 ~InstManager() {
B.stopObservingChanges(); }
650 switch (
MI.getOpcode()) {
651 case TargetOpcode::G_STORE:
654 case TargetOpcode::G_CONSTANT:
655 case TargetOpcode::G_LOAD:
656 case TargetOpcode::G_SELECT:
657 case TargetOpcode::G_PHI:
658 case TargetOpcode::G_IMPLICIT_DEF: {
663 case TargetOpcode::G_PTR_ADD: {
664 assert(
MRI.getType(Dest).isPointer() &&
"Unexpected operand type.");
679 UpdatedDefs, Observer);
681 DeadMI->eraseFromParent();
694 InstManager NewInstrObserver(Builder, NewInstrs);
698 switch (
MI.getOpcode()) {
699 case TargetOpcode::G_LOAD:
700 case TargetOpcode::G_STORE:
701 case TargetOpcode::G_PHI:
702 case TargetOpcode::G_SELECT:
703 case TargetOpcode::G_IMPLICIT_DEF: {
706 while (!NewInstrs.
empty()) {
711 if (
auto *Unmerge = dyn_cast<GUnmerge>(NewMI))
715 else if (NewMI->
getOpcode() == TargetOpcode::G_MERGE_VALUES)
723 case TargetOpcode::G_UNMERGE_VALUES:
unsigned const MachineRegisterInfo * MRI
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
static const unsigned CustomMappingID
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This contains common code to allow clients to notify changes to machine instr.
unsigned const TargetRegisterInfo * TRI
static const MipsRegisterBankInfo::ValueMapping * getGprbOrCustomMapping(unsigned Size, unsigned &MappingID)
static bool isFloatingPointOpcodeUse(unsigned Opc)
static bool isFloatingPointOpcodeDef(unsigned Opc)
static const MipsRegisterBankInfo::ValueMapping * getMSAMapping(const MachineFunction &MF)
static bool isGprbTwoInstrUnalignedLoadOrStore(const MachineInstr *MI)
static bool isAmbiguous(unsigned Opc)
static const MipsRegisterBankInfo::ValueMapping * getFprbMapping(unsigned Size)
static void combineAwayG_UNMERGE_VALUES(LegalizationArtifactCombiner &ArtCombiner, GUnmerge &MI, GISelChangeObserver &Observer)
This file declares the targeting of the RegisterBankInfo class for Mips.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
void visit(MachineFunction &MF, MachineBasicBlock &Start, std::function< void(MachineBasicBlock *)> op)
This class represents an Operation in the Expression.
Abstract class that contains various methods for clients to notify about changes.
void insert(MachineInstr *I)
Add the specified instruction to the worklist if it isn't already in it.
MachineInstr * pop_back_val()
Represents a G_UNMERGE_VALUES.
constexpr bool isScalar() const
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
constexpr bool isVector() const
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
constexpr bool isPointer() const
bool tryCombineUnmergeValues(GUnmerge &MI, SmallVectorImpl< MachineInstr * > &DeadInsts, SmallVectorImpl< Register > &UpdatedDefs, GISelChangeObserver &Observer)
LegalizeResult narrowScalar(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
Legalize an instruction by reducing the width of the underlying scalar type.
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.
Helper class to build MachineInstr.
void setInstrAndDebugLoc(MachineInstr &MI)
Set the insertion point to before MI, and set the debug loc to MI's loc.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineFunction * getMF() const
Return the function that contains the basic block that this instruction belongs to.
const MachineOperand & getOperand(unsigned i) const
MachineOperand class - Representation of each machine instruction operand.
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
void applyMappingImpl(MachineIRBuilder &Builder, const OperandsMapper &OpdMapper) const override
Here we have to narrowScalar s64 operands to s32, combine away G_MERGE or G_UNMERGE and erase instruc...
MipsRegisterBankInfo(const TargetRegisterInfo &TRI)
void setRegBank(MachineInstr &MI, MachineRegisterInfo &MRI) const
RegBankSelect determined that s64 operand is better to be split into two s32 operands in gprb.
const InstructionMapping & getInstrMapping(const MachineInstr &MI) const override
Get the mapping of the different operands of MI on the register bank.
bool systemSupportsUnalignedAccess() const
Does the system support unaligned memory access.
Helper class that represents how the value of an instruction may be mapped and what is the related co...
bool isValid() const
Check whether this object is valid.
Helper class used to get/create the virtual registers that will be used to replace the MachineOperand...
MachineInstr & getMI() const
MachineRegisterInfo & getMRI() const
The MachineRegisterInfo we used to realize the mapping.
Holds all the information related to register banks.
const InstructionMapping & getInstructionMapping(unsigned ID, unsigned Cost, const ValueMapping *OperandsMapping, unsigned NumOperands) const
Method to get a uniquely generated InstructionMapping.
static void applyDefaultMapping(const OperandsMapper &OpdMapper)
Helper method to apply something that is like the default mapping.
const InstructionMapping & getInvalidInstructionMapping() const
Method to get a uniquely generated invalid InstructionMapping.
const RegisterBank & getRegBank(unsigned ID)
Get the register bank identified by ID.
TypeSize getSizeInBits(Register Reg, const MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI) const
Get the size in bits of Reg.
const ValueMapping * getOperandsMapping(Iterator Begin, Iterator End) const
Get the uniquely generated array of ValueMapping for the elements of between Begin and End.
static const unsigned DefaultMappingID
Identifier used when the related instruction mapping instance is generated by target independent code...
const InstructionMapping & getInstrMappingImpl(const MachineInstr &MI) const
Try to get the mapping of MI.
This class implements the register bank concept.
Wrapper class representing virtual and physical registers.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
virtual const RegisterBankInfo * getRegBankInfo() const
If the information for the register banks is available, return it.
virtual const LegalizerInfo * getLegalizerInfo() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
const RegisterBankInfo::ValueMapping ValueMappings[]
const RegisterBankInfo::PartialMapping PartMappings[]
This is an optimization pass for GlobalISel generic memory operations.
bool isPreISelGenericFloatingPointOpcode(unsigned Opc)
Returns whether opcode Opc is a pre-isel generic floating-point opcode, having only floating-point op...
Helper struct that represents how a value is partially mapped into a register.
Helper struct that represents how a value is mapped through different register banks.