LLVM 19.0.0git
Combiner.cpp
Go to the documentation of this file.
1//===-- lib/CodeGen/GlobalISel/Combiner.cpp -------------------------------===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8//
9// This file constains common code to combine machine functions at generic
10// level.
11//===----------------------------------------------------------------------===//
12
15#include "llvm/ADT/SetVector.h"
16#include "llvm/ADT/Statistic.h"
25#include "llvm/Support/Debug.h"
26
27#define DEBUG_TYPE "gi-combiner"
28
29using namespace llvm;
30
31STATISTIC(NumOneIteration, "Number of functions with one iteration");
32STATISTIC(NumTwoIterations, "Number of functions with two iterations");
33STATISTIC(NumThreeOrMoreIterations,
34 "Number of functions with three or more iterations");
35
36namespace llvm {
38 "GlobalISel Combiner",
39 "Control the rules which are enabled. These options all take a comma "
40 "separated list of rules to disable and may be specified by number "
41 "or number range (e.g. 1-10)."
42#ifndef NDEBUG
43 " They may also be specified by name."
44#endif
45);
46} // end namespace llvm
47
48/// This class acts as the glue the joins the CombinerHelper to the overall
49/// Combine algorithm. The CombinerHelper is intended to report the
50/// modifications it makes to the MIR to the GISelChangeObserver and the
51/// observer subclass will act on these events. In this case, instruction
52/// erasure will cancel any future visits to the erased instruction and
53/// instruction creation will schedule that instruction for a future visit.
54/// Other Combiner implementations may require more complex behaviour from
55/// their GISelChangeObserver subclass.
58 WorkListTy &WorkList;
59 /// The instructions that have been created but we want to report once they
60 /// have their operands. This is only maintained if debug output is requested.
61#ifndef NDEBUG
63#endif
64
65public:
66 WorkListMaintainer(WorkListTy &WorkList) : WorkList(WorkList) {}
67 virtual ~WorkListMaintainer() = default;
68
69 void erasingInstr(MachineInstr &MI) override {
70 LLVM_DEBUG(dbgs() << "Erasing: " << MI << "\n");
71 WorkList.remove(&MI);
72 }
73 void createdInstr(MachineInstr &MI) override {
74 LLVM_DEBUG(dbgs() << "Creating: " << MI << "\n");
75 WorkList.insert(&MI);
76 LLVM_DEBUG(CreatedInstrs.insert(&MI));
77 }
78 void changingInstr(MachineInstr &MI) override {
79 LLVM_DEBUG(dbgs() << "Changing: " << MI << "\n");
80 WorkList.insert(&MI);
81 }
82 void changedInstr(MachineInstr &MI) override {
83 LLVM_DEBUG(dbgs() << "Changed: " << MI << "\n");
84 WorkList.insert(&MI);
85 }
86
88 LLVM_DEBUG(for (const auto *MI
89 : CreatedInstrs) {
90 dbgs() << "Created: ";
91 MI->print(dbgs());
92 });
93 LLVM_DEBUG(CreatedInstrs.clear());
94 }
95};
96
98 const TargetPassConfig *TPC, GISelKnownBits *KB,
99 GISelCSEInfo *CSEInfo)
100 : Builder(CSEInfo ? std::make_unique<CSEMIRBuilder>()
101 : std::make_unique<MachineIRBuilder>()),
102 WLObserver(std::make_unique<WorkListMaintainer>(WorkList)),
103 ObserverWrapper(std::make_unique<GISelObserverWrapper>()), CInfo(CInfo),
104 Observer(*ObserverWrapper), B(*Builder), MF(MF), MRI(MF.getRegInfo()),
105 KB(KB), TPC(TPC), CSEInfo(CSEInfo) {
106 (void)this->TPC; // FIXME: Remove when used.
107
108 // Setup builder.
109 B.setMF(MF);
110 if (CSEInfo)
112
113 // Setup observer.
114 ObserverWrapper->addObserver(WLObserver.get());
115 if (CSEInfo)
116 ObserverWrapper->addObserver(CSEInfo);
117
118 B.setChangeObserver(*ObserverWrapper);
119}
120
121Combiner::~Combiner() = default;
122
124 // If the ISel pipeline failed, do not bother running this pass.
125 // FIXME: Should this be here or in individual combiner passes.
128 return false;
129
130 // We can't call this in the constructor because the derived class is
131 // uninitialized at that time.
132 if (!HasSetupMF) {
133 HasSetupMF = true;
134 setupMF(MF, KB);
135 }
136
137 LLVM_DEBUG(dbgs() << "Generic MI Combiner for: " << MF.getName() << '\n');
138
139 MachineOptimizationRemarkEmitter MORE(MF, /*MBFI=*/nullptr);
140
141 bool MFChanged = false;
142 bool Changed;
143
144 unsigned Iteration = 0;
145 while (true) {
146 ++Iteration;
147 LLVM_DEBUG(dbgs() << "\n\nCombiner iteration #" << Iteration << '\n');
148
149 WorkList.clear();
150
151 // Collect all instructions. Do a post order traversal for basic blocks and
152 // insert with list bottom up, so while we pop_back_val, we'll traverse top
153 // down RPOT.
154 Changed = false;
155
156 RAIIDelegateInstaller DelInstall(MF, ObserverWrapper.get());
158 for (MachineInstr &CurMI :
160 // Erase dead insts before even adding to the list.
161 if (isTriviallyDead(CurMI, MRI)) {
162 LLVM_DEBUG(dbgs() << CurMI << "Is dead; erasing.\n");
164 CurMI.eraseFromParent();
165 continue;
166 }
167 WorkList.deferred_insert(&CurMI);
168 }
169 }
170 WorkList.finalize();
171 // Main Loop. Process the instructions here.
172 while (!WorkList.empty()) {
173 MachineInstr *CurrInst = WorkList.pop_back_val();
174 LLVM_DEBUG(dbgs() << "\nTry combining " << *CurrInst;);
175 Changed |= tryCombineAll(*CurrInst);
176 WLObserver->reportFullyCreatedInstrs();
177 }
178 MFChanged |= Changed;
179
180 if (!Changed) {
181 LLVM_DEBUG(dbgs() << "\nCombiner reached fixed-point after iteration #"
182 << Iteration << '\n');
183 break;
184 }
185 // Iterate until a fixed-point is reached if MaxIterations == 0,
186 // otherwise limit the number of iterations.
187 if (CInfo.MaxIterations && Iteration >= CInfo.MaxIterations) {
189 dbgs() << "\nCombiner reached iteration limit after iteration #"
190 << Iteration << '\n');
191 break;
192 }
193 }
194
195 if (Iteration == 1)
196 ++NumOneIteration;
197 else if (Iteration == 2)
198 ++NumTwoIterations;
199 else
200 ++NumThreeOrMoreIterations;
201
202#ifndef NDEBUG
203 if (CSEInfo) {
204 if (auto E = CSEInfo->verify()) {
205 errs() << E << '\n';
206 assert(false && "CSEInfo is not consistent. Likely missing calls to "
207 "observer on mutations.");
208 }
209 }
210#endif
211 return MFChanged;
212}
unsigned const MachineRegisterInfo * MRI
MachineBasicBlock & MBB
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Provides analysis for continuously CSEing during GISel passes.
This file implements a version of MachineIRBuilder which CSEs insts within a MachineBasicBlock.
Option class for Targets to specify which operations are combined how and when.
This contains the base class for all Combiners generated by TableGen.
#define LLVM_DEBUG(X)
Definition: Debug.h:101
This contains common code to allow clients to notify changes to machine instr.
IRTranslator LLVM IR MI
This file declares the MachineIRBuilder class.
===- MachineOptimizationRemarkEmitter.h - Opt Diagnostics -*- C++ -*-—===//
This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file implements a set that has insertion order iteration characteristics.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition: Statistic.h:167
This class acts as the glue the joins the CombinerHelper to the overall Combine algorithm.
Definition: Combiner.cpp:56
void changingInstr(MachineInstr &MI) override
This instruction is about to be mutated in some way.
Definition: Combiner.cpp:78
void changedInstr(MachineInstr &MI) override
This instruction was mutated in some way.
Definition: Combiner.cpp:82
void erasingInstr(MachineInstr &MI) override
An instruction is about to be erased.
Definition: Combiner.cpp:69
virtual ~WorkListMaintainer()=default
void createdInstr(MachineInstr &MI) override
An instruction has been created and inserted into the function.
Definition: Combiner.cpp:73
WorkListMaintainer(WorkListTy &WorkList)
Definition: Combiner.cpp:66
Defines a builder that does CSE of MachineInstructions using GISelCSEInfo.
Definition: CSEMIRBuilder.h:32
GISelCSEInfo * CSEInfo
Definition: Combiner.h:72
Combiner(MachineFunction &MF, CombinerInfo &CInfo, const TargetPassConfig *TPC, GISelKnownBits *KB, GISelCSEInfo *CSEInfo=nullptr)
If CSEInfo is not null, then the Combiner will use CSEInfo as the observer and also create a CSEMIRBu...
Definition: Combiner.cpp:97
bool combineMachineInstrs()
Definition: Combiner.cpp:123
MachineRegisterInfo & MRI
Definition: Combiner.h:68
virtual ~Combiner()
MachineIRBuilder & B
Definition: Combiner.h:66
GISelKnownBits * KB
Definition: Combiner.h:69
MachineFunction & MF
Definition: Combiner.h:67
CombinerInfo & CInfo
Definition: Combiner.h:64
virtual bool tryCombineAll(MachineInstr &I) const =0
virtual void setupMF(MachineFunction &mf, GISelKnownBits *kb, CodeGenCoverage *covinfo=nullptr, ProfileSummaryInfo *psi=nullptr, BlockFrequencyInfo *bfi=nullptr)
Setup per-MF executor state.
The CSE Analysis object.
Definition: CSEInfo.h:69
Abstract class that contains various methods for clients to notify about changes.
Simple wrapper observer that takes several observers, and calls each one for each event.
void insert(MachineInstr *I)
Add the specified instruction to the worklist if it isn't already in it.
Definition: GISelWorkList.h:74
MachineInstr * pop_back_val()
void deferred_insert(MachineInstr *I)
Definition: GISelWorkList.h:50
bool empty() const
Definition: GISelWorkList.h:38
void remove(const MachineInstr *I)
Remove I from the worklist if it exists.
Definition: GISelWorkList.h:83
bool hasProperty(Property P) const
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
const MachineFunctionProperties & getProperties() const
Get the function properties.
Helper class to build MachineInstr.
void setCSEInfo(GISelCSEInfo *Info)
void setMF(MachineFunction &MF)
void setChangeObserver(GISelChangeObserver &Observer)
Representation of each machine instruction.
Definition: MachineInstr.h:69
virtual void print(raw_ostream &OS, const Module *M) const
print - Print out the internal state of the pass.
Definition: Pass.cpp:130
A simple RAII based Delegate installer.
A vector that has set insertion semantics.
Definition: SetVector.h:57
bool insert(const value_type &X)
Insert a new element into the SetVector.
Definition: SetVector.h:162
Target-Independent Code Generator Pass Configuration Options.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
void salvageDebugInfo(const MachineRegisterInfo &MRI, MachineInstr &MI)
Assuming the instruction MI is going to be deleted, attempt to salvage debug users of MI by writing t...
Definition: Utils.cpp:1665
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Definition: STLExtras.h:656
iterator_range< po_iterator< T > > post_order(const T &G)
auto reverse(ContainerTy &&C)
Definition: STLExtras.h:419
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
cl::OptionCategory GICombinerOptionCategory("GlobalISel Combiner", "Control the rules which are enabled. These options all take a comma " "separated list of rules to disable and may be specified by number " "or number range (e.g. 1-10)." " They may also be specified by name.")
bool isTriviallyDead(const MachineInstr &MI, const MachineRegisterInfo &MRI)
Check whether an instruction MI is dead: it only defines dead virtual registers, and doesn't have oth...
Definition: Utils.cpp:222
Implement std::hash so that hash_code can be used in STL containers.
Definition: BitVector.h:858
#define MORE()
Definition: regcomp.c:252
#define NDEBUG
Definition: regutils.h:48
unsigned MaxIterations
The maximum number of times the Combiner will iterate over the MachineFunction.
Definition: CombinerInfo.h:55