blob: 31cb1dbbc9b5a74ec9359eba8e07725360bfe8ae [file] [log] [blame]
Daniel Sanders629db5d2018-12-14 17:50:14 +00001//===-- lib/CodeGen/GlobalISel/Combiner.cpp -------------------------------===//
Aditya Nandakumar81c81b62018-01-25 00:41:58 +00002//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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
Aditya Nandakumar81c81b62018-01-25 00:41:58 +00006//
7//===----------------------------------------------------------------------===//
8//
9// This file constains common code to combine machine functions at generic
10// level.
11//===----------------------------------------------------------------------===//
12
13#include "llvm/CodeGen/GlobalISel/Combiner.h"
Aditya Nandakumar81c81b62018-01-25 00:41:58 +000014#include "llvm/ADT/PostOrderIterator.h"
Aditya Nandakumar500e3ea2019-01-16 00:40:37 +000015#include "llvm/CodeGen/GlobalISel/CSEInfo.h"
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +000016#include "llvm/CodeGen/GlobalISel/CombinerInfo.h"
Aditya Nandakumar500e3ea2019-01-16 00:40:37 +000017#include "llvm/CodeGen/GlobalISel/CSEMIRBuilder.h"
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +000018#include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
19#include "llvm/CodeGen/GlobalISel/GISelWorkList.h"
20#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
Aditya Nandakumar81c81b62018-01-25 00:41:58 +000021#include "llvm/CodeGen/GlobalISel/Utils.h"
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +000022#include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
Aditya Nandakumar81c81b62018-01-25 00:41:58 +000023#include "llvm/CodeGen/MachineRegisterInfo.h"
24#include "llvm/Support/Debug.h"
25
26#define DEBUG_TYPE "gi-combiner"
27
28using namespace llvm;
29
Daniel Sandersc973ad12018-10-03 02:12:17 +000030namespace {
31/// This class acts as the glue the joins the CombinerHelper to the overall
32/// Combine algorithm. The CombinerHelper is intended to report the
Daniel Sanders629db5d2018-12-14 17:50:14 +000033/// modifications it makes to the MIR to the GISelChangeObserver and the
Daniel Sandersc973ad12018-10-03 02:12:17 +000034/// observer subclass will act on these events. In this case, instruction
35/// erasure will cancel any future visits to the erased instruction and
36/// instruction creation will schedule that instruction for a future visit.
37/// Other Combiner implementations may require more complex behaviour from
Daniel Sanders629db5d2018-12-14 17:50:14 +000038/// their GISelChangeObserver subclass.
Aditya Nandakumar500e3ea2019-01-16 00:40:37 +000039class WorkListMaintainer : public GISelChangeObserver {
Daniel Sandersc973ad12018-10-03 02:12:17 +000040 using WorkListTy = GISelWorkList<512>;
41 WorkListTy &WorkList;
Daniel Sanders629db5d2018-12-14 17:50:14 +000042 /// The instructions that have been created but we want to report once they
43 /// have their operands. This is only maintained if debug output is requested.
44 SmallPtrSet<const MachineInstr *, 4> CreatedInstrs;
Daniel Sandersc973ad12018-10-03 02:12:17 +000045
46public:
Aditya Nandakumar500e3ea2019-01-16 00:40:37 +000047 WorkListMaintainer(WorkListTy &WorkList)
48 : GISelChangeObserver(), WorkList(WorkList) {}
Daniel Sanders629db5d2018-12-14 17:50:14 +000049 virtual ~WorkListMaintainer() {
Daniel Sanders629db5d2018-12-14 17:50:14 +000050 }
Daniel Sandersc973ad12018-10-03 02:12:17 +000051
Aditya Nandakumar500e3ea2019-01-16 00:40:37 +000052 void erasingInstr(MachineInstr &MI) override {
Daniel Sanders24e0af62019-02-11 20:45:19 +000053 LLVM_DEBUG(dbgs() << "Erasing: " << MI << "\n");
Daniel Sandersc973ad12018-10-03 02:12:17 +000054 WorkList.remove(&MI);
55 }
Aditya Nandakumar500e3ea2019-01-16 00:40:37 +000056 void createdInstr(MachineInstr &MI) override {
Daniel Sanders629db5d2018-12-14 17:50:14 +000057 LLVM_DEBUG(dbgs() << "Creating: " << MI << "\n");
58 WorkList.insert(&MI);
59 LLVM_DEBUG(CreatedInstrs.insert(&MI));
60 }
Aditya Nandakumar500e3ea2019-01-16 00:40:37 +000061 void changingInstr(MachineInstr &MI) override {
Daniel Sanders629db5d2018-12-14 17:50:14 +000062 LLVM_DEBUG(dbgs() << "Changing: " << MI << "\n");
Daniel Sandersc973ad12018-10-03 02:12:17 +000063 WorkList.insert(&MI);
64 }
Aditya Nandakumar500e3ea2019-01-16 00:40:37 +000065 void changedInstr(MachineInstr &MI) override {
Daniel Sandersd001e0e2018-12-12 23:48:13 +000066 LLVM_DEBUG(dbgs() << "Changed: " << MI << "\n");
Daniel Sanders629db5d2018-12-14 17:50:14 +000067 WorkList.insert(&MI);
68 }
69
70 void reportFullyCreatedInstrs() {
71 LLVM_DEBUG(for (const auto *MI
72 : CreatedInstrs) {
73 dbgs() << "Created: ";
74 MI->print(dbgs());
75 });
76 LLVM_DEBUG(CreatedInstrs.clear());
77 }
Daniel Sandersc973ad12018-10-03 02:12:17 +000078};
79}
80
Aditya Nandakumar81c81b62018-01-25 00:41:58 +000081Combiner::Combiner(CombinerInfo &Info, const TargetPassConfig *TPC)
82 : CInfo(Info), TPC(TPC) {
83 (void)this->TPC; // FIXME: Remove when used.
84}
85
Aditya Nandakumar500e3ea2019-01-16 00:40:37 +000086bool Combiner::combineMachineInstrs(MachineFunction &MF,
87 GISelCSEInfo *CSEInfo) {
Aditya Nandakumar81c81b62018-01-25 00:41:58 +000088 // If the ISel pipeline failed, do not bother running this pass.
89 // FIXME: Should this be here or in individual combiner passes.
90 if (MF.getProperties().hasProperty(
91 MachineFunctionProperties::Property::FailedISel))
92 return false;
93
Aditya Nandakumar500e3ea2019-01-16 00:40:37 +000094 Builder =
95 CSEInfo ? make_unique<CSEMIRBuilder>() : make_unique<MachineIRBuilder>();
Aditya Nandakumar81c81b62018-01-25 00:41:58 +000096 MRI = &MF.getRegInfo();
Aditya Nandakumar500e3ea2019-01-16 00:40:37 +000097 Builder->setMF(MF);
98 if (CSEInfo)
99 Builder->setCSEInfo(CSEInfo);
Aditya Nandakumar81c81b62018-01-25 00:41:58 +0000100
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000101 LLVM_DEBUG(dbgs() << "Generic MI Combiner for: " << MF.getName() << '\n');
Aditya Nandakumar81c81b62018-01-25 00:41:58 +0000102
103 MachineOptimizationRemarkEmitter MORE(MF, /*MBFI=*/nullptr);
104
105 bool MFChanged = false;
106 bool Changed;
Aditya Nandakumar500e3ea2019-01-16 00:40:37 +0000107 MachineIRBuilder &B = *Builder.get();
Aditya Nandakumar81c81b62018-01-25 00:41:58 +0000108
109 do {
110 // Collect all instructions. Do a post order traversal for basic blocks and
111 // insert with list bottom up, so while we pop_back_val, we'll traverse top
112 // down RPOT.
113 Changed = false;
Aditya Nandakumar500e3ea2019-01-16 00:40:37 +0000114 GISelWorkList<512> WorkList;
115 WorkListMaintainer Observer(WorkList);
116 GISelObserverWrapper WrapperObserver(&Observer);
117 if (CSEInfo)
118 WrapperObserver.addObserver(CSEInfo);
119 RAIIDelegateInstaller DelInstall(MF, &WrapperObserver);
Aditya Nandakumar81c81b62018-01-25 00:41:58 +0000120 for (MachineBasicBlock *MBB : post_order(&MF)) {
121 if (MBB->empty())
122 continue;
123 for (auto MII = MBB->rbegin(), MIE = MBB->rend(); MII != MIE;) {
124 MachineInstr *CurMI = &*MII;
125 ++MII;
126 // Erase dead insts before even adding to the list.
127 if (isTriviallyDead(*CurMI, *MRI)) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000128 LLVM_DEBUG(dbgs() << *CurMI << "Is dead; erasing.\n");
Aditya Nandakumar81c81b62018-01-25 00:41:58 +0000129 CurMI->eraseFromParentAndMarkDBGValuesForRemoval();
130 continue;
131 }
Aditya Nandakumar0e362ec12019-02-15 01:37:54 +0000132 WorkList.deferred_insert(CurMI);
Aditya Nandakumar81c81b62018-01-25 00:41:58 +0000133 }
134 }
Aditya Nandakumar0e362ec12019-02-15 01:37:54 +0000135 WorkList.finalize();
Aditya Nandakumar81c81b62018-01-25 00:41:58 +0000136 // Main Loop. Process the instructions here.
137 while (!WorkList.empty()) {
138 MachineInstr *CurrInst = WorkList.pop_back_val();
Daniel Sanders629db5d2018-12-14 17:50:14 +0000139 LLVM_DEBUG(dbgs() << "\nTry combining " << *CurrInst;);
Aditya Nandakumar500e3ea2019-01-16 00:40:37 +0000140 Changed |= CInfo.combine(WrapperObserver, *CurrInst, B);
Daniel Sanders629db5d2018-12-14 17:50:14 +0000141 Observer.reportFullyCreatedInstrs();
Aditya Nandakumar81c81b62018-01-25 00:41:58 +0000142 }
143 MFChanged |= Changed;
144 } while (Changed);
145
146 return MFChanged;
147}