blob: 7d9d812d34bcd52a71d330bd55b410b434580b75 [file] [log] [blame]
Aditya Nandakumar500e3ea2019-01-16 00:40:37 +00001//===- CSEInfo.cpp ------------------------------===//
2//
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 Nandakumar500e3ea2019-01-16 00:40:37 +00006//
7//===----------------------------------------------------------------------===//
8//
9//
10//===----------------------------------------------------------------------===//
11#include "llvm/CodeGen/GlobalISel/CSEInfo.h"
12#include "llvm/CodeGen/MachineRegisterInfo.h"
13
14#define DEBUG_TYPE "cseinfo"
15
16using namespace llvm;
17char llvm::GISelCSEAnalysisWrapperPass::ID = 0;
18INITIALIZE_PASS_BEGIN(GISelCSEAnalysisWrapperPass, DEBUG_TYPE,
19 "Analysis containing CSE Info", false, true)
20INITIALIZE_PASS_END(GISelCSEAnalysisWrapperPass, DEBUG_TYPE,
21 "Analysis containing CSE Info", false, true)
22
23/// -------- UniqueMachineInstr -------------//
24
25void UniqueMachineInstr::Profile(FoldingSetNodeID &ID) {
26 GISelInstProfileBuilder(ID, MI->getMF()->getRegInfo()).addNodeID(MI);
27}
28/// -----------------------------------------
29
Amara Emersond1896802019-04-15 04:53:46 +000030/// --------- CSEConfigFull ---------- ///
31bool CSEConfigFull::shouldCSEOpc(unsigned Opc) {
Aditya Nandakumar500e3ea2019-01-16 00:40:37 +000032 switch (Opc) {
33 default:
34 break;
35 case TargetOpcode::G_ADD:
36 case TargetOpcode::G_AND:
37 case TargetOpcode::G_ASHR:
38 case TargetOpcode::G_LSHR:
39 case TargetOpcode::G_MUL:
40 case TargetOpcode::G_OR:
41 case TargetOpcode::G_SHL:
42 case TargetOpcode::G_SUB:
43 case TargetOpcode::G_XOR:
44 case TargetOpcode::G_UDIV:
45 case TargetOpcode::G_SDIV:
46 case TargetOpcode::G_UREM:
47 case TargetOpcode::G_SREM:
48 case TargetOpcode::G_CONSTANT:
49 case TargetOpcode::G_FCONSTANT:
50 case TargetOpcode::G_ZEXT:
51 case TargetOpcode::G_SEXT:
52 case TargetOpcode::G_ANYEXT:
53 case TargetOpcode::G_UNMERGE_VALUES:
54 case TargetOpcode::G_TRUNC:
Volkan Keles0ae60062019-08-15 23:45:45 +000055 case TargetOpcode::G_GEP:
Aditya Nandakumar500e3ea2019-01-16 00:40:37 +000056 return true;
57 }
58 return false;
59}
60
61bool CSEConfigConstantOnly::shouldCSEOpc(unsigned Opc) {
62 return Opc == TargetOpcode::G_CONSTANT;
63}
Amara Emersond1896802019-04-15 04:53:46 +000064
65std::unique_ptr<CSEConfigBase>
66llvm::getStandardCSEConfigForOpt(CodeGenOpt::Level Level) {
67 std::unique_ptr<CSEConfigBase> Config;
68 if (Level == CodeGenOpt::None)
Jonas Devlieghere0eaee542019-08-15 15:54:37 +000069 Config = std::make_unique<CSEConfigConstantOnly>();
Amara Emersond1896802019-04-15 04:53:46 +000070 else
Jonas Devlieghere0eaee542019-08-15 15:54:37 +000071 Config = std::make_unique<CSEConfigFull>();
Amara Emersond1896802019-04-15 04:53:46 +000072 return Config;
73}
74
Aditya Nandakumar500e3ea2019-01-16 00:40:37 +000075/// -----------------------------------------
76
77/// -------- GISelCSEInfo -------------//
78void GISelCSEInfo::setMF(MachineFunction &MF) {
79 this->MF = &MF;
80 this->MRI = &MF.getRegInfo();
81}
82
83GISelCSEInfo::~GISelCSEInfo() {}
84
85bool GISelCSEInfo::isUniqueMachineInstValid(
86 const UniqueMachineInstr &UMI) const {
87 // Should we check here and assert that the instruction has been fully
88 // constructed?
89 // FIXME: Any other checks required to be done here? Remove this method if
90 // none.
91 return true;
92}
93
94void GISelCSEInfo::invalidateUniqueMachineInstr(UniqueMachineInstr *UMI) {
95 bool Removed = CSEMap.RemoveNode(UMI);
96 (void)Removed;
97 assert(Removed && "Invalidation called on invalid UMI");
98 // FIXME: Should UMI be deallocated/destroyed?
99}
100
101UniqueMachineInstr *GISelCSEInfo::getNodeIfExists(FoldingSetNodeID &ID,
102 MachineBasicBlock *MBB,
103 void *&InsertPos) {
104 auto *Node = CSEMap.FindNodeOrInsertPos(ID, InsertPos);
105 if (Node) {
106 if (!isUniqueMachineInstValid(*Node)) {
107 invalidateUniqueMachineInstr(Node);
108 return nullptr;
109 }
110
111 if (Node->MI->getParent() != MBB)
112 return nullptr;
113 }
114 return Node;
115}
116
117void GISelCSEInfo::insertNode(UniqueMachineInstr *UMI, void *InsertPos) {
118 handleRecordedInsts();
119 assert(UMI);
120 UniqueMachineInstr *MaybeNewNode = UMI;
121 if (InsertPos)
122 CSEMap.InsertNode(UMI, InsertPos);
123 else
124 MaybeNewNode = CSEMap.GetOrInsertNode(UMI);
125 if (MaybeNewNode != UMI) {
126 // A similar node exists in the folding set. Let's ignore this one.
127 return;
128 }
129 assert(InstrMapping.count(UMI->MI) == 0 &&
130 "This instruction should not be in the map");
131 InstrMapping[UMI->MI] = MaybeNewNode;
132}
133
134UniqueMachineInstr *GISelCSEInfo::getUniqueInstrForMI(const MachineInstr *MI) {
135 assert(shouldCSE(MI->getOpcode()) && "Trying to CSE an unsupported Node");
136 auto *Node = new (UniqueInstrAllocator) UniqueMachineInstr(MI);
137 return Node;
138}
139
140void GISelCSEInfo::insertInstr(MachineInstr *MI, void *InsertPos) {
141 assert(MI);
142 // If it exists in temporary insts, remove it.
143 TemporaryInsts.remove(MI);
144 auto *Node = getUniqueInstrForMI(MI);
145 insertNode(Node, InsertPos);
146}
147
148MachineInstr *GISelCSEInfo::getMachineInstrIfExists(FoldingSetNodeID &ID,
149 MachineBasicBlock *MBB,
150 void *&InsertPos) {
151 handleRecordedInsts();
152 if (auto *Inst = getNodeIfExists(ID, MBB, InsertPos)) {
Francis Visoiu Mistrih8bc57952019-02-08 23:34:11 +0000153 LLVM_DEBUG(dbgs() << "CSEInfo::Found Instr " << *Inst->MI;);
Aditya Nandakumar500e3ea2019-01-16 00:40:37 +0000154 return const_cast<MachineInstr *>(Inst->MI);
155 }
156 return nullptr;
157}
158
159void GISelCSEInfo::countOpcodeHit(unsigned Opc) {
160#ifndef NDEBUG
161 if (OpcodeHitTable.count(Opc))
162 OpcodeHitTable[Opc] += 1;
163 else
164 OpcodeHitTable[Opc] = 1;
165#endif
166 // Else do nothing.
167}
168
169void GISelCSEInfo::recordNewInstruction(MachineInstr *MI) {
170 if (shouldCSE(MI->getOpcode())) {
171 TemporaryInsts.insert(MI);
Francis Visoiu Mistrih8bc57952019-02-08 23:34:11 +0000172 LLVM_DEBUG(dbgs() << "CSEInfo::Recording new MI " << *MI);
Aditya Nandakumar500e3ea2019-01-16 00:40:37 +0000173 }
174}
175
176void GISelCSEInfo::handleRecordedInst(MachineInstr *MI) {
177 assert(shouldCSE(MI->getOpcode()) && "Invalid instruction for CSE");
178 auto *UMI = InstrMapping.lookup(MI);
Francis Visoiu Mistrih8bc57952019-02-08 23:34:11 +0000179 LLVM_DEBUG(dbgs() << "CSEInfo::Handling recorded MI " << *MI);
Aditya Nandakumar500e3ea2019-01-16 00:40:37 +0000180 if (UMI) {
181 // Invalidate this MI.
182 invalidateUniqueMachineInstr(UMI);
183 InstrMapping.erase(MI);
184 }
185 /// Now insert the new instruction.
186 if (UMI) {
187 /// We'll reuse the same UniqueMachineInstr to avoid the new
188 /// allocation.
189 *UMI = UniqueMachineInstr(MI);
190 insertNode(UMI, nullptr);
191 } else {
192 /// This is a new instruction. Allocate a new UniqueMachineInstr and
193 /// Insert.
194 insertInstr(MI);
195 }
196}
197
198void GISelCSEInfo::handleRemoveInst(MachineInstr *MI) {
199 if (auto *UMI = InstrMapping.lookup(MI)) {
200 invalidateUniqueMachineInstr(UMI);
201 InstrMapping.erase(MI);
202 }
203 TemporaryInsts.remove(MI);
204}
205
206void GISelCSEInfo::handleRecordedInsts() {
207 while (!TemporaryInsts.empty()) {
208 auto *MI = TemporaryInsts.pop_back_val();
209 handleRecordedInst(MI);
210 }
211}
212
213bool GISelCSEInfo::shouldCSE(unsigned Opc) const {
214 // Only GISel opcodes are CSEable
215 if (!isPreISelGenericOpcode(Opc))
216 return false;
217 assert(CSEOpt.get() && "CSEConfig not set");
218 return CSEOpt->shouldCSEOpc(Opc);
219}
220
221void GISelCSEInfo::erasingInstr(MachineInstr &MI) { handleRemoveInst(&MI); }
222void GISelCSEInfo::createdInstr(MachineInstr &MI) { recordNewInstruction(&MI); }
223void GISelCSEInfo::changingInstr(MachineInstr &MI) {
224 // For now, perform erase, followed by insert.
225 erasingInstr(MI);
226 createdInstr(MI);
227}
228void GISelCSEInfo::changedInstr(MachineInstr &MI) { changingInstr(MI); }
229
230void GISelCSEInfo::analyze(MachineFunction &MF) {
231 setMF(MF);
232 for (auto &MBB : MF) {
233 if (MBB.empty())
234 continue;
235 for (MachineInstr &MI : MBB) {
236 if (!shouldCSE(MI.getOpcode()))
237 continue;
Matt Arsenault56edf3f2019-02-04 14:05:33 +0000238 LLVM_DEBUG(dbgs() << "CSEInfo::Add MI: " << MI);
Aditya Nandakumar500e3ea2019-01-16 00:40:37 +0000239 insertInstr(&MI);
240 }
241 }
242}
243
244void GISelCSEInfo::releaseMemory() {
Francis Visoiu Mistrih8bc57952019-02-08 23:34:11 +0000245 print();
Aditya Nandakumar500e3ea2019-01-16 00:40:37 +0000246 CSEMap.clear();
247 InstrMapping.clear();
248 UniqueInstrAllocator.Reset();
249 TemporaryInsts.clear();
250 CSEOpt.reset();
251 MRI = nullptr;
252 MF = nullptr;
253#ifndef NDEBUG
254 OpcodeHitTable.clear();
255#endif
256}
257
258void GISelCSEInfo::print() {
Francis Visoiu Mistrih8bc57952019-02-08 23:34:11 +0000259 LLVM_DEBUG(for (auto &It
260 : OpcodeHitTable) {
261 dbgs() << "CSEInfo::CSE Hit for Opc " << It.first << " : " << It.second
262 << "\n";
263 };);
Aditya Nandakumar500e3ea2019-01-16 00:40:37 +0000264}
265/// -----------------------------------------
266// ---- Profiling methods for FoldingSetNode --- //
267const GISelInstProfileBuilder &
268GISelInstProfileBuilder::addNodeID(const MachineInstr *MI) const {
269 addNodeIDMBB(MI->getParent());
270 addNodeIDOpcode(MI->getOpcode());
271 for (auto &Op : MI->operands())
272 addNodeIDMachineOperand(Op);
273 addNodeIDFlag(MI->getFlags());
274 return *this;
275}
276
277const GISelInstProfileBuilder &
278GISelInstProfileBuilder::addNodeIDOpcode(unsigned Opc) const {
279 ID.AddInteger(Opc);
280 return *this;
281}
282
283const GISelInstProfileBuilder &
284GISelInstProfileBuilder::addNodeIDRegType(const LLT &Ty) const {
285 uint64_t Val = Ty.getUniqueRAWLLTData();
286 ID.AddInteger(Val);
287 return *this;
288}
289
290const GISelInstProfileBuilder &
291GISelInstProfileBuilder::addNodeIDRegType(const TargetRegisterClass *RC) const {
292 ID.AddPointer(RC);
293 return *this;
294}
295
296const GISelInstProfileBuilder &
297GISelInstProfileBuilder::addNodeIDRegType(const RegisterBank *RB) const {
298 ID.AddPointer(RB);
299 return *this;
300}
301
302const GISelInstProfileBuilder &
303GISelInstProfileBuilder::addNodeIDImmediate(int64_t Imm) const {
304 ID.AddInteger(Imm);
305 return *this;
306}
307
308const GISelInstProfileBuilder &
309GISelInstProfileBuilder::addNodeIDRegNum(unsigned Reg) const {
310 ID.AddInteger(Reg);
311 return *this;
312}
313
314const GISelInstProfileBuilder &
315GISelInstProfileBuilder::addNodeIDRegType(const unsigned Reg) const {
316 addNodeIDMachineOperand(MachineOperand::CreateReg(Reg, false));
317 return *this;
318}
319
320const GISelInstProfileBuilder &
321GISelInstProfileBuilder::addNodeIDMBB(const MachineBasicBlock *MBB) const {
322 ID.AddPointer(MBB);
323 return *this;
324}
325
326const GISelInstProfileBuilder &
327GISelInstProfileBuilder::addNodeIDFlag(unsigned Flag) const {
328 if (Flag)
329 ID.AddInteger(Flag);
330 return *this;
331}
332
333const GISelInstProfileBuilder &GISelInstProfileBuilder::addNodeIDMachineOperand(
334 const MachineOperand &MO) const {
335 if (MO.isReg()) {
Daniel Sanders0c476112019-08-15 19:22:08 +0000336 Register Reg = MO.getReg();
Aditya Nandakumar500e3ea2019-01-16 00:40:37 +0000337 if (!MO.isDef())
338 addNodeIDRegNum(Reg);
339 LLT Ty = MRI.getType(Reg);
340 if (Ty.isValid())
341 addNodeIDRegType(Ty);
342 auto *RB = MRI.getRegBankOrNull(Reg);
343 if (RB)
344 addNodeIDRegType(RB);
345 auto *RC = MRI.getRegClassOrNull(Reg);
346 if (RC)
347 addNodeIDRegType(RC);
348 assert(!MO.isImplicit() && "Unhandled case");
349 } else if (MO.isImm())
350 ID.AddInteger(MO.getImm());
351 else if (MO.isCImm())
352 ID.AddPointer(MO.getCImm());
353 else if (MO.isFPImm())
354 ID.AddPointer(MO.getFPImm());
355 else if (MO.isPredicate())
356 ID.AddInteger(MO.getPredicate());
357 else
358 llvm_unreachable("Unhandled operand type");
359 // Handle other types
360 return *this;
361}
362
Amara Emersond1896802019-04-15 04:53:46 +0000363GISelCSEInfo &
364GISelCSEAnalysisWrapper::get(std::unique_ptr<CSEConfigBase> CSEOpt,
365 bool Recompute) {
Aditya Nandakumar500e3ea2019-01-16 00:40:37 +0000366 if (!AlreadyComputed || Recompute) {
367 Info.setCSEConfig(std::move(CSEOpt));
368 Info.analyze(*MF);
369 AlreadyComputed = true;
370 }
371 return Info;
372}
373void GISelCSEAnalysisWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
374 AU.setPreservesAll();
375 MachineFunctionPass::getAnalysisUsage(AU);
376}
377
378bool GISelCSEAnalysisWrapperPass::runOnMachineFunction(MachineFunction &MF) {
379 releaseMemory();
380 Wrapper.setMF(MF);
381 return false;
382}