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<MCRegister> 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())
190 II->getOperand(i).getReg().asMCReg())) {
195 IsPseudoIdempotent =
false;
199 if (IsPseudoIdempotent) {
200 PseudoIdempotentInstructions.push_back(
II);
207 unsigned Distance = ~0U;
210 for (
auto &UO :
MRI->use_nodbg_operands(MO.
getReg())) {
213 const unsigned DefLoc = getInstrIdx(*Def);
214 const unsigned UseLoc = getInstrIdx(*UseInst);
215 const unsigned Delta = (UseLoc - DefLoc);
217 if (UseInst->
getParent() != Def->getParent())
219 if (DefLoc >= UseLoc)
222 if (Delta < Distance) {
224 UseToBringDefCloserTo = UseInst;
225 MultiUserLookup[UseToBringDefCloserToCount++] = UseToBringDefCloserTo;
235 if (DefI != BBE && UseI != BBE)
243 if (&*BBI == UseToBringDefCloserTo) {
249 if (DefI == BBE || UseI == BBE)
253 dbgs() <<
"Splicing ";
255 dbgs() <<
" right before: ";
259 MultiUsers[UseToBringDefCloserTo].push_back(Def);
265 for (
const auto &E : MultiUserLookup) {
268 return &MI == E.second;
275 dbgs() <<
"Rescheduling Multi-Use Instructions Lexographically.");
277 MultiUsers[E.second],
MBB,
281 PseudoIdempotentInstCount = PseudoIdempotentInstructions.size();
282 LLVM_DEBUG(
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
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.
Remove Loads Into Fake Uses
Represent the analysis usage information of a pass.
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
instr_iterator instr_begin()
LLVM_ABI void dump() const
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 '...
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.
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.
LLVM_ABI void dump() const
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.
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::...