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/MachineInstrBuilder.h"
31 #include "llvm/CodeGen/MachineRegisterInfo.h"
32 #include "llvm/CodeGen/Passes.h"
33 #include "llvm/InitializePasses.h"
34 #include "llvm/Support/Debug.h"
35 #include "llvm/Support/raw_ostream.h"
42 extern char &MIRCanonicalizerID
;
45 #define DEBUG_TYPE "mir-canonicalizer"
47 static cl::opt
<unsigned>
48 CanonicalizeFunctionNumber("canon-nth-function", cl::Hidden
, cl::init(~0u),
50 cl::desc("Function number to canonicalize."));
54 class MIRCanonicalizer
: public MachineFunctionPass
{
57 MIRCanonicalizer() : MachineFunctionPass(ID
) {}
59 StringRef
getPassName() const override
{
60 return "Rename register operands in a canonical ordering.";
63 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
65 MachineFunctionPass::getAnalysisUsage(AU
);
68 bool runOnMachineFunction(MachineFunction
&MF
) override
;
71 } // end anonymous namespace
73 char MIRCanonicalizer::ID
;
75 char &llvm::MIRCanonicalizerID
= MIRCanonicalizer::ID
;
77 INITIALIZE_PASS_BEGIN(MIRCanonicalizer
, "mir-canonicalizer",
78 "Rename Register Operands Canonically", false, false)
80 INITIALIZE_PASS_END(MIRCanonicalizer
, "mir-canonicalizer",
81 "Rename Register Operands Canonically", false, false)
83 static std::vector
<MachineBasicBlock
*> GetRPOList(MachineFunction
&MF
) {
86 ReversePostOrderTraversal
<MachineBasicBlock
*> RPOT(&*MF
.begin());
87 std::vector
<MachineBasicBlock
*> RPOList
;
88 append_range(RPOList
, RPOT
);
94 rescheduleLexographically(std::vector
<MachineInstr
*> instructions
,
95 MachineBasicBlock
*MBB
,
96 std::function
<MachineBasicBlock::iterator()> getPos
) {
99 using StringInstrPair
= std::pair
<std::string
, MachineInstr
*>;
100 std::vector
<StringInstrPair
> StringInstrMap
;
102 for (auto *II
: instructions
) {
104 raw_string_ostream
OS(S
);
108 // Trim the assignment, or start from the beginning in the case of a store.
109 const size_t i
= S
.find('=');
110 StringInstrMap
.push_back({(i
== std::string::npos
) ? S
: S
.substr(i
), II
});
113 llvm::sort(StringInstrMap
,
114 [](const StringInstrPair
&a
, const StringInstrPair
&b
) -> bool {
115 return (a
.first
< b
.first
);
118 for (auto &II
: StringInstrMap
) {
121 dbgs() << "Splicing ";
123 dbgs() << " right before: ";
128 MBB
->splice(getPos(), MBB
, II
.second
);
134 static bool rescheduleCanonically(unsigned &PseudoIdempotentInstCount
,
135 MachineBasicBlock
*MBB
) {
137 bool Changed
= false;
139 // Calculates the distance of MI from the beginning of its parent BB.
140 auto getInstrIdx
= [](const MachineInstr
&MI
) {
142 for (auto &CurMI
: *MI
.getParent()) {
150 // Pre-Populate vector of instructions to reschedule so that we don't
151 // clobber the iterator.
152 std::vector
<MachineInstr
*> Instructions
;
153 for (auto &MI
: *MBB
) {
154 Instructions
.push_back(&MI
);
157 std::map
<MachineInstr
*, std::vector
<MachineInstr
*>> MultiUsers
;
158 std::map
<unsigned, MachineInstr
*> MultiUserLookup
;
159 unsigned UseToBringDefCloserToCount
= 0;
160 std::vector
<MachineInstr
*> PseudoIdempotentInstructions
;
161 std::vector
<unsigned> PhysRegDefs
;
162 for (auto *II
: Instructions
) {
163 for (unsigned i
= 1; i
< II
->getNumOperands(); i
++) {
164 MachineOperand
&MO
= II
->getOperand(i
);
168 if (Register::isVirtualRegister(MO
.getReg()))
174 PhysRegDefs
.push_back(MO
.getReg());
178 for (auto *II
: Instructions
) {
179 if (II
->getNumOperands() == 0)
181 if (II
->mayLoadOrStore())
184 MachineOperand
&MO
= II
->getOperand(0);
185 if (!MO
.isReg() || !Register::isVirtualRegister(MO
.getReg()))
190 bool IsPseudoIdempotent
= true;
191 for (unsigned i
= 1; i
< II
->getNumOperands(); i
++) {
193 if (II
->getOperand(i
).isImm()) {
197 if (II
->getOperand(i
).isReg()) {
198 if (!Register::isVirtualRegister(II
->getOperand(i
).getReg()))
199 if (!llvm::is_contained(PhysRegDefs
, II
->getOperand(i
).getReg())) {
204 IsPseudoIdempotent
= false;
208 if (IsPseudoIdempotent
) {
209 PseudoIdempotentInstructions
.push_back(II
);
213 LLVM_DEBUG(dbgs() << "Operand " << 0 << " of "; II
->dump(); MO
.dump(););
215 MachineInstr
*Def
= II
;
216 unsigned Distance
= ~0U;
217 MachineInstr
*UseToBringDefCloserTo
= nullptr;
218 MachineRegisterInfo
*MRI
= &MBB
->getParent()->getRegInfo();
219 for (auto &UO
: MRI
->use_nodbg_operands(MO
.getReg())) {
220 MachineInstr
*UseInst
= UO
.getParent();
222 const unsigned DefLoc
= getInstrIdx(*Def
);
223 const unsigned UseLoc
= getInstrIdx(*UseInst
);
224 const unsigned Delta
= (UseLoc
- DefLoc
);
226 if (UseInst
->getParent() != Def
->getParent())
228 if (DefLoc
>= UseLoc
)
231 if (Delta
< Distance
) {
233 UseToBringDefCloserTo
= UseInst
;
234 MultiUserLookup
[UseToBringDefCloserToCount
++] = UseToBringDefCloserTo
;
238 const auto BBE
= MBB
->instr_end();
239 MachineBasicBlock::iterator DefI
= BBE
;
240 MachineBasicBlock::iterator UseI
= BBE
;
242 for (auto BBI
= MBB
->instr_begin(); BBI
!= BBE
; ++BBI
) {
244 if (DefI
!= BBE
&& UseI
!= BBE
)
252 if (&*BBI
== UseToBringDefCloserTo
) {
258 if (DefI
== BBE
|| UseI
== BBE
)
262 dbgs() << "Splicing ";
264 dbgs() << " right before: ";
268 MultiUsers
[UseToBringDefCloserTo
].push_back(Def
);
270 MBB
->splice(UseI
, MBB
, DefI
);
273 // Sort the defs for users of multiple defs lexographically.
274 for (const auto &E
: MultiUserLookup
) {
276 auto UseI
= llvm::find_if(MBB
->instrs(), [&](MachineInstr
&MI
) -> bool {
277 return &MI
== E
.second
;
280 if (UseI
== MBB
->instr_end())
284 dbgs() << "Rescheduling Multi-Use Instructions Lexographically.";);
285 Changed
|= rescheduleLexographically(
286 MultiUsers
[E
.second
], MBB
,
287 [&]() -> MachineBasicBlock::iterator
{ return UseI
; });
290 PseudoIdempotentInstCount
= PseudoIdempotentInstructions
.size();
292 dbgs() << "Rescheduling Idempotent Instructions Lexographically.";);
293 Changed
|= rescheduleLexographically(
294 PseudoIdempotentInstructions
, MBB
,
295 [&]() -> MachineBasicBlock::iterator
{ return MBB
->begin(); });
300 static bool propagateLocalCopies(MachineBasicBlock
*MBB
) {
301 bool Changed
= false;
302 MachineRegisterInfo
&MRI
= MBB
->getParent()->getRegInfo();
304 std::vector
<MachineInstr
*> Copies
;
305 for (MachineInstr
&MI
: MBB
->instrs()) {
307 Copies
.push_back(&MI
);
310 for (MachineInstr
*MI
: Copies
) {
312 if (!MI
->getOperand(0).isReg())
314 if (!MI
->getOperand(1).isReg())
317 const Register Dst
= MI
->getOperand(0).getReg();
318 const Register Src
= MI
->getOperand(1).getReg();
320 if (!Register::isVirtualRegister(Dst
))
322 if (!Register::isVirtualRegister(Src
))
324 // Not folding COPY instructions if regbankselect has not set the RCs.
325 // Why are we only considering Register Classes? Because the verifier
326 // sometimes gets upset if the register classes don't match even if the
327 // types do. A future patch might add COPY folding for matching types in
328 // pre-registerbankselect code.
329 if (!MRI
.getRegClassOrNull(Dst
))
331 if (MRI
.getRegClass(Dst
) != MRI
.getRegClass(Src
))
334 std::vector
<MachineOperand
*> Uses
;
335 for (auto UI
= MRI
.use_begin(Dst
); UI
!= MRI
.use_end(); ++UI
)
336 Uses
.push_back(&*UI
);
337 for (auto *MO
: Uses
)
341 MI
->eraseFromParent();
347 static bool doDefKillClear(MachineBasicBlock
*MBB
) {
348 bool Changed
= false;
350 for (auto &MI
: *MBB
) {
351 for (auto &MO
: MI
.operands()) {
354 if (!MO
.isDef() && MO
.isKill()) {
359 if (MO
.isDef() && MO
.isDead()) {
369 static bool runOnBasicBlock(MachineBasicBlock
*MBB
,
370 unsigned BasicBlockNum
, VRegRenamer
&Renamer
) {
372 dbgs() << "\n\n NEW BASIC BLOCK: " << MBB
->getName() << " \n\n";
373 dbgs() << "\n\n================================================\n\n";
376 bool Changed
= false;
378 LLVM_DEBUG(dbgs() << "\n\n NEW BASIC BLOCK: " << MBB
->getName() << "\n\n";);
380 LLVM_DEBUG(dbgs() << "MBB Before Canonical Copy Propagation:\n";
382 Changed
|= propagateLocalCopies(MBB
);
383 LLVM_DEBUG(dbgs() << "MBB After Canonical Copy Propagation:\n"; MBB
->dump(););
385 LLVM_DEBUG(dbgs() << "MBB Before Scheduling:\n"; MBB
->dump(););
386 unsigned IdempotentInstCount
= 0;
387 Changed
|= rescheduleCanonically(IdempotentInstCount
, MBB
);
388 LLVM_DEBUG(dbgs() << "MBB After Scheduling:\n"; MBB
->dump(););
390 Changed
|= Renamer
.renameVRegs(MBB
, BasicBlockNum
);
392 // TODO: Consider dropping this. Dropping kill defs is probably not
393 // semantically sound.
394 Changed
|= doDefKillClear(MBB
);
396 LLVM_DEBUG(dbgs() << "Updated MachineBasicBlock:\n"; MBB
->dump();
399 dbgs() << "\n\n================================================\n\n");
403 bool MIRCanonicalizer::runOnMachineFunction(MachineFunction
&MF
) {
405 static unsigned functionNum
= 0;
406 if (CanonicalizeFunctionNumber
!= ~0U) {
407 if (CanonicalizeFunctionNumber
!= functionNum
++)
409 LLVM_DEBUG(dbgs() << "\n Canonicalizing Function " << MF
.getName()
413 // we need a valid vreg to create a vreg type for skipping all those
414 // stray vreg numbers so reach alignment/canonical vreg values.
415 std::vector
<MachineBasicBlock
*> RPOList
= GetRPOList(MF
);
418 dbgs() << "\n\n NEW MACHINE FUNCTION: " << MF
.getName() << " \n\n";
419 dbgs() << "\n\n================================================\n\n";
420 dbgs() << "Total Basic Blocks: " << RPOList
.size() << "\n";
422 : RPOList
) { dbgs() << MBB
->getName() << "\n"; } dbgs()
423 << "\n\n================================================\n\n";);
426 bool Changed
= false;
427 MachineRegisterInfo
&MRI
= MF
.getRegInfo();
428 VRegRenamer
Renamer(MRI
);
429 for (auto MBB
: RPOList
)
430 Changed
|= runOnBasicBlock(MBB
, BBNum
++, Renamer
);