43 #define DEBUG_TYPE "mir-canonicalizer" 48 cl::desc(
"Function number to canonicalize."));
52 cl::desc(
"BasicBlock number to canonicalize."));
62 return "Rename register operands in a canonical ordering.";
92 assert(this->
isReg() &&
"Expected a virtual or physical register.");
102 "Rename Register Operands Canonically",
false,
false)
109 std::vector<MachineBasicBlock *> RPOList;
110 for (
auto MBB : RPOT) {
111 RPOList.push_back(MBB);
122 bool Changed =
false;
123 using StringInstrPair = std::pair<std::string, MachineInstr *>;
124 std::vector<StringInstrPair> StringInstrMap;
126 for (
auto *II : instructions) {
133 const size_t i = S.find(
"=");
134 StringInstrMap.push_back({(i == std::string::npos) ? S : S.substr(i), II});
138 [](
const StringInstrPair &a,
const StringInstrPair &b) ->
bool {
139 return (a.first < b.first);
142 for (
auto &II : StringInstrMap) {
145 dbgs() <<
"Splicing ";
147 dbgs() <<
" right before: ";
152 MBB->
splice(getPos(), MBB, II.second);
161 bool Changed =
false;
166 for (
auto &CurMI : *
MI.getParent()) {
176 std::vector<MachineInstr *> Instructions;
177 for (
auto &
MI : *MBB) {
178 Instructions.push_back(&
MI);
181 std::map<MachineInstr *, std::vector<MachineInstr *>> MultiUsers;
182 std::vector<MachineInstr *> PseudoIdempotentInstructions;
183 std::vector<unsigned> PhysRegDefs;
184 for (
auto *II : Instructions) {
185 for (
unsigned i = 1; i < II->getNumOperands(); i++) {
196 PhysRegDefs.push_back(MO.
getReg());
200 for (
auto *II : Instructions) {
201 if (II->getNumOperands() == 0)
203 if (II->mayLoadOrStore())
212 bool IsPseudoIdempotent =
true;
213 for (
unsigned i = 1; i < II->getNumOperands(); i++) {
215 if (II->getOperand(i).isImm()) {
219 if (II->getOperand(i).isReg()) {
221 if (
llvm::find(PhysRegDefs, II->getOperand(i).getReg()) ==
227 IsPseudoIdempotent =
false;
231 if (IsPseudoIdempotent) {
232 PseudoIdempotentInstructions.push_back(II);
239 unsigned Distance = ~0U;
245 const unsigned DefLoc = getInstrIdx(*Def);
246 const unsigned UseLoc = getInstrIdx(*UseInst);
247 const unsigned Delta = (UseLoc - DefLoc);
251 if (DefLoc >= UseLoc)
254 if (Delta < Distance) {
256 UseToBringDefCloserTo = UseInst;
260 const auto BBE = MBB->instr_end();
264 for (
auto BBI = MBB->instr_begin(); BBI != BBE; ++BBI) {
266 if (DefI != BBE && UseI != BBE)
274 if (&*BBI == UseToBringDefCloserTo) {
280 if (DefI == BBE || UseI == BBE)
284 dbgs() <<
"Splicing ";
286 dbgs() <<
" right before: ";
290 MultiUsers[UseToBringDefCloserTo].push_back(Def);
292 MBB->splice(UseI, MBB, DefI);
296 for (
const auto &
E : MultiUsers) {
302 if (UseI == MBB->instr_end())
306 dbgs() <<
"Rescheduling Multi-Use Instructions Lexographically.";);
311 PseudoIdempotentInstCount = PseudoIdempotentInstructions.size();
313 dbgs() <<
"Rescheduling Idempotent Instructions Lexographically.";);
315 PseudoIdempotentInstructions, MBB,
322 bool Changed =
false;
325 std::vector<MachineInstr *>
Copies;
328 Copies.push_back(&
MI);
333 if (!
MI->getOperand(0).isReg())
335 if (!
MI->getOperand(1).isReg())
338 const unsigned Dst =
MI->getOperand(0).getReg();
339 const unsigned Src =
MI->getOperand(1).getReg();
354 MI->eraseFromParent();
367 std::vector<MachineInstr *> Candidates;
370 for (
auto II = MBB->
begin(),
IE = MBB->
end(); II !=
IE; ++II) {
373 bool DoesMISideEffect =
false;
380 if (DoesMISideEffect)
382 DoesMISideEffect |= (UI->getParent()->getParent() != MI->
getParent());
390 Candidates.push_back(MI);
397 std::queue<TypedVReg> &RegQueue,
398 std::vector<MachineInstr *> &VisitedMIs,
404 while (!RegQueue.empty()) {
406 auto TReg = RegQueue.front();
409 if (TReg.isFrameIndex()) {
415 assert(TReg.isReg() &&
"Expected vreg or physreg.");
416 unsigned Reg = TReg.getReg();
420 dbgs() <<
"Popping vreg ";
448 dbgs() <<
"\n========================\n";
449 dbgs() <<
"Visited MI: ";
452 dbgs() <<
"\n========================\n";
454 VisitedMIs.push_back(Def);
472 class NamedVRegCursor {
474 unsigned virtualVRegNumber;
478 unsigned VRegGapIndex = 0;
479 const unsigned VR_GAP = (++VRegGapIndex * 1000);
482 const unsigned E = (((I + VR_GAP) / VR_GAP) + 1) * VR_GAP;
484 virtualVRegNumber =
E;
488 unsigned VRegGapIndex = 1;
489 const unsigned VR_GAP = (++VRegGapIndex * 1000);
491 unsigned I = virtualVRegNumber;
492 const unsigned E = (((I + VR_GAP) / VR_GAP) + 1) * VR_GAP;
494 virtualVRegNumber =
E;
497 unsigned getVirtualVReg()
const {
return virtualVRegNumber; }
499 unsigned incrementVirtualVReg(
unsigned incr = 1) {
500 virtualVRegNumber += incr;
501 return virtualVRegNumber;
507 OS <<
"namedVReg" << (virtualVRegNumber & ~0x80000000);
516 static std::map<unsigned, unsigned>
518 const std::vector<unsigned> &renamedInOtherBB,
520 std::map<unsigned, unsigned> VRegRenameMap;
521 bool FirstCandidate =
true;
523 for (
auto &vreg : VRegs) {
524 if (vreg.isFrameIndex()) {
529 unsigned LastRenameReg = NVC.incrementVirtualVReg();
531 LLVM_DEBUG(
dbgs() <<
"Skipping rename for FI " << LastRenameReg <<
"\n";);
533 }
else if (vreg.isCandidate()) {
540 unsigned LastRenameReg = NVC.getVirtualVReg();
542 NVC.incrementVirtualVReg(LastRenameReg % 10);
543 FirstCandidate =
false;
546 unsigned LastRenameReg = NVC.incrementVirtualVReg();
549 dbgs() <<
"Skipping rename for Phys Reg " << LastRenameReg <<
"\n";
554 auto Reg = vreg.getReg();
555 if (
llvm::find(renamedInOtherBB,
Reg) != renamedInOtherBB.end()) {
557 <<
" already renamed in other BB.\n";);
563 if (VRegRenameMap.find(
Reg) == VRegRenameMap.end()) {
578 VRegRenameMap.insert(std::pair<unsigned, unsigned>(
Reg, Rename));
582 return VRegRenameMap;
586 const std::map<unsigned, unsigned> &VRegRenameMap,
588 bool Changed =
false;
589 for (
auto I = VRegRenameMap.begin(),
E = VRegRenameMap.end();
I !=
E; ++
I) {
591 auto VReg =
I->first;
592 auto Rename =
I->second;
594 RenamedInOtherBB.push_back(Rename);
596 std::vector<MachineOperand *> RenameMOs;
598 RenameMOs.push_back(&MO);
601 for (
auto *MO : RenameMOs) {
606 MO->setIsKill(
false);
614 bool Changed =
false;
616 for (
auto &
MI : *MBB) {
617 for (
auto &MO :
MI.operands()) {
620 if (!MO.isDef() && MO.isKill()) {
625 if (MO.isDef() && MO.isDead()) {
636 std::vector<StringRef> &bbNames,
637 std::vector<unsigned> &renamedInOtherBB,
638 unsigned &basicBlockNum,
unsigned &VRegGapIndex,
639 NamedVRegCursor &NVC) {
650 dbgs() <<
"Found potentially duplicate BasicBlocks: " << MBB->
getName()
657 dbgs() <<
"\n\n NEW BASIC BLOCK: " << MBB->
getName() <<
" \n\n";
658 dbgs() <<
"\n\n================================================\n\n";
661 bool Changed =
false;
665 bbNames.push_back(MBB->
getName());
674 unsigned IdempotentInstCount = 0;
679 std::vector<MachineInstr *> VisitedMIs;
680 llvm::copy(Candidates, std::back_inserter(VisitedMIs));
682 std::vector<TypedVReg> VRegs;
683 for (
auto candidate : Candidates) {
684 VRegs.push_back(
TypedVReg(RSE_NewCandidate));
686 std::queue<TypedVReg> RegQueue;
692 for (
unsigned i = 1; i < candidate->getNumOperands(); i++) {
693 if (candidate->mayStore() || candidate->isBranch())
706 for (
unsigned i = 0; i < candidate->getNumOperands(); i++) {
708 if (!candidate->mayStore() && !candidate->isBranch())
728 if (VRegs.size() == 0)
740 auto MII = MBB->
begin();
741 for (
unsigned i = 0; i < IdempotentInstCount && MII != MBB->
end(); ++i) {
745 auto Rename = NVC.createVirtualRegister(MRI.
getRegClass(vRegToRename));
747 std::vector<MachineOperand *> RenameMOs;
749 RenameMOs.push_back(&MO);
752 for (
auto *MO : RenameMOs) {
762 dbgs() <<
"\n\n================================================\n\n");
768 static unsigned functionNum = 0;
778 std::vector<MachineBasicBlock *> RPOList =
GetRPOList(MF);
781 dbgs() <<
"\n\n NEW MACHINE FUNCTION: " << MF.
getName() <<
" \n\n";
782 dbgs() <<
"\n\n================================================\n\n";
783 dbgs() <<
"Total Basic Blocks: " << RPOList.size() <<
"\n";
786 <<
"\n\n================================================\n\n";);
788 std::vector<StringRef> BBNames;
789 std::vector<unsigned> RenamedInOtherBB;
794 bool Changed =
false;
797 NamedVRegCursor NVC(MRI);
798 for (
auto MBB : RPOList)
static bool isReg(const MCInst &MI, unsigned OpNo)
static bool doVRegRenaming(std::vector< unsigned > &RenamedInOtherBB, const std::map< unsigned, unsigned > &VRegRenameMap, MachineRegisterInfo &MRI)
char & MIRCanonicalizerID
static std::vector< MachineInstr * > populateCandidates(MachineBasicBlock *MBB)
Here we find our candidates.
const TargetRegisterClass * getRegClass(unsigned Reg) const
Return the register class of the specified virtual register.
This class represents lattice values for constants.
iterator_range< use_nodbg_iterator > use_nodbg_operands(unsigned Reg) const
unsigned getReg() const
getReg - Returns the register number.
static bool isVirtualRegister(unsigned Reg)
Return true if the specified register number is in the virtual register namespace.
static bool rescheduleLexographically(std::vector< MachineInstr *> instructions, MachineBasicBlock *MBB, std::function< MachineBasicBlock::iterator()> getPos)
iterator_range< reg_iterator > reg_operands(unsigned Reg) const
static use_iterator use_end()
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
unsigned getNumOperands() const
Retuns the total number of operands.
mir Rename Register Operands Canonically
def_iterator def_begin(unsigned RegNo) const
static bool doDefKillClear(MachineBasicBlock *MBB)
static cl::opt< unsigned > CanonicalizeFunctionNumber("canon-nth-function", cl::Hidden, cl::init(~0u), cl::value_desc("N"), cl::desc("Function number to canonicalize."))
static cl::opt< unsigned > CanonicalizeBasicBlockNumber("canon-nth-basicblock", cl::Hidden, cl::init(~0u), cl::value_desc("N"), cl::desc("BasicBlock number to canonicalize."))
bool isBranch(QueryType Type=AnyInBundle) const
Returns true if this is a conditional, unconditional, or indirect branch.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
bool mayStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly modify memory.
bool isFrameIndex() const
initializer< Ty > init(const Ty &Val)
unsigned const MachineRegisterInfo * MRI
StringRef getName() const
Return the name of the corresponding LLVM basic block, or an empty string.
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
mir Rename Register Operands static false std::vector< MachineBasicBlock * > GetRPOList(MachineFunction &MF)
Represent the analysis usage information of a pass.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly...
static bool rescheduleCanonically(unsigned &PseudoIdempotentInstCount, MachineBasicBlock *MBB)
auto find_if(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range))
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly...
auto find(R &&Range, const T &Val) -> decltype(adl_begin(Range))
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly...
std::string & str()
Flushes the stream contents to the target string and returns the string's reference.
INITIALIZE_PASS_END(RegBankSelect, DEBUG_TYPE, "Assign register bank of generic virtual registers", false, false) RegBankSelect
void sort(IteratorTy Start, IteratorTy End)
unsigned createIncompleteVirtualRegister(StringRef Name="")
Creates a new virtual register that has no register class, register bank or size assigned yet...
MachineOperand class - Representation of each machine instruction operand.
Promote Memory to Register
reg_iterator reg_begin(unsigned RegNo) const
void setPreservesCFG()
This function should be called by the pass, iff they do not:
static bool propagateLocalCopies(MachineBasicBlock *MBB)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
INITIALIZE_PASS_BEGIN(MIRCanonicalizer, "mir-canonicalizer", "Rename Register Operands Canonically", false, false) INITIALIZE_PASS_END(MIRCanonicalizer
static bool runOnBasicBlock(MachineBasicBlock *MBB, std::vector< StringRef > &bbNames, std::vector< unsigned > &renamedInOtherBB, unsigned &basicBlockNum, unsigned &VRegGapIndex, NamedVRegCursor &NVC)
static std::map< unsigned, unsigned > GetVRegRenameMap(const std::vector< TypedVReg > &VRegs, const std::vector< unsigned > &renamedInOtherBB, MachineRegisterInfo &MRI, NamedVRegCursor &NVC)
const MachineBasicBlock * getParent() const
MachineRegisterInfo - Keep track of information for virtual and physical registers, including vreg register classes, use/def chains for registers, etc.
Representation of each machine instruction.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
use_iterator use_begin(unsigned RegNo) const
void setReg(unsigned Reg)
Change the register this operand corresponds to.
bool isFI() const
isFI - Tests if this is a MO_FrameIndex operand.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static def_iterator def_end()
A raw_ostream that writes to an std::string.
print Print MemDeps of function
StringRef - Represent a constant reference to a string, i.e.
inst_range instructions(Function *F)
static reg_iterator reg_end()
const MachineOperand & getOperand(unsigned i) const
OutputIt copy(R &&Range, OutputIt Out)
unsigned createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
static void doCandidateWalk(std::vector< TypedVReg > &VRegs, std::queue< TypedVReg > &RegQueue, std::vector< MachineInstr *> &VisitedMIs, const MachineBasicBlock *MBB)