38#define DEBUG_TYPE "mir-canonicalizer"
43 cl::desc(
"Function number to canonicalize."));
53 return "Rename register operands in a canonical ordering.";
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;
102 const size_t i = S.find(
'=');
103 StringInstrMap.push_back({(i == std::string::npos) ? S : S.substr(i),
II});
108 for (
auto &
II : StringInstrMap) {
111 dbgs() <<
"Splicing ";
113 dbgs() <<
" right before: ";
127 bool Changed =
false;
132 for (
const auto &CurMI : *
MI.getParent()) {
142 std::vector<MachineInstr *> Instructions;
143 for (
auto &
MI : *
MBB) {
144 Instructions.push_back(&
MI);
147 std::map<MachineInstr *, std::vector<MachineInstr *>> MultiUsers;
148 std::map<unsigned, MachineInstr *> MultiUserLookup;
149 unsigned UseToBringDefCloserToCount = 0;
150 std::vector<MachineInstr *> PseudoIdempotentInstructions;
151 std::vector<unsigned> PhysRegDefs;
152 for (
auto *
II : Instructions) {
153 for (
unsigned i = 1; i <
II->getNumOperands(); i++) {
164 PhysRegDefs.push_back(MO.
getReg());
168 for (
auto *
II : Instructions) {
169 if (
II->getNumOperands() == 0)
171 if (
II->mayLoadOrStore())
180 bool IsPseudoIdempotent =
true;
181 for (
unsigned i = 1; i <
II->getNumOperands(); i++) {
183 if (
II->getOperand(i).isImm()) {
187 if (
II->getOperand(i).isReg()) {
188 if (!
II->getOperand(i).getReg().isVirtual())
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;
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);
264 for (
const auto &E : MultiUserLookup) {
267 return &MI == E.second;
274 dbgs() <<
"Rescheduling Multi-Use Instructions Lexographically.";);
276 MultiUsers[E.second],
MBB,
280 PseudoIdempotentInstCount = PseudoIdempotentInstructions.size();
282 dbgs() <<
"Rescheduling Idempotent Instructions Lexographically.";);
284 PseudoIdempotentInstructions,
MBB,
291 bool Changed =
false;
294 std::vector<MachineInstr *>
Copies;
302 if (!
MI->getOperand(0).isReg())
304 if (!
MI->getOperand(1).isReg())
307 const Register Dst =
MI->getOperand(0).getReg();
308 const Register Src =
MI->getOperand(1).getReg();
310 if (!Dst.isVirtual())
312 if (!Src.isVirtual())
319 if (!
MRI.getRegClassOrNull(Dst))
321 if (
MRI.getRegClass(Dst) !=
MRI.getRegClass(Src))
324 std::vector<MachineOperand *>
Uses;
327 for (
auto *MO :
Uses)
331 MI->eraseFromParent();
338 bool Changed =
false;
340 for (
auto &
MI : *
MBB) {
341 for (
auto &MO :
MI.operands()) {
344 if (!MO.isDef() && MO.isKill()) {
349 if (MO.isDef() && MO.isDead()) {
363 dbgs() <<
"\n\n================================================\n\n";
366 bool Changed =
false;
376 unsigned IdempotentInstCount = 0;
389 dbgs() <<
"\n\n================================================\n\n");
395 static unsigned functionNum = 0;
405 std::vector<MachineBasicBlock *> RPOList =
GetRPOList(MF);
408 dbgs() <<
"\n\n NEW MACHINE FUNCTION: " << MF.
getName() <<
" \n\n";
409 dbgs() <<
"\n\n================================================\n\n";
410 dbgs() <<
"Total Basic Blocks: " << RPOList.size() <<
"\n";
413 <<
"\n\n================================================\n\n";);
416 bool Changed =
false;
419 for (
auto *
MBB : RPOList)
unsigned const MachineRegisterInfo * MRI
Expand Atomic instructions
Rewrite Partial Register Uses
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)
mir Rename Register Operands Canonically
static bool rescheduleCanonically(unsigned &PseudoIdempotentInstCount, MachineBasicBlock *MBB)
mir Rename Register Operands static false std::vector< MachineBasicBlock * > GetRPOList(MachineFunction &MF)
mir Rename Register Operands
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.
Represent the analysis usage information of a pass.
void setPreservesCFG()
This function should be called by the pass, iff they do not:
instr_iterator instr_begin()
instr_iterator instr_end()
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 '...
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.
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
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.
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Wrapper class representing virtual and physical registers.
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
StringRef - Represent a constant reference to a string, i.e.
VRegRenamer - This class is used for renaming vregs in a machine basic block according to semantics o...
bool renameVRegs(MachineBasicBlock *MBB, unsigned BBNum)
Same as the above, but sets a BBNum depending on BB traversal that will be used as prefix for the vre...
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.
char & MIRCanonicalizerID
MIRCanonicalizer - This pass canonicalizes MIR by renaming vregs according to the semantics of the in...
void sort(IteratorTy Start, IteratorTy End)
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::...