10b57cec5SDimitry Andric //===-------------- MIRCanonicalizer.cpp - MIR Canonicalizer --------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // The purpose of this pass is to employ a canonical code transformation so
100b57cec5SDimitry Andric // that code compiled with slightly different IR passes can be diffed more
110b57cec5SDimitry Andric // effectively than otherwise. This is done by renaming vregs in a given
120b57cec5SDimitry Andric // LiveRange in a canonical way. This pass also does a pseudo-scheduling to
130b57cec5SDimitry Andric // move defs closer to their use inorder to reduce diffs caused by slightly
140b57cec5SDimitry Andric // different schedules.
150b57cec5SDimitry Andric //
160b57cec5SDimitry Andric // Basic Usage:
170b57cec5SDimitry Andric //
180b57cec5SDimitry Andric // llc -o - -run-pass mir-canonicalizer example.mir
190b57cec5SDimitry Andric //
200b57cec5SDimitry Andric // Reorders instructions canonically.
210b57cec5SDimitry Andric // Renames virtual register operands canonically.
220b57cec5SDimitry Andric // Strips certain MIR artifacts (optionally).
230b57cec5SDimitry Andric //
240b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
250b57cec5SDimitry Andric
268bcb0991SDimitry Andric #include "MIRVRegNamerUtils.h"
270b57cec5SDimitry Andric #include "llvm/ADT/PostOrderIterator.h"
280b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
290b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
300b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
31480093f4SDimitry Andric #include "llvm/InitializePasses.h"
3281ad6265SDimitry Andric #include "llvm/Pass.h"
338bcb0991SDimitry Andric #include "llvm/Support/Debug.h"
340b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
350b57cec5SDimitry Andric
360b57cec5SDimitry Andric using namespace llvm;
370b57cec5SDimitry Andric
380b57cec5SDimitry Andric #define DEBUG_TYPE "mir-canonicalizer"
390b57cec5SDimitry Andric
400b57cec5SDimitry Andric static cl::opt<unsigned>
410b57cec5SDimitry Andric CanonicalizeFunctionNumber("canon-nth-function", cl::Hidden, cl::init(~0u),
420b57cec5SDimitry Andric cl::value_desc("N"),
430b57cec5SDimitry Andric cl::desc("Function number to canonicalize."));
440b57cec5SDimitry Andric
450b57cec5SDimitry Andric namespace {
460b57cec5SDimitry Andric
470b57cec5SDimitry Andric class MIRCanonicalizer : public MachineFunctionPass {
480b57cec5SDimitry Andric public:
490b57cec5SDimitry Andric static char ID;
MIRCanonicalizer()500b57cec5SDimitry Andric MIRCanonicalizer() : MachineFunctionPass(ID) {}
510b57cec5SDimitry Andric
getPassName() const520b57cec5SDimitry Andric StringRef getPassName() const override {
530b57cec5SDimitry Andric return "Rename register operands in a canonical ordering.";
540b57cec5SDimitry Andric }
550b57cec5SDimitry Andric
getAnalysisUsage(AnalysisUsage & AU) const560b57cec5SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override {
570b57cec5SDimitry Andric AU.setPreservesCFG();
580b57cec5SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU);
590b57cec5SDimitry Andric }
600b57cec5SDimitry Andric
610b57cec5SDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override;
620b57cec5SDimitry Andric };
630b57cec5SDimitry Andric
640b57cec5SDimitry Andric } // end anonymous namespace
650b57cec5SDimitry Andric
660b57cec5SDimitry Andric char MIRCanonicalizer::ID;
670b57cec5SDimitry Andric
680b57cec5SDimitry Andric char &llvm::MIRCanonicalizerID = MIRCanonicalizer::ID;
690b57cec5SDimitry Andric
700b57cec5SDimitry Andric INITIALIZE_PASS_BEGIN(MIRCanonicalizer, "mir-canonicalizer",
710b57cec5SDimitry Andric "Rename Register Operands Canonically", false, false)
720b57cec5SDimitry Andric
730b57cec5SDimitry Andric INITIALIZE_PASS_END(MIRCanonicalizer, "mir-canonicalizer",
740b57cec5SDimitry Andric "Rename Register Operands Canonically", false, false)
750b57cec5SDimitry Andric
GetRPOList(MachineFunction & MF)760b57cec5SDimitry Andric static std::vector<MachineBasicBlock *> GetRPOList(MachineFunction &MF) {
770b57cec5SDimitry Andric if (MF.empty())
780b57cec5SDimitry Andric return {};
790b57cec5SDimitry Andric ReversePostOrderTraversal<MachineBasicBlock *> RPOT(&*MF.begin());
800b57cec5SDimitry Andric std::vector<MachineBasicBlock *> RPOList;
81e8d8bef9SDimitry Andric append_range(RPOList, RPOT);
820b57cec5SDimitry Andric
830b57cec5SDimitry Andric return RPOList;
840b57cec5SDimitry Andric }
850b57cec5SDimitry Andric
860b57cec5SDimitry Andric static bool
rescheduleLexographically(std::vector<MachineInstr * > instructions,MachineBasicBlock * MBB,std::function<MachineBasicBlock::iterator ()> getPos)870b57cec5SDimitry Andric rescheduleLexographically(std::vector<MachineInstr *> instructions,
880b57cec5SDimitry Andric MachineBasicBlock *MBB,
890b57cec5SDimitry Andric std::function<MachineBasicBlock::iterator()> getPos) {
900b57cec5SDimitry Andric
910b57cec5SDimitry Andric bool Changed = false;
920b57cec5SDimitry Andric using StringInstrPair = std::pair<std::string, MachineInstr *>;
930b57cec5SDimitry Andric std::vector<StringInstrPair> StringInstrMap;
940b57cec5SDimitry Andric
950b57cec5SDimitry Andric for (auto *II : instructions) {
960b57cec5SDimitry Andric std::string S;
970b57cec5SDimitry Andric raw_string_ostream OS(S);
980b57cec5SDimitry Andric II->print(OS);
990b57cec5SDimitry Andric OS.flush();
1000b57cec5SDimitry Andric
1015ffd83dbSDimitry Andric // Trim the assignment, or start from the beginning in the case of a store.
102e8d8bef9SDimitry Andric const size_t i = S.find('=');
1030b57cec5SDimitry Andric StringInstrMap.push_back({(i == std::string::npos) ? S : S.substr(i), II});
1040b57cec5SDimitry Andric }
1050b57cec5SDimitry Andric
10681ad6265SDimitry Andric llvm::sort(StringInstrMap, llvm::less_first());
1070b57cec5SDimitry Andric
1080b57cec5SDimitry Andric for (auto &II : StringInstrMap) {
1090b57cec5SDimitry Andric
1100b57cec5SDimitry Andric LLVM_DEBUG({
1110b57cec5SDimitry Andric dbgs() << "Splicing ";
1120b57cec5SDimitry Andric II.second->dump();
1130b57cec5SDimitry Andric dbgs() << " right before: ";
1140b57cec5SDimitry Andric getPos()->dump();
1150b57cec5SDimitry Andric });
1160b57cec5SDimitry Andric
1170b57cec5SDimitry Andric Changed = true;
1180b57cec5SDimitry Andric MBB->splice(getPos(), MBB, II.second);
1190b57cec5SDimitry Andric }
1200b57cec5SDimitry Andric
1210b57cec5SDimitry Andric return Changed;
1220b57cec5SDimitry Andric }
1230b57cec5SDimitry Andric
rescheduleCanonically(unsigned & PseudoIdempotentInstCount,MachineBasicBlock * MBB)1240b57cec5SDimitry Andric static bool rescheduleCanonically(unsigned &PseudoIdempotentInstCount,
1250b57cec5SDimitry Andric MachineBasicBlock *MBB) {
1260b57cec5SDimitry Andric
1270b57cec5SDimitry Andric bool Changed = false;
1280b57cec5SDimitry Andric
1295ffd83dbSDimitry Andric // Calculates the distance of MI from the beginning of its parent BB.
1300b57cec5SDimitry Andric auto getInstrIdx = [](const MachineInstr &MI) {
1310b57cec5SDimitry Andric unsigned i = 0;
132fcaf7f86SDimitry Andric for (const auto &CurMI : *MI.getParent()) {
1330b57cec5SDimitry Andric if (&CurMI == &MI)
1340b57cec5SDimitry Andric return i;
1350b57cec5SDimitry Andric i++;
1360b57cec5SDimitry Andric }
1370b57cec5SDimitry Andric return ~0U;
1380b57cec5SDimitry Andric };
1390b57cec5SDimitry Andric
1400b57cec5SDimitry Andric // Pre-Populate vector of instructions to reschedule so that we don't
1410b57cec5SDimitry Andric // clobber the iterator.
1420b57cec5SDimitry Andric std::vector<MachineInstr *> Instructions;
1430b57cec5SDimitry Andric for (auto &MI : *MBB) {
1440b57cec5SDimitry Andric Instructions.push_back(&MI);
1450b57cec5SDimitry Andric }
1460b57cec5SDimitry Andric
1470b57cec5SDimitry Andric std::map<MachineInstr *, std::vector<MachineInstr *>> MultiUsers;
1480b57cec5SDimitry Andric std::map<unsigned, MachineInstr *> MultiUserLookup;
1490b57cec5SDimitry Andric unsigned UseToBringDefCloserToCount = 0;
1500b57cec5SDimitry Andric std::vector<MachineInstr *> PseudoIdempotentInstructions;
1510b57cec5SDimitry Andric std::vector<unsigned> PhysRegDefs;
1520b57cec5SDimitry Andric for (auto *II : Instructions) {
1530b57cec5SDimitry Andric for (unsigned i = 1; i < II->getNumOperands(); i++) {
1540b57cec5SDimitry Andric MachineOperand &MO = II->getOperand(i);
1550b57cec5SDimitry Andric if (!MO.isReg())
1560b57cec5SDimitry Andric continue;
1570b57cec5SDimitry Andric
158*bdd1243dSDimitry Andric if (MO.getReg().isVirtual())
1590b57cec5SDimitry Andric continue;
1600b57cec5SDimitry Andric
1610b57cec5SDimitry Andric if (!MO.isDef())
1620b57cec5SDimitry Andric continue;
1630b57cec5SDimitry Andric
1640b57cec5SDimitry Andric PhysRegDefs.push_back(MO.getReg());
1650b57cec5SDimitry Andric }
1660b57cec5SDimitry Andric }
1670b57cec5SDimitry Andric
1680b57cec5SDimitry Andric for (auto *II : Instructions) {
1690b57cec5SDimitry Andric if (II->getNumOperands() == 0)
1700b57cec5SDimitry Andric continue;
1710b57cec5SDimitry Andric if (II->mayLoadOrStore())
1720b57cec5SDimitry Andric continue;
1730b57cec5SDimitry Andric
1740b57cec5SDimitry Andric MachineOperand &MO = II->getOperand(0);
175*bdd1243dSDimitry Andric if (!MO.isReg() || !MO.getReg().isVirtual())
1760b57cec5SDimitry Andric continue;
1770b57cec5SDimitry Andric if (!MO.isDef())
1780b57cec5SDimitry Andric continue;
1790b57cec5SDimitry Andric
1800b57cec5SDimitry Andric bool IsPseudoIdempotent = true;
1810b57cec5SDimitry Andric for (unsigned i = 1; i < II->getNumOperands(); i++) {
1820b57cec5SDimitry Andric
1830b57cec5SDimitry Andric if (II->getOperand(i).isImm()) {
1840b57cec5SDimitry Andric continue;
1850b57cec5SDimitry Andric }
1860b57cec5SDimitry Andric
1870b57cec5SDimitry Andric if (II->getOperand(i).isReg()) {
188*bdd1243dSDimitry Andric if (!II->getOperand(i).getReg().isVirtual())
189e8d8bef9SDimitry Andric if (!llvm::is_contained(PhysRegDefs, II->getOperand(i).getReg())) {
1900b57cec5SDimitry Andric continue;
1910b57cec5SDimitry Andric }
1920b57cec5SDimitry Andric }
1930b57cec5SDimitry Andric
1940b57cec5SDimitry Andric IsPseudoIdempotent = false;
1950b57cec5SDimitry Andric break;
1960b57cec5SDimitry Andric }
1970b57cec5SDimitry Andric
1980b57cec5SDimitry Andric if (IsPseudoIdempotent) {
1990b57cec5SDimitry Andric PseudoIdempotentInstructions.push_back(II);
2000b57cec5SDimitry Andric continue;
2010b57cec5SDimitry Andric }
2020b57cec5SDimitry Andric
2030b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Operand " << 0 << " of "; II->dump(); MO.dump(););
2040b57cec5SDimitry Andric
2050b57cec5SDimitry Andric MachineInstr *Def = II;
2060b57cec5SDimitry Andric unsigned Distance = ~0U;
2070b57cec5SDimitry Andric MachineInstr *UseToBringDefCloserTo = nullptr;
2080b57cec5SDimitry Andric MachineRegisterInfo *MRI = &MBB->getParent()->getRegInfo();
2090b57cec5SDimitry Andric for (auto &UO : MRI->use_nodbg_operands(MO.getReg())) {
2100b57cec5SDimitry Andric MachineInstr *UseInst = UO.getParent();
2110b57cec5SDimitry Andric
2120b57cec5SDimitry Andric const unsigned DefLoc = getInstrIdx(*Def);
2130b57cec5SDimitry Andric const unsigned UseLoc = getInstrIdx(*UseInst);
2140b57cec5SDimitry Andric const unsigned Delta = (UseLoc - DefLoc);
2150b57cec5SDimitry Andric
2160b57cec5SDimitry Andric if (UseInst->getParent() != Def->getParent())
2170b57cec5SDimitry Andric continue;
2180b57cec5SDimitry Andric if (DefLoc >= UseLoc)
2190b57cec5SDimitry Andric continue;
2200b57cec5SDimitry Andric
2210b57cec5SDimitry Andric if (Delta < Distance) {
2220b57cec5SDimitry Andric Distance = Delta;
2230b57cec5SDimitry Andric UseToBringDefCloserTo = UseInst;
2240b57cec5SDimitry Andric MultiUserLookup[UseToBringDefCloserToCount++] = UseToBringDefCloserTo;
2250b57cec5SDimitry Andric }
2260b57cec5SDimitry Andric }
2270b57cec5SDimitry Andric
2280b57cec5SDimitry Andric const auto BBE = MBB->instr_end();
2290b57cec5SDimitry Andric MachineBasicBlock::iterator DefI = BBE;
2300b57cec5SDimitry Andric MachineBasicBlock::iterator UseI = BBE;
2310b57cec5SDimitry Andric
2320b57cec5SDimitry Andric for (auto BBI = MBB->instr_begin(); BBI != BBE; ++BBI) {
2330b57cec5SDimitry Andric
2340b57cec5SDimitry Andric if (DefI != BBE && UseI != BBE)
2350b57cec5SDimitry Andric break;
2360b57cec5SDimitry Andric
2370b57cec5SDimitry Andric if (&*BBI == Def) {
2380b57cec5SDimitry Andric DefI = BBI;
2390b57cec5SDimitry Andric continue;
2400b57cec5SDimitry Andric }
2410b57cec5SDimitry Andric
2420b57cec5SDimitry Andric if (&*BBI == UseToBringDefCloserTo) {
2430b57cec5SDimitry Andric UseI = BBI;
2440b57cec5SDimitry Andric continue;
2450b57cec5SDimitry Andric }
2460b57cec5SDimitry Andric }
2470b57cec5SDimitry Andric
2480b57cec5SDimitry Andric if (DefI == BBE || UseI == BBE)
2490b57cec5SDimitry Andric continue;
2500b57cec5SDimitry Andric
2510b57cec5SDimitry Andric LLVM_DEBUG({
2520b57cec5SDimitry Andric dbgs() << "Splicing ";
2530b57cec5SDimitry Andric DefI->dump();
2540b57cec5SDimitry Andric dbgs() << " right before: ";
2550b57cec5SDimitry Andric UseI->dump();
2560b57cec5SDimitry Andric });
2570b57cec5SDimitry Andric
2580b57cec5SDimitry Andric MultiUsers[UseToBringDefCloserTo].push_back(Def);
2590b57cec5SDimitry Andric Changed = true;
2600b57cec5SDimitry Andric MBB->splice(UseI, MBB, DefI);
2610b57cec5SDimitry Andric }
2620b57cec5SDimitry Andric
2630b57cec5SDimitry Andric // Sort the defs for users of multiple defs lexographically.
2640b57cec5SDimitry Andric for (const auto &E : MultiUserLookup) {
2650b57cec5SDimitry Andric
266e8d8bef9SDimitry Andric auto UseI = llvm::find_if(MBB->instrs(), [&](MachineInstr &MI) -> bool {
267e8d8bef9SDimitry Andric return &MI == E.second;
268e8d8bef9SDimitry Andric });
2690b57cec5SDimitry Andric
2700b57cec5SDimitry Andric if (UseI == MBB->instr_end())
2710b57cec5SDimitry Andric continue;
2720b57cec5SDimitry Andric
2730b57cec5SDimitry Andric LLVM_DEBUG(
2740b57cec5SDimitry Andric dbgs() << "Rescheduling Multi-Use Instructions Lexographically.";);
2750b57cec5SDimitry Andric Changed |= rescheduleLexographically(
2760b57cec5SDimitry Andric MultiUsers[E.second], MBB,
2770b57cec5SDimitry Andric [&]() -> MachineBasicBlock::iterator { return UseI; });
2780b57cec5SDimitry Andric }
2790b57cec5SDimitry Andric
2800b57cec5SDimitry Andric PseudoIdempotentInstCount = PseudoIdempotentInstructions.size();
2810b57cec5SDimitry Andric LLVM_DEBUG(
2820b57cec5SDimitry Andric dbgs() << "Rescheduling Idempotent Instructions Lexographically.";);
2830b57cec5SDimitry Andric Changed |= rescheduleLexographically(
2840b57cec5SDimitry Andric PseudoIdempotentInstructions, MBB,
2850b57cec5SDimitry Andric [&]() -> MachineBasicBlock::iterator { return MBB->begin(); });
2860b57cec5SDimitry Andric
2870b57cec5SDimitry Andric return Changed;
2880b57cec5SDimitry Andric }
2890b57cec5SDimitry Andric
propagateLocalCopies(MachineBasicBlock * MBB)2900b57cec5SDimitry Andric static bool propagateLocalCopies(MachineBasicBlock *MBB) {
2910b57cec5SDimitry Andric bool Changed = false;
2920b57cec5SDimitry Andric MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo();
2930b57cec5SDimitry Andric
2940b57cec5SDimitry Andric std::vector<MachineInstr *> Copies;
2950b57cec5SDimitry Andric for (MachineInstr &MI : MBB->instrs()) {
2960b57cec5SDimitry Andric if (MI.isCopy())
2970b57cec5SDimitry Andric Copies.push_back(&MI);
2980b57cec5SDimitry Andric }
2990b57cec5SDimitry Andric
3000b57cec5SDimitry Andric for (MachineInstr *MI : Copies) {
3010b57cec5SDimitry Andric
3020b57cec5SDimitry Andric if (!MI->getOperand(0).isReg())
3030b57cec5SDimitry Andric continue;
3040b57cec5SDimitry Andric if (!MI->getOperand(1).isReg())
3050b57cec5SDimitry Andric continue;
3060b57cec5SDimitry Andric
3078bcb0991SDimitry Andric const Register Dst = MI->getOperand(0).getReg();
3088bcb0991SDimitry Andric const Register Src = MI->getOperand(1).getReg();
3090b57cec5SDimitry Andric
310*bdd1243dSDimitry Andric if (!Dst.isVirtual())
3110b57cec5SDimitry Andric continue;
312*bdd1243dSDimitry Andric if (!Src.isVirtual())
3130b57cec5SDimitry Andric continue;
3140b57cec5SDimitry Andric // Not folding COPY instructions if regbankselect has not set the RCs.
3150b57cec5SDimitry Andric // Why are we only considering Register Classes? Because the verifier
3160b57cec5SDimitry Andric // sometimes gets upset if the register classes don't match even if the
3170b57cec5SDimitry Andric // types do. A future patch might add COPY folding for matching types in
3180b57cec5SDimitry Andric // pre-registerbankselect code.
3190b57cec5SDimitry Andric if (!MRI.getRegClassOrNull(Dst))
3200b57cec5SDimitry Andric continue;
3210b57cec5SDimitry Andric if (MRI.getRegClass(Dst) != MRI.getRegClass(Src))
3220b57cec5SDimitry Andric continue;
3230b57cec5SDimitry Andric
3240b57cec5SDimitry Andric std::vector<MachineOperand *> Uses;
325349cc55cSDimitry Andric for (MachineOperand &MO : MRI.use_operands(Dst))
326349cc55cSDimitry Andric Uses.push_back(&MO);
3270b57cec5SDimitry Andric for (auto *MO : Uses)
3280b57cec5SDimitry Andric MO->setReg(Src);
3290b57cec5SDimitry Andric
3300b57cec5SDimitry Andric Changed = true;
3310b57cec5SDimitry Andric MI->eraseFromParent();
3320b57cec5SDimitry Andric }
3330b57cec5SDimitry Andric
3340b57cec5SDimitry Andric return Changed;
3350b57cec5SDimitry Andric }
3360b57cec5SDimitry Andric
doDefKillClear(MachineBasicBlock * MBB)3370b57cec5SDimitry Andric static bool doDefKillClear(MachineBasicBlock *MBB) {
3380b57cec5SDimitry Andric bool Changed = false;
3390b57cec5SDimitry Andric
3400b57cec5SDimitry Andric for (auto &MI : *MBB) {
3410b57cec5SDimitry Andric for (auto &MO : MI.operands()) {
3420b57cec5SDimitry Andric if (!MO.isReg())
3430b57cec5SDimitry Andric continue;
3440b57cec5SDimitry Andric if (!MO.isDef() && MO.isKill()) {
3450b57cec5SDimitry Andric Changed = true;
3460b57cec5SDimitry Andric MO.setIsKill(false);
3470b57cec5SDimitry Andric }
3480b57cec5SDimitry Andric
3490b57cec5SDimitry Andric if (MO.isDef() && MO.isDead()) {
3500b57cec5SDimitry Andric Changed = true;
3510b57cec5SDimitry Andric MO.setIsDead(false);
3520b57cec5SDimitry Andric }
3530b57cec5SDimitry Andric }
3540b57cec5SDimitry Andric }
3550b57cec5SDimitry Andric
3560b57cec5SDimitry Andric return Changed;
3570b57cec5SDimitry Andric }
3580b57cec5SDimitry Andric
runOnBasicBlock(MachineBasicBlock * MBB,unsigned BasicBlockNum,VRegRenamer & Renamer)3590b57cec5SDimitry Andric static bool runOnBasicBlock(MachineBasicBlock *MBB,
360480093f4SDimitry Andric unsigned BasicBlockNum, VRegRenamer &Renamer) {
3610b57cec5SDimitry Andric LLVM_DEBUG({
3620b57cec5SDimitry Andric dbgs() << "\n\n NEW BASIC BLOCK: " << MBB->getName() << " \n\n";
3630b57cec5SDimitry Andric dbgs() << "\n\n================================================\n\n";
3640b57cec5SDimitry Andric });
3650b57cec5SDimitry Andric
3660b57cec5SDimitry Andric bool Changed = false;
3670b57cec5SDimitry Andric
3680b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\n\n NEW BASIC BLOCK: " << MBB->getName() << "\n\n";);
3690b57cec5SDimitry Andric
3700b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "MBB Before Canonical Copy Propagation:\n";
3710b57cec5SDimitry Andric MBB->dump(););
3720b57cec5SDimitry Andric Changed |= propagateLocalCopies(MBB);
3730b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "MBB After Canonical Copy Propagation:\n"; MBB->dump(););
3740b57cec5SDimitry Andric
3750b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "MBB Before Scheduling:\n"; MBB->dump(););
3760b57cec5SDimitry Andric unsigned IdempotentInstCount = 0;
3770b57cec5SDimitry Andric Changed |= rescheduleCanonically(IdempotentInstCount, MBB);
3780b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "MBB After Scheduling:\n"; MBB->dump(););
3790b57cec5SDimitry Andric
380480093f4SDimitry Andric Changed |= Renamer.renameVRegs(MBB, BasicBlockNum);
3810b57cec5SDimitry Andric
382480093f4SDimitry Andric // TODO: Consider dropping this. Dropping kill defs is probably not
383480093f4SDimitry Andric // semantically sound.
3840b57cec5SDimitry Andric Changed |= doDefKillClear(MBB);
3850b57cec5SDimitry Andric
3860b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Updated MachineBasicBlock:\n"; MBB->dump();
3870b57cec5SDimitry Andric dbgs() << "\n";);
3880b57cec5SDimitry Andric LLVM_DEBUG(
3890b57cec5SDimitry Andric dbgs() << "\n\n================================================\n\n");
3900b57cec5SDimitry Andric return Changed;
3910b57cec5SDimitry Andric }
3920b57cec5SDimitry Andric
runOnMachineFunction(MachineFunction & MF)3930b57cec5SDimitry Andric bool MIRCanonicalizer::runOnMachineFunction(MachineFunction &MF) {
3940b57cec5SDimitry Andric
3950b57cec5SDimitry Andric static unsigned functionNum = 0;
3960b57cec5SDimitry Andric if (CanonicalizeFunctionNumber != ~0U) {
3970b57cec5SDimitry Andric if (CanonicalizeFunctionNumber != functionNum++)
3980b57cec5SDimitry Andric return false;
3990b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\n Canonicalizing Function " << MF.getName()
4000b57cec5SDimitry Andric << "\n";);
4010b57cec5SDimitry Andric }
4020b57cec5SDimitry Andric
4030b57cec5SDimitry Andric // we need a valid vreg to create a vreg type for skipping all those
4040b57cec5SDimitry Andric // stray vreg numbers so reach alignment/canonical vreg values.
4050b57cec5SDimitry Andric std::vector<MachineBasicBlock *> RPOList = GetRPOList(MF);
4060b57cec5SDimitry Andric
4070b57cec5SDimitry Andric LLVM_DEBUG(
4080b57cec5SDimitry Andric dbgs() << "\n\n NEW MACHINE FUNCTION: " << MF.getName() << " \n\n";
4090b57cec5SDimitry Andric dbgs() << "\n\n================================================\n\n";
4100b57cec5SDimitry Andric dbgs() << "Total Basic Blocks: " << RPOList.size() << "\n";
4110b57cec5SDimitry Andric for (auto MBB
4120b57cec5SDimitry Andric : RPOList) { dbgs() << MBB->getName() << "\n"; } dbgs()
4130b57cec5SDimitry Andric << "\n\n================================================\n\n";);
4140b57cec5SDimitry Andric
4150b57cec5SDimitry Andric unsigned BBNum = 0;
4160b57cec5SDimitry Andric bool Changed = false;
4170b57cec5SDimitry Andric MachineRegisterInfo &MRI = MF.getRegInfo();
418480093f4SDimitry Andric VRegRenamer Renamer(MRI);
419fcaf7f86SDimitry Andric for (auto *MBB : RPOList)
420480093f4SDimitry Andric Changed |= runOnBasicBlock(MBB, BBNum++, Renamer);
4210b57cec5SDimitry Andric
4220b57cec5SDimitry Andric return Changed;
4230b57cec5SDimitry Andric }
424