1 //===-- lib/CodeGen/GlobalISel/GICombiner.cpp -----------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file constains common code to combine machine functions at generic
12 //===----------------------------------------------------------------------===//
14 #include "llvm/CodeGen/GlobalISel/Combiner.h"
15 #include "llvm/CodeGen/GlobalISel/CombinerInfo.h"
16 #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
17 #include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
18 #include "llvm/CodeGen/GlobalISel/GISelWorkList.h"
19 #include "llvm/ADT/PostOrderIterator.h"
20 #include "llvm/CodeGen/GlobalISel/Utils.h"
21 #include "llvm/CodeGen/MachineRegisterInfo.h"
22 #include "llvm/Support/Debug.h"
24 #define DEBUG_TYPE "gi-combiner"
29 /// This class acts as the glue the joins the CombinerHelper to the overall
30 /// Combine algorithm. The CombinerHelper is intended to report the
31 /// modifications it makes to the MIR to the CombinerChangeObserver and the
32 /// observer subclass will act on these events. In this case, instruction
33 /// erasure will cancel any future visits to the erased instruction and
34 /// instruction creation will schedule that instruction for a future visit.
35 /// Other Combiner implementations may require more complex behaviour from
36 /// their CombinerChangeObserver subclass.
37 class WorkListMaintainer
: public CombinerChangeObserver
{
38 using WorkListTy
= GISelWorkList
<512>;
42 WorkListMaintainer(WorkListTy
&WorkList
) : WorkList(WorkList
) {}
43 virtual ~WorkListMaintainer() {}
45 void erasedInstr(MachineInstr
&MI
) override
{
46 LLVM_DEBUG(dbgs() << "Erased: "; MI
.print(dbgs()); dbgs() << "\n");
49 void createdInstr(MachineInstr
&MI
) override
{
50 LLVM_DEBUG(dbgs() << "Created: "; MI
.print(dbgs()); dbgs() << "\n");
56 Combiner::Combiner(CombinerInfo
&Info
, const TargetPassConfig
*TPC
)
57 : CInfo(Info
), TPC(TPC
) {
58 (void)this->TPC
; // FIXME: Remove when used.
61 bool Combiner::combineMachineInstrs(MachineFunction
&MF
) {
62 // If the ISel pipeline failed, do not bother running this pass.
63 // FIXME: Should this be here or in individual combiner passes.
64 if (MF
.getProperties().hasProperty(
65 MachineFunctionProperties::Property::FailedISel
))
68 MRI
= &MF
.getRegInfo();
71 LLVM_DEBUG(dbgs() << "Generic MI Combiner for: " << MF
.getName() << '\n');
73 MachineOptimizationRemarkEmitter
MORE(MF
, /*MBFI=*/nullptr);
75 bool MFChanged
= false;
79 // Collect all instructions. Do a post order traversal for basic blocks and
80 // insert with list bottom up, so while we pop_back_val, we'll traverse top
83 GISelWorkList
<512> WorkList
;
84 WorkListMaintainer
Observer(WorkList
);
85 for (MachineBasicBlock
*MBB
: post_order(&MF
)) {
88 for (auto MII
= MBB
->rbegin(), MIE
= MBB
->rend(); MII
!= MIE
;) {
89 MachineInstr
*CurMI
= &*MII
;
91 // Erase dead insts before even adding to the list.
92 if (isTriviallyDead(*CurMI
, *MRI
)) {
93 LLVM_DEBUG(dbgs() << *CurMI
<< "Is dead; erasing.\n");
94 CurMI
->eraseFromParentAndMarkDBGValuesForRemoval();
97 WorkList
.insert(CurMI
);
100 // Main Loop. Process the instructions here.
101 while (!WorkList
.empty()) {
102 MachineInstr
*CurrInst
= WorkList
.pop_back_val();
103 LLVM_DEBUG(dbgs() << "Try combining " << *CurrInst
<< "\n";);
104 Changed
|= CInfo
.combine(Observer
, *CurrInst
, Builder
);
106 MFChanged
|= Changed
;