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;
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: ";
118 MBB->splice(getPos(),
MBB,
II.second);
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;
229 const auto BBE =
MBB->instr_end();
233 for (
auto BBI =
MBB->instr_begin(); BBI != BBE; ++BBI) {
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);
261 MBB->splice(UseI,
MBB, DefI);
265 for (
const auto &
E : MultiUserLookup) {
268 return &MI == E.second;
271 if (UseI ==
MBB->instr_end())
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,
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();
340 for (
auto &
MI : *
MBB) {
341 for (
auto &MO :
MI.operands()) {
344 if (!MO.isDef() && MO.isKill()) {
349 if (MO.isDef() && MO.isDead()) {
362 dbgs() <<
"\n\n NEW BASIC BLOCK: " <<
MBB->getName() <<
" \n\n";
363 dbgs() <<
"\n\n================================================\n\n";
376 unsigned IdempotentInstCount = 0;
380 Changed |= Renamer.renameVRegs(
MBB, BasicBlockNum);
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";);
418 VRegRenamer Renamer(
MRI);
419 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::...