38#define DEBUG_TYPE "mir-canonicalizer"
43 cl::desc(
"Function number to canonicalize."));
52 StringRef getPassName()
const override {
53 return "Rename register operands in a canonical ordering.";
56 void getAnalysisUsage(AnalysisUsage &AU)
const override {
61 bool runOnMachineFunction(MachineFunction &MF)
override;
66char MIRCanonicalizer::ID;
71 "Rename Register Operands Canonically",
false,
false)
80 std::vector<MachineBasicBlock *> RPOList;
92 using StringInstrPair = std::pair<std::string, MachineInstr *>;
93 std::vector<StringInstrPair> StringInstrMap;
101 const size_t i = S.find(
'=');
102 StringInstrMap.push_back({(i == std::string::npos) ? S : S.substr(i),
II});
107 for (
auto &
II : StringInstrMap) {
110 dbgs() <<
"Splicing ";
112 dbgs() <<
" right before: ";
117 MBB->splice(getPos(),
MBB,
II.second);
131 for (
const auto &CurMI : *
MI.getParent()) {
141 std::vector<MachineInstr *> Instructions;
142 for (
auto &
MI : *
MBB) {
143 Instructions.push_back(&
MI);
146 std::map<MachineInstr *, std::vector<MachineInstr *>> MultiUsers;
147 std::map<unsigned, MachineInstr *> MultiUserLookup;
148 unsigned UseToBringDefCloserToCount = 0;
149 std::vector<MachineInstr *> PseudoIdempotentInstructions;
150 std::vector<MCRegister> PhysRegDefs;
151 for (
auto *
II : Instructions) {
152 for (
unsigned i = 1; i <
II->getNumOperands(); i++) {
163 PhysRegDefs.push_back(MO.
getReg());
167 for (
auto *
II : Instructions) {
168 if (
II->getNumOperands() == 0)
170 if (
II->mayLoadOrStore())
179 bool IsPseudoIdempotent =
true;
180 for (
unsigned i = 1; i <
II->getNumOperands(); i++) {
182 if (
II->getOperand(i).isImm()) {
186 if (
II->getOperand(i).isReg()) {
187 if (!
II->getOperand(i).getReg().isVirtual())
189 II->getOperand(i).getReg().asMCReg())) {
194 IsPseudoIdempotent =
false;
198 if (IsPseudoIdempotent) {
199 PseudoIdempotentInstructions.push_back(
II);
206 unsigned Distance = ~0U;
209 for (
auto &UO :
MRI->use_nodbg_operands(MO.
getReg())) {
212 const unsigned DefLoc = getInstrIdx(*Def);
213 const unsigned UseLoc = getInstrIdx(*UseInst);
214 const unsigned Delta = (UseLoc - DefLoc);
216 if (UseInst->
getParent() != Def->getParent())
218 if (DefLoc >= UseLoc)
221 if (Delta < Distance) {
223 UseToBringDefCloserTo = UseInst;
224 MultiUserLookup[UseToBringDefCloserToCount++] = UseToBringDefCloserTo;
228 const auto BBE =
MBB->instr_end();
232 for (
auto BBI =
MBB->instr_begin(); BBI != BBE; ++BBI) {
234 if (DefI != BBE && UseI != BBE)
242 if (&*BBI == UseToBringDefCloserTo) {
248 if (DefI == BBE || UseI == BBE)
252 dbgs() <<
"Splicing ";
254 dbgs() <<
" right before: ";
258 MultiUsers[UseToBringDefCloserTo].push_back(Def);
260 MBB->splice(UseI,
MBB, DefI);
264 for (
const auto &
E : MultiUserLookup) {
267 return &MI == E.second;
270 if (UseI ==
MBB->instr_end())
274 dbgs() <<
"Rescheduling Multi-Use Instructions Lexographically.");
276 MultiUsers[
E.second],
MBB,
280 PseudoIdempotentInstCount = PseudoIdempotentInstructions.size();
281 LLVM_DEBUG(
dbgs() <<
"Rescheduling Idempotent Instructions Lexographically.");
283 PseudoIdempotentInstructions,
MBB,
293 std::vector<MachineInstr *>
Copies;
301 if (!
MI->getOperand(0).isReg())
303 if (!
MI->getOperand(1).isReg())
306 const Register Dst =
MI->getOperand(0).getReg();
307 const Register Src =
MI->getOperand(1).getReg();
309 if (!Dst.isVirtual())
311 if (!Src.isVirtual())
318 if (!
MRI.getRegClassOrNull(Dst))
320 if (
MRI.getRegClass(Dst) !=
MRI.getRegClass(Src))
323 std::vector<MachineOperand *>
Uses;
326 for (
auto *MO :
Uses)
330 MI->eraseFromParent();
339 for (
auto &
MI : *
MBB) {
340 for (
auto &MO :
MI.operands()) {
343 if (!MO.isDef() && MO.isKill()) {
348 if (MO.isDef() && MO.isDead()) {
361 dbgs() <<
"\n\n NEW BASIC BLOCK: " <<
MBB->getName() <<
" \n\n";
362 dbgs() <<
"\n\n================================================\n\n";
375 unsigned IdempotentInstCount = 0;
379 Changed |= Renamer.renameVRegs(
MBB, BasicBlockNum);
388 dbgs() <<
"\n\n================================================\n\n");
394 static unsigned functionNum = 0;
404 std::vector<MachineBasicBlock *> RPOList =
GetRPOList(MF);
407 dbgs() <<
"\n\n NEW MACHINE FUNCTION: " << MF.
getName() <<
" \n\n";
408 dbgs() <<
"\n\n================================================\n\n";
409 dbgs() <<
"Total Basic Blocks: " << RPOList.size() <<
"\n";
412 <<
"\n\n================================================\n\n";);
417 VRegRenamer Renamer(
MRI);
418 for (
auto *
MBB : RPOList)
unsigned const MachineRegisterInfo * MRI
Expand Atomic instructions
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static bool runOnBasicBlock(MachineBasicBlock *MBB, unsigned BasicBlockNum, VRegRenamer &Renamer)
static bool rescheduleLexographically(std::vector< MachineInstr * > instructions, MachineBasicBlock *MBB, std::function< MachineBasicBlock::iterator()> getPos)
static cl::opt< unsigned > CanonicalizeFunctionNumber("canon-nth-function", cl::Hidden, cl::init(~0u), cl::value_desc("N"), cl::desc("Function number to canonicalize."))
static bool doDefKillClear(MachineBasicBlock *MBB)
static bool propagateLocalCopies(MachineBasicBlock *MBB)
static bool rescheduleCanonically(unsigned &PseudoIdempotentInstCount, MachineBasicBlock *MBB)
mir Rename Register Operands static false std::vector< MachineBasicBlock * > GetRPOList(MachineFunction &MF)
uint64_t IntrinsicInst * II
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.
Remove Loads Into Fake Uses
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
MachineInstrBundleIterator< MachineInstr > iterator
LLVM_ABI StringRef getName() const
Return the name of the corresponding LLVM basic block, or an empty string.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Representation of each machine instruction.
const MachineBasicBlock * getParent() const
MachineOperand class - Representation of each machine instruction operand.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
LLVM_ABI void dump() const
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
Wrapper class representing virtual and physical registers.
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
VRegRenamer - This class is used for renaming vregs in a machine basic block according to semantics o...
A raw_ostream that writes to an std::string.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
LLVM_ABI char & MIRCanonicalizerID
MIRCanonicalizer - This pass canonicalizes MIR by renaming vregs according to the semantics of the in...
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Implement std::hash so that hash_code can be used in STL containers.
Function object to check whether the first component of a container supported by std::get (like std::...