blob: f3f075af4869598c724f9e833d3d4556e9394d58 [file] [log] [blame]
Aditya Nandakumar81c81b62018-01-25 00:41:58 +00001//===-- lib/CodeGen/GlobalISel/GICombiner.cpp -----------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file constains common code to combine machine functions at generic
11// level.
12//===----------------------------------------------------------------------===//
13
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"
23
24#define DEBUG_TYPE "gi-combiner"
25
26using namespace llvm;
27
Daniel Sandersc973ad12018-10-03 02:12:17 +000028namespace {
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.
37class WorkListMaintainer : public CombinerChangeObserver {
38 using WorkListTy = GISelWorkList<512>;
39 WorkListTy &WorkList;
40
41public:
42 WorkListMaintainer(WorkListTy &WorkList) : WorkList(WorkList) {}
43 virtual ~WorkListMaintainer() {}
44
45 void erasedInstr(MachineInstr &MI) override {
46 LLVM_DEBUG(dbgs() << "Erased: "; MI.print(dbgs()); dbgs() << "\n");
47 WorkList.remove(&MI);
48 }
49 void createdInstr(MachineInstr &MI) override {
50 LLVM_DEBUG(dbgs() << "Created: "; MI.print(dbgs()); dbgs() << "\n");
51 WorkList.insert(&MI);
52 }
53};
54}
55
Aditya Nandakumar81c81b62018-01-25 00:41:58 +000056Combiner::Combiner(CombinerInfo &Info, const TargetPassConfig *TPC)
57 : CInfo(Info), TPC(TPC) {
58 (void)this->TPC; // FIXME: Remove when used.
59}
60
61bool 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))
66 return false;
67
68 MRI = &MF.getRegInfo();
69 Builder.setMF(MF);
70
Nicola Zaghend34e60c2018-05-14 12:53:11 +000071 LLVM_DEBUG(dbgs() << "Generic MI Combiner for: " << MF.getName() << '\n');
Aditya Nandakumar81c81b62018-01-25 00:41:58 +000072
73 MachineOptimizationRemarkEmitter MORE(MF, /*MBFI=*/nullptr);
74
75 bool MFChanged = false;
76 bool Changed;
77
78 do {
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
81 // down RPOT.
82 Changed = false;
83 GISelWorkList<512> WorkList;
Daniel Sandersc973ad12018-10-03 02:12:17 +000084 WorkListMaintainer Observer(WorkList);
Aditya Nandakumar81c81b62018-01-25 00:41:58 +000085 for (MachineBasicBlock *MBB : post_order(&MF)) {
86 if (MBB->empty())
87 continue;
88 for (auto MII = MBB->rbegin(), MIE = MBB->rend(); MII != MIE;) {
89 MachineInstr *CurMI = &*MII;
90 ++MII;
91 // Erase dead insts before even adding to the list.
92 if (isTriviallyDead(*CurMI, *MRI)) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +000093 LLVM_DEBUG(dbgs() << *CurMI << "Is dead; erasing.\n");
Aditya Nandakumar81c81b62018-01-25 00:41:58 +000094 CurMI->eraseFromParentAndMarkDBGValuesForRemoval();
95 continue;
96 }
97 WorkList.insert(CurMI);
98 }
99 }
100 // Main Loop. Process the instructions here.
101 while (!WorkList.empty()) {
102 MachineInstr *CurrInst = WorkList.pop_back_val();
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000103 LLVM_DEBUG(dbgs() << "Try combining " << *CurrInst << "\n";);
Daniel Sandersc973ad12018-10-03 02:12:17 +0000104 Changed |= CInfo.combine(Observer, *CurrInst, Builder);
Aditya Nandakumar81c81b62018-01-25 00:41:58 +0000105 }
106 MFChanged |= Changed;
107 } while (Changed);
108
109 return MFChanged;
110}