LLVM 17.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"
24#include "llvm/Support/Debug.h"
25
26#define DEBUG_TYPE "gi-combiner"
27
28using namespace llvm;
29
30namespace llvm {
32 "GlobalISel Combiner",
33 "Control the rules which are enabled. These options all take a comma "
34 "separated list of rules to disable and may be specified by number "
35 "or number range (e.g. 1-10)."
36#ifndef NDEBUG
37 " They may also be specified by name."
38#endif
39);
40} // end namespace llvm
41
42namespace {
43/// This class acts as the glue the joins the CombinerHelper to the overall
44/// Combine algorithm. The CombinerHelper is intended to report the
45/// modifications it makes to the MIR to the GISelChangeObserver and the
46/// observer subclass will act on these events. In this case, instruction
47/// erasure will cancel any future visits to the erased instruction and
48/// instruction creation will schedule that instruction for a future visit.
49/// Other Combiner implementations may require more complex behaviour from
50/// their GISelChangeObserver subclass.
51class WorkListMaintainer : public GISelChangeObserver {
52 using WorkListTy = GISelWorkList<512>;
53 WorkListTy &WorkList;
54 /// The instructions that have been created but we want to report once they
55 /// have their operands. This is only maintained if debug output is requested.
56#ifndef NDEBUG
58#endif
59
60public:
61 WorkListMaintainer(WorkListTy &WorkList) : WorkList(WorkList) {}
62 virtual ~WorkListMaintainer() = default;
63
64 void erasingInstr(MachineInstr &MI) override {
65 LLVM_DEBUG(dbgs() << "Erasing: " << MI << "\n");
66 WorkList.remove(&MI);
67 }
68 void createdInstr(MachineInstr &MI) override {
69 LLVM_DEBUG(dbgs() << "Creating: " << MI << "\n");
70 WorkList.insert(&MI);
71 LLVM_DEBUG(CreatedInstrs.insert(&MI));
72 }
73 void changingInstr(MachineInstr &MI) override {
74 LLVM_DEBUG(dbgs() << "Changing: " << MI << "\n");
75 WorkList.insert(&MI);
76 }
77 void changedInstr(MachineInstr &MI) override {
78 LLVM_DEBUG(dbgs() << "Changed: " << MI << "\n");
79 WorkList.insert(&MI);
80 }
81
82 void reportFullyCreatedInstrs() {
83 LLVM_DEBUG(for (const auto *MI
84 : CreatedInstrs) {
85 dbgs() << "Created: ";
86 MI->print(dbgs());
87 });
88 LLVM_DEBUG(CreatedInstrs.clear());
89 }
90};
91}
92
94 : CInfo(Info), TPC(TPC) {
95 (void)this->TPC; // FIXME: Remove when used.
96}
97
99 GISelCSEInfo *CSEInfo) {
100 // If the ISel pipeline failed, do not bother running this pass.
101 // FIXME: Should this be here or in individual combiner passes.
102 if (MF.getProperties().hasProperty(
104 return false;
105
106 Builder =
107 CSEInfo ? std::make_unique<CSEMIRBuilder>() : std::make_unique<MachineIRBuilder>();
108 MRI = &MF.getRegInfo();
109 Builder->setMF(MF);
110 if (CSEInfo)
111 Builder->setCSEInfo(CSEInfo);
112
113 LLVM_DEBUG(dbgs() << "Generic MI Combiner for: " << MF.getName() << '\n');
114
115 MachineOptimizationRemarkEmitter MORE(MF, /*MBFI=*/nullptr);
116
117 bool MFChanged = false;
118 bool Changed;
120
121 do {
122 // Collect all instructions. Do a post order traversal for basic blocks and
123 // insert with list bottom up, so while we pop_back_val, we'll traverse top
124 // down RPOT.
125 Changed = false;
126 GISelWorkList<512> WorkList;
127 WorkListMaintainer Observer(WorkList);
128 GISelObserverWrapper WrapperObserver(&Observer);
129 if (CSEInfo)
130 WrapperObserver.addObserver(CSEInfo);
131 RAIIDelegateInstaller DelInstall(MF, &WrapperObserver);
132 for (MachineBasicBlock *MBB : post_order(&MF)) {
133 for (MachineInstr &CurMI :
135 // Erase dead insts before even adding to the list.
136 if (isTriviallyDead(CurMI, *MRI)) {
137 LLVM_DEBUG(dbgs() << CurMI << "Is dead; erasing.\n");
139 CurMI.eraseFromParent();
140 continue;
141 }
142 WorkList.deferred_insert(&CurMI);
143 }
144 }
145 WorkList.finalize();
146 // Main Loop. Process the instructions here.
147 while (!WorkList.empty()) {
148 MachineInstr *CurrInst = WorkList.pop_back_val();
149 LLVM_DEBUG(dbgs() << "\nTry combining " << *CurrInst;);
150 Changed |= CInfo.combine(WrapperObserver, *CurrInst, B);
151 Observer.reportFullyCreatedInstrs();
152 }
153 MFChanged |= Changed;
154 } while (Changed);
155
156#ifndef NDEBUG
157 if (CSEInfo) {
158 if (auto E = CSEInfo->verify()) {
159 errs() << E << '\n';
160 assert(false && "CSEInfo is not consistent. Likely missing calls to "
161 "observer on mutations.");
162 }
163 }
164#endif
165 return MFChanged;
166}
MachineBasicBlock & MBB
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Analysis containing CSE Info
Definition: CSEInfo.cpp:27
Provides analysis for continuously CSEing during GISel passes.
This file implements a version of MachineIRBuilder which CSEs insts within a MachineBasicBlock.
Interface for Targets to specify which operations are combined how and when.
This contains common code to drive combines.
#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.
virtual bool combine(GISelChangeObserver &Observer, MachineInstr &MI, MachineIRBuilder &B) const =0
Attempt to combine instructions using MI as the root.
MachineRegisterInfo * MRI
Definition: Combiner.h:38
bool combineMachineInstrs(MachineFunction &MF, GISelCSEInfo *CSEInfo)
If CSEInfo is not null, then the Combiner will setup observer for CSEInfo and instantiate a CSEMIRBui...
Definition: Combiner.cpp:98
std::unique_ptr< MachineIRBuilder > Builder
Definition: Combiner.h:40
CombinerInfo & CInfo
Definition: Combiner.h:36
Combiner(CombinerInfo &CombinerInfo, const TargetPassConfig *TPC)
Definition: Combiner.cpp:93
The CSE Analysis object.
Definition: CSEInfo.h:69
Abstract class that contains various methods for clients to notify about changes.
virtual void changingInstr(MachineInstr &MI)=0
This instruction is about to be mutated in some way.
virtual void changedInstr(MachineInstr &MI)=0
This instruction was mutated in some way.
virtual void createdInstr(MachineInstr &MI)=0
An instruction has been created and inserted into the function.
virtual void erasingInstr(MachineInstr &MI)=0
An instruction is about to be erased.
Simple wrapper observer that takes several observers, and calls each one for each event.
void addObserver(GISelChangeObserver *O)
MachineInstr * pop_back_val()
void deferred_insert(MachineInstr *I)
Definition: GISelWorkList.h:50
bool empty() const
Definition: GISelWorkList.h:38
bool hasProperty(Property P) const
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const MachineFunctionProperties & getProperties() const
Get the function properties.
Helper class to build MachineInstr.
Representation of each machine instruction.
Definition: MachineInstr.h:68
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:51
bool insert(const value_type &X)
Insert a new element into the SetVector.
Definition: SetVector.h:152
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:1364
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:748
iterator_range< po_iterator< T > > post_order(const T &G)
auto reverse(ContainerTy &&C)
Definition: STLExtras.h:511
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:212
#define MORE()
Definition: regcomp.c:252
#define NDEBUG
Definition: regutils.h:48