mir-canon simplified patch

Puyan Lotfi via llvm-commits llvm-commits at lists.llvm.org
Fri Oct 27 16:29:01 PDT 2017


Thanks Justin!

I have an updated patch, addressing the provided feedback.

Thanks Again

-Puyan



On Tue, Oct 24, 2017 at 8:04 PM, Justin Bogner <mail at justinbogner.com>
wrote:

> Puyan Lotfi <puyan.lotfi.llvm at gmail.com> writes:
> > Hi
> >
> > I've reorganized my mir-canon code into a single pass. Standalone tool is
> > now gone based on community feedback.
>
> This is looking pretty good. A bunch of style and consistency nitpicks
> below. Thanks for working on this!
>
> > Next steps will be to work on vreg naming issues in llvm (as described in
> > the mir-canon rfc, skipping lots of vregs can get expensive as far as
> > compile time goes).
> >
> > PL
> > commit 6e8ab7e06228fb3d67510cda130e9262a81f148a
> > Author: Puyan Lotfi <plotfi at apple.com>
> > Date:   Mon Oct 23 14:41:00 2017 -0700
> >
> >     mir-canon: 1st patch (simplified).
>
> I'm assuming you'll put some detail about what what this is for in the
> message when you're ready to commit.
>
> > diff --git a/include/llvm/InitializePasses.h b/include/llvm/
> InitializePasses.h
> > index bf54b6471f4..12d2e9adc34 100644
> > --- a/include/llvm/InitializePasses.h
> > +++ b/include/llvm/InitializePasses.h
> > @@ -377,6 +377,7 @@ void initializeWinEHPreparePass(PassRegistry&);
> >  void initializeWriteBitcodePassPass(PassRegistry&);
> >  void initializeWriteThinLTOBitcodePass(PassRegistry&);
> >  void initializeXRayInstrumentationPass(PassRegistry&);
> > +void initializeMIRCanonicalizerPass(PassRegistry &);
> >
> >  } // end namespace llvm
> >
> > diff --git a/lib/CodeGen/CMakeLists.txt b/lib/CodeGen/CMakeLists.txt
> > index 7ec7fda4e44..2e364cd4794 100644
> > --- a/lib/CodeGen/CMakeLists.txt
> > +++ b/lib/CodeGen/CMakeLists.txt
> > @@ -113,6 +113,7 @@ add_llvm_library(LLVMCodeGen
> >    RegisterPressure.cpp
> >    RegisterScavenging.cpp
> >    RenameIndependentSubregs.cpp
> > +  MIRCanonicalizerPass.cpp
> >    RegisterUsageInfo.cpp
> >    RegUsageInfoCollector.cpp
> >    RegUsageInfoPropagate.cpp
> > diff --git a/lib/CodeGen/CodeGen.cpp b/lib/CodeGen/CodeGen.cpp
> > index f4ccb4889d3..bfab865687e 100644
> > --- a/lib/CodeGen/CodeGen.cpp
> > +++ b/lib/CodeGen/CodeGen.cpp
> > @@ -99,6 +99,7 @@ void llvm::initializeCodeGen(PassRegistry &Registry) {
> >    initializeVirtRegRewriterPass(Registry);
> >    initializeWinEHPreparePass(Registry);
> >    initializeXRayInstrumentationPass(Registry);
> > +  initializeMIRCanonicalizerPass(Registry);
> >  }
> >
> >  void LLVMInitializeCodeGen(LLVMPassRegistryRef R) {
> > diff --git a/lib/CodeGen/MIRCanonicalizerPass.cpp b/lib/CodeGen/
> MIRCanonicalizerPass.cpp
> > new file mode 100644
> > index 00000000000..728995d0d11
> > --- /dev/null
> > +++ b/lib/CodeGen/MIRCanonicalizerPass.cpp
> > @@ -0,0 +1,611 @@
> > +//===-------------- MIRCanonicalizer.cpp - MIR Canonicalizer
> --------------===//
> > +//
> > +//                     The LLVM Compiler Infrastructure
> > +//
> > +// This file is distributed under the University of Illinois Open Source
> > +// License. See LICENSE.TXT for details.
> > +//
> > +//===------------------------------------------------------
> ----------------===//
> > +//
> > +// Reorders instructions canonically.
> > +// Renames virtual register operands canonically.
> > +// Strips certain MIR artifacts (optionally).
>
> It would be better to write a couple of sentences here about what the
> pass is for, rather than these details about how it does it.
>
> > +//
> > +//===------------------------------------------------------
> ----------------===//
> > +
> > +#include "llvm/CodeGen/Passes.h"
> > +#include "llvm/CodeGen/MachineInstrBuilder.h"
> > +#include "llvm/CodeGen/MachineFunctionPass.h"
> > +#include "llvm/CodeGen/MachineRegisterInfo.h"
> > +
> > +#include "llvm/Support/raw_ostream.h"
> > +#include "llvm/ADT/PostOrderIterator.h"
> > +#include "llvm/Target/TargetInstrInfo.h"
> > +
> > +#include <tuple>
> > +#include <queue>
>
> Please sort each section of includes by name. clang-format can do that
> for you.
>
> > +
> > +using namespace llvm;
> > +
> > +#include <cassert>
>
> This is probably included transitively by the other llvm headers anyway,
> in which case you can just remove it. If not, please put it up with the
> other stdlib headers.
>
> > +namespace llvm {
> > +/// The purpose of this pass is to establish a canonical operand naming
> so
> > +/// that code compiled with slightly different IR passes can be diffed
> more
> > +/// effectively than otherwise. This is done by renaming vregs in a
> given
> > +/// LiveRange in a canonical way.
>
> This is more or less the comment I was looking for up above in the
> header. Just moving this there would make sense :)
>
> > +extern char &MIRCanonicalizerID;
> > +} // namespace llvm
> > +
> > +#define DEBUG_TYPE "mir-canonicalizer"
> > +
> > +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."));
> > +
> > +namespace {
> > +
> > +class MIRCanonicalizer : public MachineFunctionPass {
> > +public:
> > +  static char ID;
> > +  MIRCanonicalizer() : MachineFunctionPass(ID) {}
> > +
> > +  StringRef getPassName() const override {
> > +    return "Rename register operands in a canonical ordering.";
> > +  }
> > +
> > +  void getAnalysisUsage(AnalysisUsage &AU) const override {
> > +    AU.setPreservesCFG();
> > +    MachineFunctionPass::getAnalysisUsage(AU);
> > +  }
> > +
> > +  bool runOnMachineFunction(MachineFunction &MF) override;
> > +};
> > +
> > +} // end anonymous namespace
> > +
> > +enum RSType { RSE_Reg = 0, RSE_FrameIndex, RSE_NewCandidate };
> > +typedef std::tuple<RSType, unsigned> typedRegStackEntry;
>
> I'd probably do a simple struct instead of a tuple here - names are
> nicer than std::get and with brace initialization you don't even need to
> write a constructor, so you aren't really saving anything with the tuple.
>
> > +
> > +char MIRCanonicalizer::ID;
> > +
> > +char &llvm::MIRCanonicalizerID = MIRCanonicalizer::ID;
> > +
> > +INITIALIZE_PASS_BEGIN(MIRCanonicalizer, "mir-canonicalizer",
> > +                      "Rename Register Operands Canonically", false,
> false);
> > +
> > +INITIALIZE_PASS_END(MIRCanonicalizer, "mir-canonicalizer",
> > +                    "Rename Register Operands Canonically", false,
> false);
> > +
> > +static std::vector<MachineBasicBlock *> GetRPOList(MachineFunction &MF)
> {
> > +  MachineBasicBlock *Entry = &*MF.begin();
> > +  std::vector<MachineBasicBlock*> RPOList;
> > +  ReversePostOrderTraversal<MachineBasicBlock*> RPOT(Entry);
> > +  for (ReversePostOrderTraversal<MachineBasicBlock*>::rpo_iterator
> > +       MBBI = RPOT.begin(), MBBE = RPOT.end(); MBBI != MBBE; ++MBBI)> {
>
> Why not use a range-for here?
>
> > +    MachineBasicBlock *MBB = *MBBI;
> > +    RPOList.push_back(MBB);
> > +  }
> > +
> > +  return RPOList;
> > +}
> > +
> > +// Set a dummy vreg. We use this vregs register class to generate
> throw-away
> > +// vregs that are used to skip vreg numbers so that vreg numbers line
> up.
> > +static unsigned GetDummyVReg(const MachineFunction &MF) {
> > +  for (auto &MBB : MF) {
> > +    for (auto II = MBB.begin(), IE = MBB.end(); II != IE; ++II) {
>
> Same here.
>
> > +      const MachineInstr *MI = &*II;
> > +      for (unsigned i = 0; i < MI->getNumOperands(); i++) {
> > +        const MachineOperand &MO = MI->getOperand(i);
>
> And again here, by using MI->operands()
>
> > +        if (!MO.isReg() || !TargetRegisterInfo::
> isVirtualRegister(MO.getReg()))
> > +          continue;
> > +        return MO.getReg();
> > +      }
> > +    }
> > +  }
> > +
> > +  return ~0U;
> > +}
> > +
> > +static bool rescheduleCanoncally(MachineBasicBlock *MBB) {
> > +
> > +  bool Changed = false;
> > +
> > +  // Calculates the distance of MI from the begining of its parent BB.
> > +  auto getInstrIdx = [](const MachineInstr &MI) {
> > +    unsigned i = 0;
> > +    for (auto &I : *MI.getParent()) {
> > +      if (&I == &MI)
> > +        return i;
> > +      i++;
> > +    }
>
> Please don't use i and I here, it's confusing to have two variables that
> only differ by case. I'd probably call the instruction Cur or CurMI or
> something and use a capital I for the index.
>
> > +    return ~0U;
> > +  };
> > +
> > +  // Pre-Populate vector of instructions to reschedule so that we don't
> > +  // clobber the iterator.
> > +  std::vector<MachineInstr *> instructions;
> > +  for (auto II = MBB->begin(); II != MBB->end(); ++II) {
>
> More range-for
>
> > +    instructions.push_back(&*II);
> > +  }
> > +
> > +  for (auto II : instructions) {
>
> Saying "auto *II" makes it a bit more obvious at a glance that there's
> nothing interesting being copied here.
>
> > +    if (II->getNumOperands() == 0)
> > +      continue;
> > +
> > +    MachineOperand &MO = II->getOperand(0);
> > +    if (!MO.isReg() || !TargetRegisterInfo::
> isVirtualRegister(MO.getReg()))
> > +      continue;
> > +
> > +    DEBUG(dbgs() << "Operand " << 0 << " of "; II->dump(); MO.dump(););
> > +
> > +    MachineInstr *def = II;
> > +    unsigned distance = ~0U;
> > +    MachineInstr *useToBringDefCloserTo = nullptr;
> > +    MachineRegisterInfo *MRI = &MBB->getParent()->getRegInfo();
> > +    for (auto UI = MRI->use_begin(MO.getReg()), UE = MRI->use_end();
> > +         UI != UE; ++UI) {
>
> There's probably some API on MRI to do a range for here too (MRI->uses()
> maybe?).
>
> > +      MachineInstr *useInst = UI->getParent();
> > +
> > +      const unsigned defLoc = getInstrIdx(*def);
> > +      const unsigned useLoc = getInstrIdx(*useInst);
> > +      const unsigned delta = (useLoc - defLoc);
>
> These variables should start with capital letters for consistency. There
> are some more variables that start with lower case letter elsewhere in
> the patch to clean up too.
>
> > +
> > +      if (useInst->getParent() != def->getParent())
> > +        continue;
> > +      if (defLoc >= useLoc)
> > +        continue;
> > +
> > +      if (delta < distance) {
> > +        distance = delta;
> > +        useToBringDefCloserTo = useInst;
> > +      }
> > +    }
> > +
> > +    MachineBasicBlock::iterator defI = MBB->instr_end();
> > +    MachineBasicBlock::iterator useI = MBB->instr_end();
> > +
> > +    for (auto BBI = MBB->instr_begin(); BBI != MBB->instr_end(); ++BBI)
> {
>
> Maybe do "BBE = MBB->instr_end()" in the init here and use it in the
> places where you call instr_end() again below?
>
> > +
> > +      if (defI != MBB->instr_end() && useI != MBB->instr_end())
> > +        break;
> > +
> > +      if ((&*BBI != def) && (&*BBI != useToBringDefCloserTo))
> > +        continue;
> > +
> > +      if (&*BBI == def) {
> > +        defI = BBI;
> > +        continue;
> > +      }
> > +
> > +      if (&*BBI == useToBringDefCloserTo) {
> > +        useI = BBI;
> > +        continue;
> > +      }
> > +    }
> > +
> > +    if (defI == MBB->instr_end() || useI == MBB->instr_end())
> > +      continue;
> > +
> > +    DEBUG({
> > +      dbgs() << "Splicing ";
> > +      defI->dump();
> > +      dbgs() << " right before: ";
> > +      useI->dump();
> > +    });
> > +
> > +    Changed = true;
> > +    MBB->splice(useI, MBB, defI);
> > +  }
> > +
> > +  return Changed;
> > +}
> > +
> > +static std::vector<MachineInstr *> populateCandidates(MachineBasicBlock
> *MBB) {
> > +  std::vector<MachineInstr *> candidates;
> > +  MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo();
> > +
> > +  for (auto II = MBB->begin(), IE = MBB->end(); II != IE; ++II) {
> > +    MachineInstr *MI = &*II;
> > +
> > +    bool doesMISideEffect = false;
> > +
> > +    if (MI->getNumOperands() > 0 && MI->getOperand(0).isReg()) {
> > +      const unsigned dst = MI->getOperand(0).getReg();
> > +      doesMISideEffect |= !TargetRegisterInfo::isVirtualRegister(dst);
> > +
> > +      for (auto UI = MRI.use_begin(dst); UI != MRI.use_end(); ++UI) {
> > +        if (doesMISideEffect) break;
> > +        doesMISideEffect |= (UI->getParent()->getParent() !=
> MI->getParent());
> > +      }
>
> A comment explaining what makes n interesting candidate would be helpful
> when reading this part.
>
> > +    }
> > +
> > +    if (!MI->mayStore() && !MI->isBranch() && !doesMISideEffect)
> > +      continue;
> > +
> > +    DEBUG(dbgs() << "Found Candidate:  "; MI->dump(););
> > +    candidates.push_back(MI);
> > +  }
> > +
> > +  return candidates;
> > +}
> > +
> > +void doCandidateWalk(std::vector<typedRegStackEntry> &VRegs,
> > +                     std::queue <typedRegStackEntry> &reg_queue,
> > +                     std::vector<MachineInstr *> &visitedMIs,
> > +                     const MachineBasicBlock *MBB) {
> > +
> > +  const MachineFunction &MF = *MBB->getParent();
> > +  const MachineRegisterInfo &MRI = MF.getRegInfo();
> > +
> > +  while (reg_queue.size()) {
> > +    auto regType = std::get<0>(reg_queue.front());
> > +    auto reg = std::get<1>(reg_queue.front());
> > +    reg_queue.pop();
> > +
> > +    if (regType == RSE_FrameIndex) {
> > +      DEBUG(dbgs() << "Popping frame index.\n";);
> > +      VRegs.push_back(std::make_tuple(RSE_FrameIndex, ~0U));
> > +      continue;
> > +    }
> > +
> > +    assert(regType == RSE_Reg && "Expected vreg or physreg.");
> > +
> > +    if (TargetRegisterInfo::isVirtualRegister(reg)) {
> > +      DEBUG({
> > +        dbgs() << "Popping vreg ";
> > +        MRI.def_begin(reg)->dump();
> > +        dbgs() << "\n";
> > +      });
> > +
> > +      bool hasVisitedVReg = false;
> > +      for (auto vreg : VRegs) {
> > +        if (std::get<1>(vreg) == reg) {
> > +          hasVisitedVReg = true;
> > +          break;
> > +        }
> > +      }
>
> find/find_if is probably shorter.
>
> > +
> > +      if (!hasVisitedVReg)
> > +        VRegs.push_back(std::make_tuple(RSE_Reg, reg));
> > +    } else {
> > +      DEBUG(dbgs() << "Popping physreg.\n";);
> > +      VRegs.push_back(std::make_tuple(RSE_Reg, reg));
> > +      continue;
> > +    }
> > +
> > +    for (auto RI = MRI.def_begin(reg), RE = MRI.def_end(); RI != RE;
> ++RI) {
> > +      MachineInstr *def = RI->getParent();
> > +
> > +      if (def->getParent() != MBB)
> > +        continue;
> > +
> > +      bool hasVisited = false;
> > +      for (auto VMI : visitedMIs) {
> > +        if (def == VMI) {
> > +          hasVisited = true;
> > +          break;
> > +        }
> > +      }
>
> Same here.
>
> > +
> > +      if (hasVisited)
> > +        break;
> > +
> > +      DEBUG({
> > +        dbgs() << "\n========================\n";
> > +        dbgs() << "Visited MI: ";
> > +        def->dump();
> > +        dbgs() << "BB Name: " << def->getParent()->getName() << "\n";
> > +        dbgs() << "\n========================\n";
> > +      });
> > +      visitedMIs.push_back(def);
> > +      for (unsigned I = 1, E = def->getNumOperands(); I != E; ++I) {
> > +
> > +        MachineOperand &MO = def->getOperand(I);
> > +        if (MO.isFI()) {
> > +          DEBUG(dbgs() << "Pushing frame index.\n";);
> > +          reg_queue.push(std::make_tuple(RSE_FrameIndex, ~0U));
> > +        }
> > +
> > +        if (!MO.isReg())
> > +          continue;
> > +        reg_queue.push(std::make_tuple(RSE_Reg, MO.getReg()));
> > +      }
> > +    }
> > +  }
> > +}
> > +
> > +static void SkipVRegs(unsigned &VRegGapIndex, MachineRegisterInfo &MRI,
> > +                      const TargetRegisterClass *RC) {
> > +  const unsigned VR_GAP = (++VRegGapIndex * 1000);
> > +
> > +  DEBUG({
> > +    dbgs() << "Adjusting per-BB VR_GAP for BB" << VRegGapIndex << " to "
> > +           << VR_GAP << "\n";
> > +  });
> > +
> > +  unsigned I = MRI.createVirtualRegister(RC);
> > +  const unsigned E = (((I + VR_GAP) / VR_GAP) + 1) * VR_GAP;
> > +  while (I != E) {
> > +    I = MRI.createVirtualRegister(RC);
> > +  }
> > +}
> > +
> > +static void GetVRegRenameMap(std::map<unsigned, unsigned>
> &vregRenameMap,
> > +                             const std::vector<typedRegStackEntry>
> &VRegs,
> > +                             const std::vector<unsigned>
> &renamedInOtherBB,
> > +                             MachineRegisterInfo &MRI,
> > +                             const TargetRegisterClass *RC) {
> > +
> > +  unsigned lastRenameReg = MRI.createVirtualRegister(RC);
> > +
> > +  bool firstCandidate = true;
> > +  for (auto vreg : VRegs) {
>
> You probably don't want copies here.
>
> > +
> > +    auto regType = std::get<0>(vreg);
> > +    auto reg = std::get<1>(vreg);
> > +
> > +    if (regType == RSE_FrameIndex) {
> > +      lastRenameReg = MRI.createVirtualRegister(RC);
> > +      DEBUG(dbgs() << "Skipping rename for FI " << lastRenameReg <<
> "\n";);
> > +      continue;
> > +    } else if (regType == RSE_NewCandidate) {
> > +      if (!firstCandidate) {
> > +        while (lastRenameReg % 10) {
> > +          lastRenameReg = MRI.createVirtualRegister(RC);
>
> A comment like "round register number to the nearest ten to minimize
> register id differences" or something would be good here.
>
> > +
> > +          DEBUG({
> > +            dbgs() << "Skipping rename for new candidate " <<
> lastRenameReg
> > +                   << "\n";
> > +          });
> > +        }
> > +      }
> > +      firstCandidate = false;
> > +      continue;
> > +    } else if (!TargetRegisterInfo::isVirtualRegister(reg)) {
> > +      lastRenameReg = MRI.createVirtualRegister(RC);
> > +      DEBUG({
> > +        dbgs() << "Skipping rename for Phys Reg " << lastRenameReg <<
> "\n";
> > +      });
> > +      continue;
> > +    }
> > +
> > +    if (std::find(renamedInOtherBB.begin(), renamedInOtherBB.end(),
> reg) !=
> > +        renamedInOtherBB.end()) {
>
> There's an llvm::find in ADT/STLExtras.h that works on ranges to make this
> a
> little shorter.
>
> > +      DEBUG(dbgs() << "Vreg " << reg << " already renamed in other
> BB.\n";);
> > +      continue;
> > +    }
> > +
> > +    auto rename = MRI.createVirtualRegister(MRI.getRegClass(reg));
> > +    lastRenameReg = rename;
> > +
> > +    if (vregRenameMap.find(reg) == vregRenameMap.end()) {
> > +      DEBUG(dbgs() << "Mapping vreg ";);
> > +      if (MRI.reg_begin(reg) != MRI.reg_end()) {
> > +        DEBUG(auto foo = &*MRI.reg_begin(reg); foo->dump(););
> > +      } else {
> > +        DEBUG(dbgs() << reg;);
> > +      }
> > +      DEBUG(dbgs() << " to ";);
> > +      if (MRI.reg_begin(rename) != MRI.reg_end()) {
> > +        DEBUG(auto foo = &*MRI.reg_begin(rename); foo->dump(););
> > +      } else {
> > +        DEBUG(dbgs() << rename;);
> > +      }
> > +      DEBUG(dbgs() << "\n";);
> > +
> > +      vregRenameMap.insert(std::pair<unsigned, unsigned>(reg, rename));
> > +    }
> > +  }
> > +}
> > +
> > +static bool doVRegRenaming(std::vector<unsigned> &renamedInOtherBB,
> > +                           const std::map<unsigned, unsigned>
> &vregRenameMap,
> > +                           MachineRegisterInfo &MRI) {
> > +  bool Changed = false;
> > +  for (auto I = vregRenameMap.begin(), E = vregRenameMap.end(); I != E;
> ++I) {
> > +
> > +    auto vreg = I->first;
> > +    auto rename = I->second;
> > +
> > +    renamedInOtherBB.push_back(rename);
> > +
> > +    std::vector<MachineOperand *> renameMOs;
> > +    for (MachineOperand &MO : MRI.reg_operands(vreg)) {
> > +      renameMOs.push_back(&MO);
> > +    }
> > +
> > +    for (auto MO : renameMOs) {
>
> Another good place for "auto *"
>
> > +      Changed = true;
> > +      MO->setReg(rename);
> > +
> > +      if (!MO->isDef())
> > +        MO->setIsKill(false);
> > +    }
> > +  }
> > +
> > +  return Changed;
> > +}
> > +
> > +static bool doDefKillClear(MachineBasicBlock *MBB) {
> > +  bool Changed = false;
> > +
> > +  for (auto II = MBB->begin(), IE = MBB->end(); II != IE; ++II) {
> > +    MachineInstr *MI = &*II;
> > +
> > +    for (unsigned i = 0; i < MI->getNumOperands(); i++) {
> > +      MachineOperand &MO = MI->getOperand(i);
> > +      if (!MO.isReg())
> > +        continue;
> > +      if (!MO.isDef() && MO.isKill()) {
> > +        Changed = true;
> > +        MO.setIsKill(false);
> > +      }
> > +
> > +      if (MO.isDef() && MO.isDead()) {
> > +        Changed = true;
> > +        MO.setIsDead(false);
> > +      }
> > +    }
> > +  }
> > +
> > +  return Changed;
> > +}
> > +
> > +static bool runOnBasicBlock(MachineBasicBlock *MBB,
> > +                            std::vector<StringRef> &bbNames,
> > +                            std::vector<unsigned> &renamedInOtherBB,
> > +                            unsigned &basicBlockNum, unsigned
> &VRegGapIndex) {
> > +
> > +  if (CanonicalizeBasicBlockNumber != ~0U) {
> > +    if (CanonicalizeBasicBlockNumber != basicBlockNum++)
> > +      return false;
> > +    DEBUG(dbgs() << "\n Canonicalizing BasicBlock " << MBB->getName()
> << "\n";);
> > +  }
> > +
> > +  if (std::find(bbNames.begin(), bbNames.end(), MBB->getName()) !=
> > +      bbNames.end()) {
> > +    DEBUG({
> > +      dbgs() << "Found potentially duplicate BasicBlocks: " <<
> MBB->getName()
> > +             << "\n";
> > +    });
> > +    return false;
> > +  }
> > +
> > +  DEBUG({
> > +    dbgs() << "\n\n  NEW BASIC BLOCK: " << MBB->getName() << "  \n\n";
> > +    dbgs() << "\n\n=========================
> =======================\n\n";
> > +  });
> > +
> > +  bool Changed = false;
> > +  MachineFunction &MF = *MBB->getParent();
> > +  MachineRegisterInfo &MRI = MF.getRegInfo();
> > +
> > +  const TargetRegisterClass *dummyRC = [] (const MachineFunction &MF) {
> > +    const unsigned dummyVReg = GetDummyVReg(MF);
> > +    assert(dummyVReg != ~0U && "Could not find a dummy VReg.");
> > +    const MachineRegisterInfo &MRI = MF.getRegInfo();
> > +    return MRI.getRegClass(dummyVReg);
> > +  } (MF);
> > +
> > +  bbNames.push_back(MBB->getName());
> > +  DEBUG(dbgs() << "\n\n NEW BASIC BLOCK: " << MBB->getName() <<
> "\n\n";);
> > +
> > +  DEBUG(dbgs() << "MBB Before Scheduling:\n"; MBB->dump(););
> > +  Changed |= rescheduleCanoncally(MBB);
> > +  DEBUG(dbgs() << "MBB After Scheduling:\n"; MBB->dump(););
> > +
> > +  std::vector<MachineInstr *> candidates = populateCandidates(MBB);
> > +  std::vector<MachineInstr *> visitedMIs;
> > +  std::copy(candidates.begin(), candidates.end(),
> > +            std::back_inserter(visitedMIs));
> > +
> > +  std::vector<typedRegStackEntry> VRegs;
> > +  for (auto candidate : candidates) {
> > +    VRegs.push_back(std::make_tuple(RSE_NewCandidate, ~0U));
> > +
> > +    std::queue<typedRegStackEntry> reg_queue;
> > +
> > +    // Here we walk the vreg operands of a non-root node along our walk.
> > +    // The root nodes are the original candidates (stores normally).
> > +    // These are normally not the root nodes (except for the case of
> copies to
> > +    // physical registers).
> > +    for (unsigned i = 1; i < candidate->getNumOperands(); i++) {
> > +      if (candidate->mayStore() || candidate->isBranch())
> > +        break;
> > +
> > +      MachineOperand &MO = candidate->getOperand(i);
> > +      if (!(MO.isReg() && TargetRegisterInfo::
> isVirtualRegister(MO.getReg())))
> > +        continue;
> > +
> > +      DEBUG(dbgs() << "Enqueue register"; MO.dump(); dbgs() << "\n";);
> > +      reg_queue.push(std::make_tuple(RSE_Reg, MO.getReg()));
> > +    }
> > +
> > +    // Here we walk the root candidates. We start from the 0th operand
> because
> > +    // the root is normally a store to a vreg.
> > +    for (unsigned i = 0; i < candidate->getNumOperands(); i++) {
> > +
> > +      if (!candidate->mayStore() && !candidate->isBranch())
> > +        break;
> > +
> > +      MachineOperand &MO = candidate->getOperand(i);
> > +
> > +      // TODO: Do we want to only add vregs here?
> > +      if (!MO.isReg() && !MO.isFI())
> > +        continue;
> > +
> > +      DEBUG(dbgs() << "Enqueue Reg/FI"; MO.dump(); dbgs() << "\n";);
> > +
> > +      reg_queue.push(MO.isReg() ? std::make_tuple(RSE_Reg, MO.getReg())
> :
> > +                                  std::make_tuple(RSE_FrameIndex,
> ~0U));
> > +    }
> > +
> > +    // Now that we have pushed the operands of the candidate here, we
> do the
> > +    // full breadth first walk.
> > +    doCandidateWalk(VRegs, reg_queue, visitedMIs, MBB);
> > +  }
> > +
> > +  // If we have populated no vregs to rename then bail.
> > +  // The rest of this function does the vreg remaping.
> > +  if (VRegs.size() == 0)
> > +    return Changed;
> > +
> > +  // Skip some vregs, so we can recon where we'll land next.
> > +  SkipVRegs(VRegGapIndex, MRI, dummyRC);
> > +
> > +  std::map<unsigned, unsigned> vregRenameMap;
> > +  GetVRegRenameMap(vregRenameMap, VRegs, renamedInOtherBB, MRI,
> dummyRC);
> > +
> > +  Changed |= doVRegRenaming(renamedInOtherBB, vregRenameMap, MRI);
> > +  Changed |= doDefKillClear(MBB);
> > +
> > +  DEBUG(dbgs() << "Updated MachineBasicBlock:\n"; MBB->dump(); dbgs()
> << "\n";);
> > +  DEBUG(dbgs() << "\n\n=========================
> =======================\n\n");
> > +  return Changed;
> > +}
> > +
> > +bool MIRCanonicalizer::runOnMachineFunction(MachineFunction &MF) {
> > +
> > +  static unsigned functionNum = 0;
> > +  if (CanonicalizeFunctionNumber != ~0U) {
> > +    if (CanonicalizeFunctionNumber != functionNum++)
> > +      return false;
> > +    DEBUG(dbgs() << "\n Canonicalizing Function " << MF.getName() <<
> "\n";);
> > +  }
> > +
> > +  // we need a valid vreg to create a vreg type for skipping all those
> > +  // stray vreg numbers so reach alignment/canonical vreg values.
> > +  std::vector<MachineBasicBlock*> RPOList = GetRPOList(MF);
> > +
> > +  DEBUG(
> > +    dbgs() << "\n\n  NEW MACHINE FUNCTION: " << MF.getName() << "
> \n\n";
> > +    dbgs() << "\n\n=========================
> =======================\n\n";
> > +    dbgs() << "Total Basic Blocks: " << RPOList.size() << "\n";
> > +    for (auto MBB : RPOList) {
> > +      dbgs() << MBB->getName() << "\n";
> > +    }
> > +    dbgs() << "\n\n=========================
> =======================\n\n";
> > +  );
> > +
> > +  std::vector<StringRef> bbNames;
> > +  std::vector<unsigned> renamedInOtherBB;
> > +
> > +  unsigned gapIdx = 0;
> > +  unsigned bbNum = 0;
> > +
> > +  bool Changed = false;
> > +
> > +  for (auto MBB : RPOList)
> > +    Changed |= runOnBasicBlock(MBB, bbNames, renamedInOtherBB, bbNum,
> gapIdx);
> > +
> > +  return Changed;
> > +}
> > +
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20171027/facf3708/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: mir-canon-simplified2.patch
Type: application/octet-stream
Size: 22975 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20171027/facf3708/attachment.obj>


More information about the llvm-commits mailing list