1 //===- CSEInfo.cpp ------------------------------===//
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 //===----------------------------------------------------------------------===//
10 //===----------------------------------------------------------------------===//
11 #include "llvm/CodeGen/GlobalISel/CSEInfo.h"
12 #include "llvm/CodeGen/MachineRegisterInfo.h"
14 #define DEBUG_TYPE "cseinfo"
17 char llvm::GISelCSEAnalysisWrapperPass::ID
= 0;
18 INITIALIZE_PASS_BEGIN(GISelCSEAnalysisWrapperPass
, DEBUG_TYPE
,
19 "Analysis containing CSE Info", false, true)
20 INITIALIZE_PASS_END(GISelCSEAnalysisWrapperPass
, DEBUG_TYPE
,
21 "Analysis containing CSE Info", false, true)
23 /// -------- UniqueMachineInstr -------------//
25 void UniqueMachineInstr::Profile(FoldingSetNodeID
&ID
) {
26 GISelInstProfileBuilder(ID
, MI
->getMF()->getRegInfo()).addNodeID(MI
);
28 /// -----------------------------------------
30 /// --------- CSEConfigFull ---------- ///
31 bool CSEConfigFull::shouldCSEOpc(unsigned Opc
) {
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
:
55 case TargetOpcode::G_GEP
:
61 bool CSEConfigConstantOnly::shouldCSEOpc(unsigned Opc
) {
62 return Opc
== TargetOpcode::G_CONSTANT
;
65 std::unique_ptr
<CSEConfigBase
>
66 llvm::getStandardCSEConfigForOpt(CodeGenOpt::Level Level
) {
67 std::unique_ptr
<CSEConfigBase
> Config
;
68 if (Level
== CodeGenOpt::None
)
69 Config
= std::make_unique
<CSEConfigConstantOnly
>();
71 Config
= std::make_unique
<CSEConfigFull
>();
75 /// -----------------------------------------
77 /// -------- GISelCSEInfo -------------//
78 void GISelCSEInfo::setMF(MachineFunction
&MF
) {
80 this->MRI
= &MF
.getRegInfo();
83 GISelCSEInfo::~GISelCSEInfo() {}
85 bool GISelCSEInfo::isUniqueMachineInstValid(
86 const UniqueMachineInstr
&UMI
) const {
87 // Should we check here and assert that the instruction has been fully
89 // FIXME: Any other checks required to be done here? Remove this method if
94 void GISelCSEInfo::invalidateUniqueMachineInstr(UniqueMachineInstr
*UMI
) {
95 bool Removed
= CSEMap
.RemoveNode(UMI
);
97 assert(Removed
&& "Invalidation called on invalid UMI");
98 // FIXME: Should UMI be deallocated/destroyed?
101 UniqueMachineInstr
*GISelCSEInfo::getNodeIfExists(FoldingSetNodeID
&ID
,
102 MachineBasicBlock
*MBB
,
104 auto *Node
= CSEMap
.FindNodeOrInsertPos(ID
, InsertPos
);
106 if (!isUniqueMachineInstValid(*Node
)) {
107 invalidateUniqueMachineInstr(Node
);
111 if (Node
->MI
->getParent() != MBB
)
117 void GISelCSEInfo::insertNode(UniqueMachineInstr
*UMI
, void *InsertPos
) {
118 handleRecordedInsts();
120 UniqueMachineInstr
*MaybeNewNode
= UMI
;
122 CSEMap
.InsertNode(UMI
, InsertPos
);
124 MaybeNewNode
= CSEMap
.GetOrInsertNode(UMI
);
125 if (MaybeNewNode
!= UMI
) {
126 // A similar node exists in the folding set. Let's ignore this one.
129 assert(InstrMapping
.count(UMI
->MI
) == 0 &&
130 "This instruction should not be in the map");
131 InstrMapping
[UMI
->MI
] = MaybeNewNode
;
134 UniqueMachineInstr
*GISelCSEInfo::getUniqueInstrForMI(const MachineInstr
*MI
) {
135 assert(shouldCSE(MI
->getOpcode()) && "Trying to CSE an unsupported Node");
136 auto *Node
= new (UniqueInstrAllocator
) UniqueMachineInstr(MI
);
140 void GISelCSEInfo::insertInstr(MachineInstr
*MI
, void *InsertPos
) {
142 // If it exists in temporary insts, remove it.
143 TemporaryInsts
.remove(MI
);
144 auto *Node
= getUniqueInstrForMI(MI
);
145 insertNode(Node
, InsertPos
);
148 MachineInstr
*GISelCSEInfo::getMachineInstrIfExists(FoldingSetNodeID
&ID
,
149 MachineBasicBlock
*MBB
,
151 handleRecordedInsts();
152 if (auto *Inst
= getNodeIfExists(ID
, MBB
, InsertPos
)) {
153 LLVM_DEBUG(dbgs() << "CSEInfo::Found Instr " << *Inst
->MI
;);
154 return const_cast<MachineInstr
*>(Inst
->MI
);
159 void GISelCSEInfo::countOpcodeHit(unsigned Opc
) {
161 if (OpcodeHitTable
.count(Opc
))
162 OpcodeHitTable
[Opc
] += 1;
164 OpcodeHitTable
[Opc
] = 1;
169 void GISelCSEInfo::recordNewInstruction(MachineInstr
*MI
) {
170 if (shouldCSE(MI
->getOpcode())) {
171 TemporaryInsts
.insert(MI
);
172 LLVM_DEBUG(dbgs() << "CSEInfo::Recording new MI " << *MI
);
176 void GISelCSEInfo::handleRecordedInst(MachineInstr
*MI
) {
177 assert(shouldCSE(MI
->getOpcode()) && "Invalid instruction for CSE");
178 auto *UMI
= InstrMapping
.lookup(MI
);
179 LLVM_DEBUG(dbgs() << "CSEInfo::Handling recorded MI " << *MI
);
181 // Invalidate this MI.
182 invalidateUniqueMachineInstr(UMI
);
183 InstrMapping
.erase(MI
);
185 /// Now insert the new instruction.
187 /// We'll reuse the same UniqueMachineInstr to avoid the new
189 *UMI
= UniqueMachineInstr(MI
);
190 insertNode(UMI
, nullptr);
192 /// This is a new instruction. Allocate a new UniqueMachineInstr and
198 void GISelCSEInfo::handleRemoveInst(MachineInstr
*MI
) {
199 if (auto *UMI
= InstrMapping
.lookup(MI
)) {
200 invalidateUniqueMachineInstr(UMI
);
201 InstrMapping
.erase(MI
);
203 TemporaryInsts
.remove(MI
);
206 void GISelCSEInfo::handleRecordedInsts() {
207 while (!TemporaryInsts
.empty()) {
208 auto *MI
= TemporaryInsts
.pop_back_val();
209 handleRecordedInst(MI
);
213 bool GISelCSEInfo::shouldCSE(unsigned Opc
) const {
214 // Only GISel opcodes are CSEable
215 if (!isPreISelGenericOpcode(Opc
))
217 assert(CSEOpt
.get() && "CSEConfig not set");
218 return CSEOpt
->shouldCSEOpc(Opc
);
221 void GISelCSEInfo::erasingInstr(MachineInstr
&MI
) { handleRemoveInst(&MI
); }
222 void GISelCSEInfo::createdInstr(MachineInstr
&MI
) { recordNewInstruction(&MI
); }
223 void GISelCSEInfo::changingInstr(MachineInstr
&MI
) {
224 // For now, perform erase, followed by insert.
228 void GISelCSEInfo::changedInstr(MachineInstr
&MI
) { changingInstr(MI
); }
230 void GISelCSEInfo::analyze(MachineFunction
&MF
) {
232 for (auto &MBB
: MF
) {
235 for (MachineInstr
&MI
: MBB
) {
236 if (!shouldCSE(MI
.getOpcode()))
238 LLVM_DEBUG(dbgs() << "CSEInfo::Add MI: " << MI
);
244 void GISelCSEInfo::releaseMemory() {
247 InstrMapping
.clear();
248 UniqueInstrAllocator
.Reset();
249 TemporaryInsts
.clear();
254 OpcodeHitTable
.clear();
258 void GISelCSEInfo::print() {
259 LLVM_DEBUG(for (auto &It
261 dbgs() << "CSEInfo::CSE Hit for Opc " << It
.first
<< " : " << It
.second
265 /// -----------------------------------------
266 // ---- Profiling methods for FoldingSetNode --- //
267 const GISelInstProfileBuilder
&
268 GISelInstProfileBuilder::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());
277 const GISelInstProfileBuilder
&
278 GISelInstProfileBuilder::addNodeIDOpcode(unsigned Opc
) const {
283 const GISelInstProfileBuilder
&
284 GISelInstProfileBuilder::addNodeIDRegType(const LLT
&Ty
) const {
285 uint64_t Val
= Ty
.getUniqueRAWLLTData();
290 const GISelInstProfileBuilder
&
291 GISelInstProfileBuilder::addNodeIDRegType(const TargetRegisterClass
*RC
) const {
296 const GISelInstProfileBuilder
&
297 GISelInstProfileBuilder::addNodeIDRegType(const RegisterBank
*RB
) const {
302 const GISelInstProfileBuilder
&
303 GISelInstProfileBuilder::addNodeIDImmediate(int64_t Imm
) const {
308 const GISelInstProfileBuilder
&
309 GISelInstProfileBuilder::addNodeIDRegNum(unsigned Reg
) const {
314 const GISelInstProfileBuilder
&
315 GISelInstProfileBuilder::addNodeIDRegType(const unsigned Reg
) const {
316 addNodeIDMachineOperand(MachineOperand::CreateReg(Reg
, false));
320 const GISelInstProfileBuilder
&
321 GISelInstProfileBuilder::addNodeIDMBB(const MachineBasicBlock
*MBB
) const {
326 const GISelInstProfileBuilder
&
327 GISelInstProfileBuilder::addNodeIDFlag(unsigned Flag
) const {
333 const GISelInstProfileBuilder
&GISelInstProfileBuilder::addNodeIDMachineOperand(
334 const MachineOperand
&MO
) const {
336 Register Reg
= MO
.getReg();
338 addNodeIDRegNum(Reg
);
339 LLT Ty
= MRI
.getType(Reg
);
341 addNodeIDRegType(Ty
);
342 auto *RB
= MRI
.getRegBankOrNull(Reg
);
344 addNodeIDRegType(RB
);
345 auto *RC
= MRI
.getRegClassOrNull(Reg
);
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());
358 llvm_unreachable("Unhandled operand type");
359 // Handle other types
364 GISelCSEAnalysisWrapper::get(std::unique_ptr
<CSEConfigBase
> CSEOpt
,
366 if (!AlreadyComputed
|| Recompute
) {
367 Info
.setCSEConfig(std::move(CSEOpt
));
369 AlreadyComputed
= true;
373 void GISelCSEAnalysisWrapperPass::getAnalysisUsage(AnalysisUsage
&AU
) const {
374 AU
.setPreservesAll();
375 MachineFunctionPass::getAnalysisUsage(AU
);
378 bool GISelCSEAnalysisWrapperPass::runOnMachineFunction(MachineFunction
&MF
) {