<div dir="ltr"><div><div>This is the test I intend to add in the next week or so.<br></div>It's based on one of the dhrystone source files from the llvm test suite (that I used originally to develop the canon pass).<br><br></div>PL<br></div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Nov 2, 2017 at 6:54 AM, Justin Bogner <span dir="ltr"><<a href="mailto:mail@justinbogner.com" target="_blank">mail@justinbogner.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">Puyan Lotfi <<a href="mailto:puyan.lotfi.llvm@gmail.com">puyan.lotfi.llvm@gmail.com</a>> writes:<br>
> Alright, here's another revised patch.<br>
<br>
</span>This LGTM. I have a few more really minor nitpicks, but please feel free<br>
to commit once you deal with those.<br>
<br>
> commit 3849fba5c76ab735e1f02577e8fdd4<wbr>4365ca4f25<br>
> Author: Puyan Lotfi <<a href="mailto:plotfi@apple.com">plotfi@apple.com</a>><br>
> Date: Wed Nov 1 16:04:27 2017 -0700<br>
<span class="">><br>
> mir-canon: First commit.<br>
><br>
> mir-canon (MIRCanonicalizerPass) is a pass designed to reorder<br>
> instructions and rename operands so that two similar programs will diff<br>
> more cleanly after bring run through mir-canon than they could<br>
> otherwise. This project is still a work in progress and there are ideas<br>
> still being discussed for improving diff quality.<br>
><br>
> diff --git a/include/llvm/<wbr>InitializePasses.h b/include/llvm/<wbr>InitializePasses.h<br>
</span>> index abf69e25fd0..e9ec95170b1 100644<br>
<span class="">> --- a/include/llvm/<wbr>InitializePasses.h<br>
> +++ b/include/llvm/<wbr>InitializePasses.h<br>
> @@ -378,6 +378,7 @@ void initializeWinEHPreparePass(<wbr>PassRegistry&);<br>
> void initializeWriteBitcodePassPass<wbr>(PassRegistry&);<br>
> void initializeWriteThinLTOBitcodeP<wbr>ass(PassRegistry&);<br>
> void initializeXRayInstrumentationP<wbr>ass(PassRegistry&);<br>
> +void initializeMIRCanonicalizerPass<wbr>(PassRegistry &);<br>
><br>
> } // end namespace llvm<br>
><br>
> diff --git a/lib/CodeGen/CMakeLists.txt b/lib/CodeGen/CMakeLists.txt<br>
</span>> index 44da41ac745..05f18acb488 100644<br>
> --- a/lib/CodeGen/CMakeLists.txt<br>
> +++ b/lib/CodeGen/CMakeLists.txt<br>
> @@ -114,6 +114,7 @@ add_llvm_library(LLVMCodeGen<br>
<span class="">> RegisterPressure.cpp<br>
> RegisterScavenging.cpp<br>
> RenameIndependentSubregs.cpp<br>
> + MIRCanonicalizerPass.cpp<br>
> RegisterUsageInfo.cpp<br>
> RegUsageInfoCollector.cpp<br>
> RegUsageInfoPropagate.cpp<br>
> diff --git a/lib/CodeGen/CodeGen.cpp b/lib/CodeGen/CodeGen.cpp<br>
</span>> index c0e7511aa0c..b730f5ecf43 100644<br>
> --- a/lib/CodeGen/CodeGen.cpp<br>
> +++ b/lib/CodeGen/CodeGen.cpp<br>
> @@ -100,6 +100,7 @@ void llvm::initializeCodeGen(<wbr>PassRegistry &Registry) {<br>
<span class="">> initializeVirtRegRewriterPass(<wbr>Registry);<br>
> initializeWinEHPreparePass(<wbr>Registry);<br>
> initializeXRayInstrumentationP<wbr>ass(Registry);<br>
> + initializeMIRCanonicalizerPass<wbr>(Registry);<br>
> }<br>
><br>
> void LLVMInitializeCodeGen(<wbr>LLVMPassRegistryRef R) {<br>
> diff --git a/lib/CodeGen/<wbr>MIRCanonicalizerPass.cpp b/lib/CodeGen/<wbr>MIRCanonicalizerPass.cpp<br>
> new file mode 100644<br>
</span>> index 00000000000..5817bd2ba23<br>
> --- /dev/null<br>
> +++ b/lib/CodeGen/<wbr>MIRCanonicalizerPass.cpp<br>
> @@ -0,0 +1,632 @@<br>
<span class="">> +//===-------------- MIRCanonicalizer.cpp - MIR Canonicalizer --------------===//<br>
> +//<br>
> +// The LLVM Compiler Infrastructure<br>
> +//<br>
> +// This file is distributed under the University of Illinois Open Source<br>
> +// License. See LICENSE.TXT for details.<br>
> +//<br>
> +//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
> +//<br>
</span>> +// The purpose of this pass is to employ a canonical code transformation so<br>
> +// that code compiled with slightly different IR passes can be diffed more<br>
<span class="">> +// effectively than otherwise. This is done by renaming vregs in a given<br>
> +// LiveRange in a canonical way. This pass also does a pseudo-scheduling to<br>
</span>> +// move defs closer to their use inorder to reduce diffs caused by slightly<br>
> +// different schedules.<br>
> +//<br>
> +// Basic Usage:<br>
> +//<br>
> +// llc -o - -run-pass mir-canonicalizer example.mir<br>
<div><div class="h5">> +//<br>
> +// Reorders instructions canonically.<br>
> +// Renames virtual register operands canonically.<br>
> +// Strips certain MIR artifacts (optionally).<br>
> +//<br>
> +//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
> +<br>
> +#include "llvm/ADT/PostOrderIterator.h"<br>
> +#include "llvm/ADT/STLExtras.h"<br>
> +#include "llvm/CodeGen/Passes.h"<br>
> +#include "llvm/CodeGen/<wbr>MachineFunctionPass.h"<br>
> +#include "llvm/CodeGen/<wbr>MachineInstrBuilder.h"<br>
> +#include "llvm/CodeGen/<wbr>MachineRegisterInfo.h"<br>
> +#include "llvm/Support/raw_ostream.h"<br>
> +#include "llvm/Target/TargetInstrInfo.<wbr>h"<br>
> +<br>
> +#include <queue><br>
> +<br>
> +using namespace llvm;<br>
> +<br>
> +namespace llvm {<br>
> +extern char &MIRCanonicalizerID;<br>
> +} // namespace llvm<br>
> +<br>
> +#define DEBUG_TYPE "mir-canonicalizer"<br>
> +<br>
> +static cl::opt<unsigned><br>
> +CanonicalizeFunctionNumber("<wbr>canon-nth-function", cl::Hidden, cl::init(~0u),<br>
> + cl::value_desc("N"),<br>
> + cl::desc("Function number to canonicalize."));<br>
> +<br>
> +static cl::opt<unsigned><br>
> +CanonicalizeBasicBlockNumber(<wbr>"canon-nth-basicblock", cl::Hidden, cl::init(~0u),<br>
> + cl::value_desc("N"),<br>
> + cl::desc("BasicBlock number to canonicalize."));<br>
> +<br>
> +namespace {<br>
> +<br>
> +class MIRCanonicalizer : public MachineFunctionPass {<br>
> +public:<br>
> + static char ID;<br>
> + MIRCanonicalizer() : MachineFunctionPass(ID) {}<br>
> +<br>
> + StringRef getPassName() const override {<br>
> + return "Rename register operands in a canonical ordering.";<br>
> + }<br>
> +<br>
> + void getAnalysisUsage(AnalysisUsage &AU) const override {<br>
> + AU.setPreservesCFG();<br>
> + MachineFunctionPass::<wbr>getAnalysisUsage(AU);<br>
> + }<br>
> +<br>
> + bool runOnMachineFunction(<wbr>MachineFunction &MF) override;<br>
> +};<br>
> +<br>
> +} // end anonymous namespace<br>
> +<br>
> +enum VRType { RSE_Reg = 0, RSE_FrameIndex, RSE_NewCandidate };<br>
> +class TypedVReg {<br>
</div></div><span class="">> + VRType type;<br>
> + unsigned reg;<br>
> +<br>
</span>> +public:<br>
<span class="">> + TypedVReg(const TypedVReg &TR) : type(TR.type), reg(TR.reg) {}<br>
<br>
</span>This copy constructor is unnecessary and the default will do (for the<br>
same reason as the copy assignment operator).<br>
<br>
> + TypedVReg(unsigned reg) : type(RSE_Reg), reg(reg) {}<br>
> + TypedVReg(VRType type) : type(type), reg(~0U) {<br>
> + assert(type != RSE_Reg && "Expected a non-register type.");<br>
> + }<br>
<span class="">> +<br>
> + VRType getType() const { return type; }<br>
> + unsigned getReg() const {<br>
> + assert(this->isReg() && "Expected a virtual or physical register.");<br>
> + return reg;<br>
> + }<br>
> +<br>
> + bool isReg() const { return type == RSE_Reg; }<br>
> + bool isFrameIndex() const { return type == RSE_FrameIndex; }<br>
> + bool isCandidate() const { return type == RSE_NewCandidate; }<br>
> +};<br>
> +<br>
> +char MIRCanonicalizer::ID;<br>
> +<br>
> +char &llvm::MIRCanonicalizerID = MIRCanonicalizer::ID;<br>
> +<br>
> +INITIALIZE_PASS_BEGIN(<wbr>MIRCanonicalizer, "mir-canonicalizer",<br>
> + "Rename Register Operands Canonically", false, false);<br>
> +<br>
> +INITIALIZE_PASS_END(<wbr>MIRCanonicalizer, "mir-canonicalizer",<br>
> + "Rename Register Operands Canonically", false, false);<br>
> +<br>
> +static std::vector<MachineBasicBlock *> GetRPOList(MachineFunction &MF) {<br>
> + ReversePostOrderTraversal<<wbr>MachineBasicBlock *> RPOT(&*MF.begin());<br>
</span>> + std::vector<MachineBasicBlock *> RPOList;<br>
<span class="">> + for (auto MBB : RPOT) {<br>
> + RPOList.push_back(MBB);<br>
> + }<br>
> +<br>
> + return RPOList;<br>
> +}<br>
> +<br>
> +// Set a dummy vreg. We use this vregs register class to generate throw-away<br>
> +// vregs that are used to skip vreg numbers so that vreg numbers line up.<br>
> +static unsigned GetDummyVReg(const MachineFunction &MF) {<br>
> + for (auto &MBB : MF) {<br>
> + for (auto &MI : MBB) {<br>
> + for (auto &MO : MI.operands()) {<br>
> + if (!MO.isReg() || !TargetRegisterInfo::<wbr>isVirtualRegister(MO.getReg())<wbr>)<br>
> + continue;<br>
> + return MO.getReg();<br>
> + }<br>
> + }<br>
> + }<br>
> +<br>
> + return ~0U;<br>
> +}<br>
> +<br>
> +static bool rescheduleCanoncally(<wbr>MachineBasicBlock *MBB) {<br>
<br>
</span>Typo in the name here. Should be Canonically.<br>
<div><div class="h5"><br>
> +<br>
> + bool Changed = false;<br>
> +<br>
> + // Calculates the distance of MI from the begining of its parent BB.<br>
> + auto getInstrIdx = [](const MachineInstr &MI) {<br>
> + unsigned i = 0;<br>
> + for (auto &CurMI : *MI.getParent()) {<br>
> + if (&CurMI == &MI)<br>
> + return i;<br>
> + i++;<br>
> + }<br>
> + return ~0U;<br>
> + };<br>
> +<br>
> + // Pre-Populate vector of instructions to reschedule so that we don't<br>
> + // clobber the iterator.<br>
> + std::vector<MachineInstr *> Instructions;<br>
> + for (auto &MI : *MBB) {<br>
> + Instructions.push_back(&MI);<br>
> + }<br>
> +<br>
> + for (auto *II : Instructions) {<br>
> + if (II->getNumOperands() == 0)<br>
> + continue;<br>
> +<br>
> + MachineOperand &MO = II->getOperand(0);<br>
> + if (!MO.isReg() || !TargetRegisterInfo::<wbr>isVirtualRegister(MO.getReg())<wbr>)<br>
> + continue;<br>
> +<br>
> + DEBUG(dbgs() << "Operand " << 0 << " of "; II->dump(); MO.dump(););<br>
> +<br>
> + MachineInstr *Def = II;<br>
> + unsigned Distance = ~0U;<br>
> + MachineInstr *UseToBringDefCloserTo = nullptr;<br>
> + MachineRegisterInfo *MRI = &MBB->getParent()->getRegInfo(<wbr>);<br>
> + for (auto &UO : MRI->use_nodbg_operands(MO.<wbr>getReg())) {<br>
> + MachineInstr *UseInst = UO.getParent();<br>
> +<br>
> + const unsigned DefLoc = getInstrIdx(*Def);<br>
> + const unsigned UseLoc = getInstrIdx(*UseInst);<br>
> + const unsigned Delta = (UseLoc - DefLoc);<br>
> +<br>
> + if (UseInst->getParent() != Def->getParent())<br>
> + continue;<br>
> + if (DefLoc >= UseLoc)<br>
> + continue;<br>
> +<br>
> + if (Delta < Distance) {<br>
> + Distance = Delta;<br>
> + UseToBringDefCloserTo = UseInst;<br>
> + }<br>
> + }<br>
> +<br>
> + const auto BBE = MBB->instr_end();<br>
> + MachineBasicBlock::iterator DefI = BBE;<br>
> + MachineBasicBlock::iterator UseI = BBE;<br>
> +<br>
> + for (auto BBI = MBB->instr_begin(); BBI != BBE; ++BBI) {<br>
> +<br>
> + if (DefI != BBE && UseI != BBE)<br>
> + break;<br>
> +<br>
> + if ((&*BBI != Def) && (&*BBI != UseToBringDefCloserTo))<br>
> + continue;<br>
> +<br>
> + if (&*BBI == Def) {<br>
> + DefI = BBI;<br>
> + continue;<br>
> + }<br>
> +<br>
> + if (&*BBI == UseToBringDefCloserTo) {<br>
> + UseI = BBI;<br>
> + continue;<br>
> + }<br>
> + }<br>
> +<br>
> + if (DefI == BBE || UseI == BBE)<br>
> + continue;<br>
> +<br>
> + DEBUG({<br>
> + dbgs() << "Splicing ";<br>
> + DefI->dump();<br>
> + dbgs() << " right before: ";<br>
> + UseI->dump();<br>
> + });<br>
> +<br>
> + Changed = true;<br>
> + MBB->splice(UseI, MBB, DefI);<br>
> + }<br>
> +<br>
> + return Changed;<br>
> +}<br>
> +<br>
> +/// Here we find our candidates. What makes an interesting candidate?<br>
> +/// An candidate for a canonicalization tree root is normally any kind of<br>
> +/// instruction that causes side effects such as a store to memory or a copy to<br>
> +/// a physical register or a return instruction. We use these as an expression<br>
> +/// tree root that we walk inorder to build a canonical walk which should result<br>
> +/// in canoncal vreg renaming.<br>
> +static std::vector<MachineInstr *> populateCandidates(<wbr>MachineBasicBlock *MBB) {<br>
> + std::vector<MachineInstr *> Candidates;<br>
> + MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo()<wbr>;<br>
> +<br>
> + for (auto II = MBB->begin(), IE = MBB->end(); II != IE; ++II) {<br>
> + MachineInstr *MI = &*II;<br>
> +<br>
> + bool DoesMISideEffect = false;<br>
> +<br>
> + if (MI->getNumOperands() > 0 && MI->getOperand(0).isReg()) {<br>
> + const unsigned Dst = MI->getOperand(0).getReg();<br>
> + DoesMISideEffect |= !TargetRegisterInfo::<wbr>isVirtualRegister(Dst);<br>
> +<br>
> + for (auto UI = MRI.use_begin(Dst); UI != MRI.use_end(); ++UI) {<br>
> + if (DoesMISideEffect) break;<br>
> + DoesMISideEffect |= (UI->getParent()->getParent() != MI->getParent());<br>
> + }<br>
> + }<br>
> +<br>
> + if (!MI->mayStore() && !MI->isBranch() && !DoesMISideEffect)<br>
> + continue;<br>
> +<br>
> + DEBUG(dbgs() << "Found Candidate: "; MI->dump(););<br>
> + Candidates.push_back(MI);<br>
> + }<br>
> +<br>
> + return Candidates;<br>
> +}<br>
> +<br>
> +void doCandidateWalk(std::vector<<wbr>TypedVReg> &VRegs,<br>
</div></div>> + std::queue <TypedVReg> &RegQueue,<br>
> + std::vector<MachineInstr *> &VisitedMIs,<br>
<span class="">> + const MachineBasicBlock *MBB) {<br>
> +<br>
> + const MachineFunction &MF = *MBB->getParent();<br>
> + const MachineRegisterInfo &MRI = MF.getRegInfo();<br>
> +<br>
</span>> + while (RegQueue.size()) {<br>
<br>
Better to write !RegQueue.empty()<br>
<br>
> +<br>
> + auto TReg = RegQueue.front();<br>
> + RegQueue.pop();<br>
<span class="">> +<br>
> + if (TReg.isFrameIndex()) {<br>
> + DEBUG(dbgs() << "Popping frame index.\n";);<br>
> + VRegs.push_back(TypedVReg(RSE_<wbr>FrameIndex));<br>
> + continue;<br>
> + }<br>
> +<br>
> + assert(TReg.isReg() && "Expected vreg or physreg.");<br>
</span>> + unsigned Reg = TReg.getReg();<br>
<span class="">> +<br>
> + if (TargetRegisterInfo::<wbr>isVirtualRegister(Reg)) {<br>
> + DEBUG({<br>
> + dbgs() << "Popping vreg ";<br>
> + MRI.def_begin(Reg)->dump();<br>
> + dbgs() << "\n";<br>
> + });<br>
> +<br>
</span>> + if (!llvm::any_of(VRegs, [&](const TypedVReg &TR) {<br>
<span class="">> + return TR.isReg() && TR.getReg() == Reg;<br>
</span>> + })) {<br>
> + VRegs.push_back(TypedVReg(Reg)<wbr>);<br>
> + }<br>
<span class="">> + } else {<br>
> + DEBUG(dbgs() << "Popping physreg.\n";);<br>
> + VRegs.push_back(TypedVReg(Reg)<wbr>);<br>
> + continue;<br>
> + }<br>
> +<br>
> + for (auto RI = MRI.def_begin(Reg), RE = MRI.def_end(); RI != RE; ++RI) {<br>
> + MachineInstr *Def = RI->getParent();<br>
> +<br>
> + if (Def->getParent() != MBB)<br>
> + continue;<br>
> +<br>
</span>> + if (llvm::any_of(VisitedMIs,<br>
> + [&](const MachineInstr *VMI) { return Def == VMI; })) {<br>
> + break;<br>
> + }<br>
> +<br>
> + DEBUG({<br>
> + dbgs() << "\n========================\n"<wbr>;<br>
<span class="">> + dbgs() << "Visited MI: ";<br>
> + Def->dump();<br>
> + dbgs() << "BB Name: " << Def->getParent()->getName() << "\n";<br>
> + dbgs() << "\n========================\n"<wbr>;<br>
> + });<br>
</span>> + VisitedMIs.push_back(Def);<br>
<span class="">> + for (unsigned I = 1, E = Def->getNumOperands(); I != E; ++I) {<br>
> +<br>
> + MachineOperand &MO = Def->getOperand(I);<br>
> + if (MO.isFI()) {<br>
> + DEBUG(dbgs() << "Pushing frame index.\n";);<br>
</span>> + RegQueue.push(TypedVReg(RSE_<wbr>FrameIndex));<br>
<span class="">> + }<br>
> +<br>
> + if (!MO.isReg())<br>
> + continue;<br>
</span>> + RegQueue.push(TypedVReg(MO.<wbr>getReg()));<br>
<span class="">> + }<br>
> + }<br>
> + }<br>
> +}<br>
> +<br>
> +/// TODO: Work to remove this in the future. One day when we have named vregs<br>
<br>
</span>TODOs probably shouldn't be doc comments. Maybe move this to a regular<br>
comment inside the function.<br>
<span class=""><br>
> +/// we should be able to form the canonical name based on some characteristic<br>
> +/// we see in that point of the expression tree (like if we were to name based<br>
> +/// on some sort of value numbering scheme).<br>
> +static void SkipVRegs(unsigned &VRegGapIndex, MachineRegisterInfo &MRI,<br>
> + const TargetRegisterClass *RC) {<br>
> + const unsigned VR_GAP = (++VRegGapIndex * 1000);<br>
> +<br>
> + DEBUG({<br>
> + dbgs() << "Adjusting per-BB VR_GAP for BB" << VRegGapIndex << " to "<br>
> + << VR_GAP << "\n";<br>
> + });<br>
> +<br>
> + unsigned I = MRI.createVirtualRegister(RC);<br>
> + const unsigned E = (((I + VR_GAP) / VR_GAP) + 1) * VR_GAP;<br>
> + while (I != E) {<br>
> + I = MRI.createVirtualRegister(RC);<br>
> + }<br>
> +}<br>
> +<br>
> +static void GetVRegRenameMap(std::map<<wbr>unsigned, unsigned> &vregRenameMap,<br>
<br>
</span>Why not return the map, rather than taking an empty map as a parameter?<br>
<span class=""><br>
> + const std::vector<TypedVReg> &VRegs,<br>
> + const std::vector<unsigned> &renamedInOtherBB,<br>
<br>
</span>Capital "R".<br>
<div><div class="h5"><br>
> + MachineRegisterInfo &MRI,<br>
> + const TargetRegisterClass *RC) {<br>
> +<br>
> + unsigned LastRenameReg = MRI.createVirtualRegister(RC);<br>
> + bool FirstCandidate = true;<br>
> +<br>
> + for (auto &vreg : VRegs) {<br>
> + if (vreg.isFrameIndex()) {<br>
> + // We skip one vreg for any frame index because there is a good chance<br>
> + // (especially when comparing SelectionDAG to GlobalISel generated MIR)<br>
> + // that in the other file we are just getting an incoming vreg that comes<br>
> + // from a copy from a frame index. So it's safe to skip by one.<br>
> + LastRenameReg = MRI.createVirtualRegister(RC);<br>
> + DEBUG(dbgs() << "Skipping rename for FI " << LastRenameReg << "\n";);<br>
> + continue;<br>
> + } else if (vreg.isCandidate()) {<br>
> +<br>
> + // After the first candidate, for every subsequent candidate, we skip mod<br>
> + // 10 registers so that the candidates are more likely to start at the<br>
> + // same vreg number making it more likely that the canonical walk from the<br>
> + // candidate insruction. We don't need to skip from the first candidate of<br>
> + // the BasicBlock because we already skip ahead several vregs for each BB.<br>
> + while (LastRenameReg % 10) {<br>
> + if (!FirstCandidate) break;<br>
> + LastRenameReg = MRI.createVirtualRegister(RC);<br>
> +<br>
> + DEBUG({<br>
> + dbgs() << "Skipping rename for new candidate " << LastRenameReg<br>
> + << "\n";<br>
> + });<br>
> + }<br>
> + FirstCandidate = false;<br>
> + continue;<br>
> + } else if (!TargetRegisterInfo::<wbr>isVirtualRegister(vreg.getReg(<wbr>))) {<br>
> + LastRenameReg = MRI.createVirtualRegister(RC);<br>
> + DEBUG({<br>
> + dbgs() << "Skipping rename for Phys Reg " << LastRenameReg << "\n";<br>
> + });<br>
> + continue;<br>
> + }<br>
> +<br>
> + auto Reg = vreg.getReg();<br>
> + if (llvm::find(renamedInOtherBB, Reg) != renamedInOtherBB.end()) {<br>
> + DEBUG(dbgs() << "Vreg " << Reg << " already renamed in other BB.\n";);<br>
> + continue;<br>
> + }<br>
> +<br>
> + auto Rename = MRI.createVirtualRegister(MRI.<wbr>getRegClass(Reg));<br>
> + LastRenameReg = Rename;<br>
> +<br>
> + if (vregRenameMap.find(Reg) == vregRenameMap.end()) {<br>
> + DEBUG(dbgs() << "Mapping vreg ";);<br>
> + if (MRI.reg_begin(Reg) != MRI.reg_end()) {<br>
> + DEBUG(auto foo = &*MRI.reg_begin(Reg); foo->dump(););<br>
> + } else {<br>
> + DEBUG(dbgs() << Reg;);<br>
> + }<br>
> + DEBUG(dbgs() << " to ";);<br>
> + if (MRI.reg_begin(Rename) != MRI.reg_end()) {<br>
> + DEBUG(auto foo = &*MRI.reg_begin(Rename); foo->dump(););<br>
> + } else {<br>
> + DEBUG(dbgs() << Rename;);<br>
> + }<br>
> + DEBUG(dbgs() << "\n";);<br>
> +<br>
> + vregRenameMap.insert(std::<wbr>pair<unsigned, unsigned>(Reg, Rename));<br>
> + }<br>
> + }<br>
> +}<br>
> +<br>
> +static bool doVRegRenaming(std::vector<<wbr>unsigned> &renamedInOtherBB,<br>
> + const std::map<unsigned, unsigned> &vregRenameMap,<br>
> + MachineRegisterInfo &MRI) {<br>
> + bool Changed = false;<br>
> + for (auto I = vregRenameMap.begin(), E = vregRenameMap.end(); I != E; ++I) {<br>
> +<br>
> + auto VReg = I->first;<br>
> + auto Rename = I->second;<br>
> +<br>
> + renamedInOtherBB.push_back(<wbr>Rename);<br>
> +<br>
> + std::vector<MachineOperand *> RenameMOs;<br>
> + for (auto &MO : MRI.reg_operands(VReg)) {<br>
> + RenameMOs.push_back(&MO);<br>
> + }<br>
> +<br>
> + for (auto *MO : RenameMOs) {<br>
> + Changed = true;<br>
> + MO->setReg(Rename);<br>
> +<br>
> + if (!MO->isDef())<br>
> + MO->setIsKill(false);<br>
> + }<br>
> + }<br>
> +<br>
> + return Changed;<br>
> +}<br>
> +<br>
> +static bool doDefKillClear(<wbr>MachineBasicBlock *MBB) {<br>
> + bool Changed = false;<br>
> +<br>
> + for (auto &MI : *MBB) {<br>
> + for (auto &MO : MI.operands()) {<br>
> + if (!MO.isReg())<br>
> + continue;<br>
> + if (!MO.isDef() && MO.isKill()) {<br>
> + Changed = true;<br>
> + MO.setIsKill(false);<br>
> + }<br>
> +<br>
> + if (MO.isDef() && MO.isDead()) {<br>
> + Changed = true;<br>
> + MO.setIsDead(false);<br>
> + }<br>
> + }<br>
> + }<br>
> +<br>
> + return Changed;<br>
> +}<br>
> +<br>
> +static bool runOnBasicBlock(<wbr>MachineBasicBlock *MBB,<br>
> + std::vector<StringRef> &bbNames,<br>
> + std::vector<unsigned> &renamedInOtherBB,<br>
> + unsigned &basicBlockNum, unsigned &VRegGapIndex) {<br>
> +<br>
> + if (CanonicalizeBasicBlockNumber != ~0U) {<br>
> + if (CanonicalizeBasicBlockNumber != basicBlockNum++)<br>
> + return false;<br>
> + DEBUG(dbgs() << "\n Canonicalizing BasicBlock " << MBB->getName() << "\n";);<br>
> + }<br>
> +<br>
> + if (llvm::find(bbNames, MBB->getName()) != bbNames.end()) {<br>
> + DEBUG({<br>
> + dbgs() << "Found potentially duplicate BasicBlocks: " << MBB->getName()<br>
> + << "\n";<br>
> + });<br>
> + return false;<br>
> + }<br>
> +<br>
> + DEBUG({<br>
> + dbgs() << "\n\n NEW BASIC BLOCK: " << MBB->getName() << " \n\n";<br>
> + dbgs() << "\n\n=========================<wbr>=======================\n\n";<br>
> + });<br>
> +<br>
> + bool Changed = false;<br>
> + MachineFunction &MF = *MBB->getParent();<br>
> + MachineRegisterInfo &MRI = MF.getRegInfo();<br>
> +<br>
</div></div><span class="">> + const TargetRegisterClass *DummyRC = [] (const MachineFunction &MF) {<br>
> + const unsigned DummyVReg = GetDummyVReg(MF);<br>
</span>> + const MachineRegisterInfo &MRI = MF.getRegInfo();<br>
> + return (DummyVReg == ~0U) ? nullptr : MRI.getRegClass(DummyVReg);<br>
> + } (MF);<br>
> +<br>
> + if (!DummyRC) return false;<br>
<br>
I don't think the lambda's helping much at this point.<br>
<span class=""><br>
> +<br>
> + bbNames.push_back(MBB-><wbr>getName());<br>
> + DEBUG(dbgs() << "\n\n NEW BASIC BLOCK: " << MBB->getName() << "\n\n";);<br>
> +<br>
> + DEBUG(dbgs() << "MBB Before Scheduling:\n"; MBB->dump(););<br>
> + Changed |= rescheduleCanoncally(MBB);<br>
> + DEBUG(dbgs() << "MBB After Scheduling:\n"; MBB->dump(););<br>
> +<br>
> + std::vector<MachineInstr *> Candidates = populateCandidates(MBB);<br>
> + std::vector<MachineInstr *> VisitedMIs;<br>
> + std::copy(Candidates.begin(), Candidates.end(),<br>
> + std::back_inserter(VisitedMIs)<wbr>);<br>
> +<br>
> + std::vector<TypedVReg> VRegs;<br>
> + for (auto candidate : Candidates) {<br>
> + VRegs.push_back(TypedVReg(RSE_<wbr>NewCandidate));<br>
> +<br>
</span>> + std::queue<TypedVReg> RegQueue;<br>
<span class="">> +<br>
> + // Here we walk the vreg operands of a non-root node along our walk.<br>
> + // The root nodes are the original candidates (stores normally).<br>
> + // These are normally not the root nodes (except for the case of copies to<br>
> + // physical registers).<br>
> + for (unsigned i = 1; i < candidate->getNumOperands(); i++) {<br>
> + if (candidate->mayStore() || candidate->isBranch())<br>
> + break;<br>
> +<br>
> + MachineOperand &MO = candidate->getOperand(i);<br>
> + if (!(MO.isReg() && TargetRegisterInfo::<wbr>isVirtualRegister(MO.getReg())<wbr>))<br>
> + continue;<br>
> +<br>
> + DEBUG(dbgs() << "Enqueue register"; MO.dump(); dbgs() << "\n";);<br>
</span>> + RegQueue.push(TypedVReg(MO.<wbr>getReg()));<br>
<span class="">> + }<br>
> +<br>
> + // Here we walk the root candidates. We start from the 0th operand because<br>
> + // the root is normally a store to a vreg.<br>
> + for (unsigned i = 0; i < candidate->getNumOperands(); i++) {<br>
> +<br>
> + if (!candidate->mayStore() && !candidate->isBranch())<br>
> + break;<br>
> +<br>
> + MachineOperand &MO = candidate->getOperand(i);<br>
> +<br>
> + // TODO: Do we want to only add vregs here?<br>
> + if (!MO.isReg() && !MO.isFI())<br>
> + continue;<br>
> +<br>
> + DEBUG(dbgs() << "Enqueue Reg/FI"; MO.dump(); dbgs() << "\n";);<br>
> +<br>
</span>> + RegQueue.push(MO.isReg() ? TypedVReg(MO.getReg()) :<br>
<span class="">> + TypedVReg(RSE_FrameIndex));<br>
> + }<br>
> +<br>
> + // Now that we have pushed the operands of the candidate here, we do the<br>
> + // full breadth first walk.<br>
</span>> + doCandidateWalk(VRegs, RegQueue, VisitedMIs, MBB);<br>
<div><div class="h5">> + }<br>
> +<br>
> + // If we have populated no vregs to rename then bail.<br>
> + // The rest of this function does the vreg remaping.<br>
> + if (VRegs.size() == 0)<br>
> + return Changed;<br>
> +<br>
> + // Skip some vregs, so we can recon where we'll land next.<br>
> + SkipVRegs(VRegGapIndex, MRI, DummyRC);<br>
> +<br>
> + std::map<unsigned, unsigned> VRegRenameMap;<br>
> + GetVRegRenameMap(<wbr>VRegRenameMap, VRegs, renamedInOtherBB, MRI, DummyRC);<br>
> +<br>
> + Changed |= doVRegRenaming(<wbr>renamedInOtherBB, VRegRenameMap, MRI);<br>
> + Changed |= doDefKillClear(MBB);<br>
> +<br>
> + DEBUG(dbgs() << "Updated MachineBasicBlock:\n"; MBB->dump(); dbgs() << "\n";);<br>
> + DEBUG(dbgs() << "\n\n=========================<wbr>=======================\n\n");<br>
> + return Changed;<br>
> +}<br>
> +<br>
> +bool MIRCanonicalizer::<wbr>runOnMachineFunction(<wbr>MachineFunction &MF) {<br>
> +<br>
> + static unsigned functionNum = 0;<br>
> + if (CanonicalizeFunctionNumber != ~0U) {<br>
> + if (CanonicalizeFunctionNumber != functionNum++)<br>
> + return false;<br>
> + DEBUG(dbgs() << "\n Canonicalizing Function " << MF.getName() << "\n";);<br>
> + }<br>
> +<br>
> + // we need a valid vreg to create a vreg type for skipping all those<br>
> + // stray vreg numbers so reach alignment/canonical vreg values.<br>
<br>
</div></div>This comment's confusing. Either reword or remove it.<br>
<div class="HOEnZb"><div class="h5"><br>
> + std::vector<MachineBasicBlock*<wbr>> RPOList = GetRPOList(MF);<br>
> +<br>
> + DEBUG(<br>
> + dbgs() << "\n\n NEW MACHINE FUNCTION: " << MF.getName() << " \n\n";<br>
> + dbgs() << "\n\n=========================<wbr>=======================\n\n";<br>
> + dbgs() << "Total Basic Blocks: " << RPOList.size() << "\n";<br>
> + for (auto MBB : RPOList) {<br>
> + dbgs() << MBB->getName() << "\n";<br>
> + }<br>
> + dbgs() << "\n\n=========================<wbr>=======================\n\n";<br>
> + );<br>
> +<br>
> + std::vector<StringRef> BBNames;<br>
> + std::vector<unsigned> RenamedInOtherBB;<br>
> +<br>
> + unsigned GapIdx = 0;<br>
> + unsigned BBNum = 0;<br>
> +<br>
> + bool Changed = false;<br>
> +<br>
> + for (auto MBB : RPOList)<br>
> + Changed |= runOnBasicBlock(MBB, BBNames, RenamedInOtherBB, BBNum, GapIdx);<br>
> +<br>
> + return Changed;<br>
> +}<br>
> +<br>
</div></div></blockquote></div><br></div>