1 //===-------------- MIRCanonicalizer.cpp - MIR Canonicalizer --------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // The purpose of this pass is to employ a canonical code transformation so
10 // that code compiled with slightly different IR passes can be diffed more
11 // effectively than otherwise. This is done by renaming vregs in a given
12 // LiveRange in a canonical way. This pass also does a pseudo-scheduling to
13 // move defs closer to their use inorder to reduce diffs caused by slightly
14 // different schedules.
18 // llc -o - -run-pass mir-canonicalizer example.mir
20 // Reorders instructions canonically.
21 // Renames virtual register operands canonically.
22 // Strips certain MIR artifacts (optionally).
24 //===----------------------------------------------------------------------===//
26 #include "MIRVRegNamerUtils.h"
27 #include "llvm/ADT/PostOrderIterator.h"
28 #include "llvm/ADT/STLExtras.h"
29 #include "llvm/CodeGen/MachineFunctionPass.h"
30 #include "llvm/CodeGen/MachineRegisterInfo.h"
31 #include "llvm/InitializePasses.h"
32 #include "llvm/Pass.h"
33 #include "llvm/Support/Debug.h"
34 #include "llvm/Support/raw_ostream.h"
38 #define DEBUG_TYPE "mir-canonicalizer"
40 static cl::opt
<unsigned>
41 CanonicalizeFunctionNumber("canon-nth-function", cl::Hidden
, cl::init(~0u),
43 cl::desc("Function number to canonicalize."));
47 class MIRCanonicalizer
: public MachineFunctionPass
{
50 MIRCanonicalizer() : MachineFunctionPass(ID
) {}
52 StringRef
getPassName() const override
{
53 return "Rename register operands in a canonical ordering.";
56 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
58 MachineFunctionPass::getAnalysisUsage(AU
);
61 bool runOnMachineFunction(MachineFunction
&MF
) override
;
64 } // end anonymous namespace
66 char MIRCanonicalizer::ID
;
68 char &llvm::MIRCanonicalizerID
= MIRCanonicalizer::ID
;
70 INITIALIZE_PASS_BEGIN(MIRCanonicalizer
, "mir-canonicalizer",
71 "Rename Register Operands Canonically", false, false)
73 INITIALIZE_PASS_END(MIRCanonicalizer
, "mir-canonicalizer",
74 "Rename Register Operands Canonically", false, false)
76 static std::vector
<MachineBasicBlock
*> GetRPOList(MachineFunction
&MF
) {
79 ReversePostOrderTraversal
<MachineBasicBlock
*> RPOT(&*MF
.begin());
80 std::vector
<MachineBasicBlock
*> RPOList
;
81 append_range(RPOList
, RPOT
);
87 rescheduleLexographically(std::vector
<MachineInstr
*> instructions
,
88 MachineBasicBlock
*MBB
,
89 std::function
<MachineBasicBlock::iterator()> getPos
) {
92 using StringInstrPair
= std::pair
<std::string
, MachineInstr
*>;
93 std::vector
<StringInstrPair
> StringInstrMap
;
95 for (auto *II
: instructions
) {
97 raw_string_ostream
OS(S
);
101 // Trim the assignment, or start from the beginning in the case of a store.
102 const size_t i
= S
.find('=');
103 StringInstrMap
.push_back({(i
== std::string::npos
) ? S
: S
.substr(i
), II
});
106 llvm::sort(StringInstrMap
, llvm::less_first());
108 for (auto &II
: StringInstrMap
) {
111 dbgs() << "Splicing ";
113 dbgs() << " right before: ";
118 MBB
->splice(getPos(), MBB
, II
.second
);
124 static bool rescheduleCanonically(unsigned &PseudoIdempotentInstCount
,
125 MachineBasicBlock
*MBB
) {
127 bool Changed
= false;
129 // Calculates the distance of MI from the beginning of its parent BB.
130 auto getInstrIdx
= [](const MachineInstr
&MI
) {
132 for (const auto &CurMI
: *MI
.getParent()) {
140 // Pre-Populate vector of instructions to reschedule so that we don't
141 // clobber the iterator.
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
++) {
154 MachineOperand
&MO
= II
->getOperand(i
);
158 if (MO
.getReg().isVirtual())
164 PhysRegDefs
.push_back(MO
.getReg());
168 for (auto *II
: Instructions
) {
169 if (II
->getNumOperands() == 0)
171 if (II
->mayLoadOrStore())
174 MachineOperand
&MO
= II
->getOperand(0);
175 if (!MO
.isReg() || !MO
.getReg().isVirtual())
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())
189 if (!llvm::is_contained(PhysRegDefs
, II
->getOperand(i
).getReg())) {
194 IsPseudoIdempotent
= false;
198 if (IsPseudoIdempotent
) {
199 PseudoIdempotentInstructions
.push_back(II
);
203 LLVM_DEBUG(dbgs() << "Operand " << 0 << " of "; II
->dump(); MO
.dump(););
205 MachineInstr
*Def
= II
;
206 unsigned Distance
= ~0U;
207 MachineInstr
*UseToBringDefCloserTo
= nullptr;
208 MachineRegisterInfo
*MRI
= &MBB
->getParent()->getRegInfo();
209 for (auto &UO
: MRI
->use_nodbg_operands(MO
.getReg())) {
210 MachineInstr
*UseInst
= UO
.getParent();
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();
229 MachineBasicBlock::iterator DefI
= BBE
;
230 MachineBasicBlock::iterator UseI
= BBE
;
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
);
263 // Sort the defs for users of multiple defs lexographically.
264 for (const auto &E
: MultiUserLookup
) {
266 auto UseI
= llvm::find_if(MBB
->instrs(), [&](MachineInstr
&MI
) -> bool {
267 return &MI
== E
.second
;
270 if (UseI
== MBB
->instr_end())
274 dbgs() << "Rescheduling Multi-Use Instructions Lexographically.";);
275 Changed
|= rescheduleLexographically(
276 MultiUsers
[E
.second
], MBB
,
277 [&]() -> MachineBasicBlock::iterator
{ return UseI
; });
280 PseudoIdempotentInstCount
= PseudoIdempotentInstructions
.size();
282 dbgs() << "Rescheduling Idempotent Instructions Lexographically.";);
283 Changed
|= rescheduleLexographically(
284 PseudoIdempotentInstructions
, MBB
,
285 [&]() -> MachineBasicBlock::iterator
{ return MBB
->begin(); });
290 static bool propagateLocalCopies(MachineBasicBlock
*MBB
) {
291 bool Changed
= false;
292 MachineRegisterInfo
&MRI
= MBB
->getParent()->getRegInfo();
294 std::vector
<MachineInstr
*> Copies
;
295 for (MachineInstr
&MI
: MBB
->instrs()) {
297 Copies
.push_back(&MI
);
300 for (MachineInstr
*MI
: 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())
314 // Not folding COPY instructions if regbankselect has not set the RCs.
315 // Why are we only considering Register Classes? Because the verifier
316 // sometimes gets upset if the register classes don't match even if the
317 // types do. A future patch might add COPY folding for matching types in
318 // pre-registerbankselect code.
319 if (!MRI
.getRegClassOrNull(Dst
))
321 if (MRI
.getRegClass(Dst
) != MRI
.getRegClass(Src
))
324 std::vector
<MachineOperand
*> Uses
;
325 for (MachineOperand
&MO
: MRI
.use_operands(Dst
))
327 for (auto *MO
: Uses
)
331 MI
->eraseFromParent();
337 static bool doDefKillClear(MachineBasicBlock
*MBB
) {
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()) {
359 static bool runOnBasicBlock(MachineBasicBlock
*MBB
,
360 unsigned BasicBlockNum
, VRegRenamer
&Renamer
) {
362 dbgs() << "\n\n NEW BASIC BLOCK: " << MBB
->getName() << " \n\n";
363 dbgs() << "\n\n================================================\n\n";
366 bool Changed
= false;
368 LLVM_DEBUG(dbgs() << "\n\n NEW BASIC BLOCK: " << MBB
->getName() << "\n\n";);
370 LLVM_DEBUG(dbgs() << "MBB Before Canonical Copy Propagation:\n";
372 Changed
|= propagateLocalCopies(MBB
);
373 LLVM_DEBUG(dbgs() << "MBB After Canonical Copy Propagation:\n"; MBB
->dump(););
375 LLVM_DEBUG(dbgs() << "MBB Before Scheduling:\n"; MBB
->dump(););
376 unsigned IdempotentInstCount
= 0;
377 Changed
|= rescheduleCanonically(IdempotentInstCount
, MBB
);
378 LLVM_DEBUG(dbgs() << "MBB After Scheduling:\n"; MBB
->dump(););
380 Changed
|= Renamer
.renameVRegs(MBB
, BasicBlockNum
);
382 // TODO: Consider dropping this. Dropping kill defs is probably not
383 // semantically sound.
384 Changed
|= doDefKillClear(MBB
);
386 LLVM_DEBUG(dbgs() << "Updated MachineBasicBlock:\n"; MBB
->dump();
389 dbgs() << "\n\n================================================\n\n");
393 bool MIRCanonicalizer::runOnMachineFunction(MachineFunction
&MF
) {
395 static unsigned functionNum
= 0;
396 if (CanonicalizeFunctionNumber
!= ~0U) {
397 if (CanonicalizeFunctionNumber
!= functionNum
++)
399 LLVM_DEBUG(dbgs() << "\n Canonicalizing Function " << MF
.getName()
403 // we need a valid vreg to create a vreg type for skipping all those
404 // stray vreg numbers so reach alignment/canonical vreg values.
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";
412 : RPOList
) { dbgs() << MBB
->getName() << "\n"; } dbgs()
413 << "\n\n================================================\n\n";);
416 bool Changed
= false;
417 MachineRegisterInfo
&MRI
= MF
.getRegInfo();
418 VRegRenamer
Renamer(MRI
);
419 for (auto *MBB
: RPOList
)
420 Changed
|= runOnBasicBlock(MBB
, BBNum
++, Renamer
);