LLVM: lib/CodeGen/MIRCanonicalizerPass.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
35
36using namespace llvm;
37
38#define DEBUG_TYPE "mir-canonicalizer"
39
43 cl::desc("Function number to canonicalize."));
44
45namespace {
46
48public:
49 static char ID;
51
52 StringRef getPassName() const override {
53 return "Rename register operands in a canonical ordering.";
54 }
55
56 void getAnalysisUsage(AnalysisUsage &AU) const override {
59 }
60
61 bool runOnMachineFunction(MachineFunction &MF) override;
62};
63
64}
65
66char MIRCanonicalizer::ID;
67
69
71 "Rename Register Operands Canonically", false, false)
72
74 "Rename Register Operands Canonically", false, false)
75
77 if (MF.empty())
78 return {};
80 std::vector<MachineBasicBlock *> RPOList;
82
83 return RPOList;
84}
85
86static bool
90
92 using StringInstrPair = std::pair<std::string, MachineInstr *>;
93 std::vector StringInstrMap;
94
96 std::string S;
98 II->print(OS);
100
101
102 const size_t i = S.find('=');
103 StringInstrMap.push_back({(i == std:🧵:npos) ? S : S.substr(i), II});
104 }
105
107
108 for (auto &II : StringInstrMap) {
109
111 dbgs() << "Splicing ";
112 II.second->dump();
113 dbgs() << " right before: ";
114 getPos()->dump();
115 });
116
118 MBB->splice(getPos(), MBB, II.second);
119 }
120
122}
123
126
128
129
131 unsigned i = 0;
132 for (const auto &CurMI : *MI.getParent()) {
133 if (&CurMI == &MI)
134 return i;
135 i++;
136 }
137 return ~0U;
138 };
139
140
141
142 std::vector<MachineInstr *> Instructions;
144 Instructions.push_back(&MI);
145 }
146
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 PhysRegDefs;
152 for (auto *II : Instructions) {
153 for (unsigned i = 1; i < II->getNumOperands(); i++) {
156 continue;
157
159 continue;
160
162 continue;
163
164 PhysRegDefs.push_back(MO.getReg());
165 }
166 }
167
168 for (auto *II : Instructions) {
169 if (II->getNumOperands() == 0)
170 continue;
171 if (II->mayLoadOrStore())
172 continue;
173
176 continue;
178 continue;
179
180 bool IsPseudoIdempotent = true;
181 for (unsigned i = 1; i < II->getNumOperands(); i++) {
182
183 if (II->getOperand(i).isImm()) {
184 continue;
185 }
186
187 if (II->getOperand(i).isReg()) {
188 if (->getOperand(i).getReg().isVirtual())
190 II->getOperand(i).getReg().asMCReg())) {
191 continue;
192 }
193 }
194
195 IsPseudoIdempotent = false;
196 break;
197 }
198
199 if (IsPseudoIdempotent) {
200 PseudoIdempotentInstructions.push_back(II);
201 continue;
202 }
203
205
207 unsigned Distance = ~0U;
208 MachineInstr *UseToBringDefCloserTo = nullptr;
210 for (auto &UO : MRI->use_nodbg_operands(MO.getReg())) {
212
213 const unsigned DefLoc = getInstrIdx(*Def);
214 const unsigned UseLoc = getInstrIdx(*UseInst);
215 const unsigned Delta = (UseLoc - DefLoc);
216
217 if (UseInst->getParent() != Def->getParent())
218 continue;
219 if (DefLoc >= UseLoc)
220 continue;
221
222 if (Delta < Distance) {
223 Distance = Delta;
224 UseToBringDefCloserTo = UseInst;
225 MultiUserLookup[UseToBringDefCloserToCount++] = UseToBringDefCloserTo;
226 }
227 }
228
229 const auto BBE = MBB->instr_end();
232
233 for (auto BBI = MBB->instr_begin(); BBI != BBE; ++BBI) {
234
235 if (DefI != BBE && UseI != BBE)
236 break;
237
238 if (&*BBI == Def) {
239 DefI = BBI;
240 continue;
241 }
242
243 if (&*BBI == UseToBringDefCloserTo) {
244 UseI = BBI;
245 continue;
246 }
247 }
248
249 if (DefI == BBE || UseI == BBE)
250 continue;
251
253 dbgs() << "Splicing ";
254 DefI->dump();
255 dbgs() << " right before: ";
256 UseI->dump();
257 });
258
259 MultiUsers[UseToBringDefCloserTo].push_back(Def);
261 MBB->splice(UseI, MBB, DefI);
262 }
263
264
265 for (const auto &E : MultiUserLookup) {
266
268 return &MI == E.second;
269 });
270
271 if (UseI == MBB->instr_end())
272 continue;
273
275 dbgs() << "Rescheduling Multi-Use Instructions Lexographically.");
277 MultiUsers[E.second], MBB,
279 }
280
281 PseudoIdempotentInstCount = PseudoIdempotentInstructions.size();
282 LLVM_DEBUG(dbgs() << "Rescheduling Idempotent Instructions Lexographically.");
284 PseudoIdempotentInstructions, MBB,
286
288}
289
293
294 std::vector<MachineInstr *> Copies;
296 if (MI.isCopy())
298 }
299
301
302 if (->getOperand(0).isReg())
303 continue;
304 if (->getOperand(1).isReg())
305 continue;
306
307 const Register Dst = MI->getOperand(0).getReg();
308 const Register Src = MI->getOperand(1).getReg();
309
310 if (!Dst.isVirtual())
311 continue;
312 if (!Src.isVirtual())
313 continue;
314
315
316
317
318
319 if (.getRegClassOrNull(Dst))
320 continue;
321 if (MRI.getRegClass(Dst) != MRI.getRegClass(Src))
322 continue;
323
324 std::vector<MachineOperand *> Uses;
326 Uses.push_back(&MO);
327 for (auto *MO : Uses)
328 MO->setReg(Src);
329
331 MI->eraseFromParent();
332 }
333
335}
336
339
341 for (auto &MO : MI.operands()) {
342 if (!MO.isReg())
343 continue;
344 if (!MO.isDef() && MO.isKill()) {
346 MO.setIsKill(false);
347 }
348
349 if (MO.isDef() && MO.isDead()) {
351 MO.setIsDead(false);
352 }
353 }
354 }
355
357}
358
360 unsigned BasicBlockNum, VRegRenamer &Renamer) {
362 dbgs() << "\n\n NEW BASIC BLOCK: " << MBB->getName() << " \n\n";
363 dbgs() << "\n\n================================================\n\n";
364 });
365
367
368 LLVM_DEBUG(dbgs() << "\n\n NEW BASIC BLOCK: " << MBB->getName() << "\n\n");
369
370 LLVM_DEBUG(dbgs() << "MBB Before Canonical Copy Propagation:\n";
371 MBB->dump(););
373 LLVM_DEBUG(dbgs() << "MBB After Canonical Copy Propagation:\n"; MBB->dump(););
374
376 unsigned IdempotentInstCount = 0;
379
380 Changed |= Renamer.renameVRegs(MBB, BasicBlockNum);
381
382
383
385
386 LLVM_DEBUG(dbgs() << "Updated MachineBasicBlock:\n"; MBB->dump();
387 dbgs() << "\n");
389 dbgs() << "\n\n================================================\n\n");
391}
392
393bool MIRCanonicalizer::runOnMachineFunction(MachineFunction &MF) {
394
395 static unsigned functionNum = 0;
398 return false;
400 << "\n";);
401 }
402
403
404
405 std::vector<MachineBasicBlock *> RPOList = GetRPOList(MF);
406
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";
411 for (auto MBB
413 << "\n\n================================================\n\n";);
414
415 unsigned BBNum = 0;
418 VRegRenamer Renamer(MRI);
419 for (auto *MBB : RPOList)
421
423}
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)
Definition MIRCanonicalizerPass.cpp:359
static bool rescheduleLexographically(std::vector< MachineInstr * > instructions, MachineBasicBlock *MBB, std::function< MachineBasicBlock::iterator()> getPos)
Definition MIRCanonicalizerPass.cpp:87
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)
Definition MIRCanonicalizerPass.cpp:337
static bool propagateLocalCopies(MachineBasicBlock *MBB)
Definition MIRCanonicalizerPass.cpp:290
static bool rescheduleCanonically(unsigned &PseudoIdempotentInstCount, MachineBasicBlock *MBB)
Definition MIRCanonicalizerPass.cpp:124
mir Rename Register Operands static false std::vector< MachineBasicBlock * > GetRPOList(MachineFunction &MF)
Definition MIRCanonicalizerPass.cpp:76
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...
Definition MIRCanonicalizerPass.cpp:68
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::...