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;
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())
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)
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,...
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
iterator_range< use_nodbg_iterator > use_nodbg_operands(Register Reg) const
const TargetRegisterClass * getRegClassOrNull(Register Reg) const
Return the register class of Reg, or null if Reg has not been assigned a register class yet.
iterator_range< use_iterator > use_operands(Register Reg) const
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::...