LLVM  16.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 
23 #include "llvm/Support/Debug.h"
24 
25 #define DEBUG_TYPE "gi-combiner"
26 
27 using namespace llvm;
28 
29 namespace llvm {
31  "GlobalISel Combiner",
32  "Control the rules which are enabled. These options all take a comma "
33  "separated list of rules to disable and may be specified by number "
34  "or number range (e.g. 1-10)."
35 #ifndef NDEBUG
36  " They may also be specified by name."
37 #endif
38 );
39 } // end namespace llvm
40 
41 namespace {
42 /// This class acts as the glue the joins the CombinerHelper to the overall
43 /// Combine algorithm. The CombinerHelper is intended to report the
44 /// modifications it makes to the MIR to the GISelChangeObserver and the
45 /// observer subclass will act on these events. In this case, instruction
46 /// erasure will cancel any future visits to the erased instruction and
47 /// instruction creation will schedule that instruction for a future visit.
48 /// Other Combiner implementations may require more complex behaviour from
49 /// their GISelChangeObserver subclass.
50 class WorkListMaintainer : public GISelChangeObserver {
51  using WorkListTy = GISelWorkList<512>;
52  WorkListTy &WorkList;
53  /// The instructions that have been created but we want to report once they
54  /// have their operands. This is only maintained if debug output is requested.
56 
57 public:
58  WorkListMaintainer(WorkListTy &WorkList) : WorkList(WorkList) {}
59  virtual ~WorkListMaintainer() = default;
60 
61  void erasingInstr(MachineInstr &MI) override {
62  LLVM_DEBUG(dbgs() << "Erasing: " << MI << "\n");
63  WorkList.remove(&MI);
64  }
65  void createdInstr(MachineInstr &MI) override {
66  LLVM_DEBUG(dbgs() << "Creating: " << MI << "\n");
67  WorkList.insert(&MI);
68  LLVM_DEBUG(CreatedInstrs.insert(&MI));
69  }
70  void changingInstr(MachineInstr &MI) override {
71  LLVM_DEBUG(dbgs() << "Changing: " << MI << "\n");
72  WorkList.insert(&MI);
73  }
74  void changedInstr(MachineInstr &MI) override {
75  LLVM_DEBUG(dbgs() << "Changed: " << MI << "\n");
76  WorkList.insert(&MI);
77  }
78 
79  void reportFullyCreatedInstrs() {
80  LLVM_DEBUG(for (const auto *MI
81  : CreatedInstrs) {
82  dbgs() << "Created: ";
83  MI->print(dbgs());
84  });
85  LLVM_DEBUG(CreatedInstrs.clear());
86  }
87 };
88 }
89 
91  : CInfo(Info), TPC(TPC) {
92  (void)this->TPC; // FIXME: Remove when used.
93 }
94 
96  GISelCSEInfo *CSEInfo) {
97  // If the ISel pipeline failed, do not bother running this pass.
98  // FIXME: Should this be here or in individual combiner passes.
99  if (MF.getProperties().hasProperty(
101  return false;
102 
103  Builder =
104  CSEInfo ? std::make_unique<CSEMIRBuilder>() : std::make_unique<MachineIRBuilder>();
105  MRI = &MF.getRegInfo();
106  Builder->setMF(MF);
107  if (CSEInfo)
108  Builder->setCSEInfo(CSEInfo);
109 
110  LLVM_DEBUG(dbgs() << "Generic MI Combiner for: " << MF.getName() << '\n');
111 
112  MachineOptimizationRemarkEmitter MORE(MF, /*MBFI=*/nullptr);
113 
114  bool MFChanged = false;
115  bool Changed;
117 
118  do {
119  // Collect all instructions. Do a post order traversal for basic blocks and
120  // insert with list bottom up, so while we pop_back_val, we'll traverse top
121  // down RPOT.
122  Changed = false;
123  GISelWorkList<512> WorkList;
124  WorkListMaintainer Observer(WorkList);
125  GISelObserverWrapper WrapperObserver(&Observer);
126  if (CSEInfo)
127  WrapperObserver.addObserver(CSEInfo);
128  RAIIDelegateInstaller DelInstall(MF, &WrapperObserver);
129  for (MachineBasicBlock *MBB : post_order(&MF)) {
130  for (MachineInstr &CurMI :
132  // Erase dead insts before even adding to the list.
133  if (isTriviallyDead(CurMI, *MRI)) {
134  LLVM_DEBUG(dbgs() << CurMI << "Is dead; erasing.\n");
135  llvm::salvageDebugInfo(*MRI, CurMI);
136  CurMI.eraseFromParent();
137  continue;
138  }
139  WorkList.deferred_insert(&CurMI);
140  }
141  }
142  WorkList.finalize();
143  // Main Loop. Process the instructions here.
144  while (!WorkList.empty()) {
145  MachineInstr *CurrInst = WorkList.pop_back_val();
146  LLVM_DEBUG(dbgs() << "\nTry combining " << *CurrInst;);
147  Changed |= CInfo.combine(WrapperObserver, *CurrInst, B);
148  Observer.reportFullyCreatedInstrs();
149  }
150  MFChanged |= Changed;
151  } while (Changed);
152 
153 #ifndef NDEBUG
154  if (CSEInfo) {
155  if (auto E = CSEInfo->verify()) {
156  errs() << E << '\n';
157  assert(false && "CSEInfo is not consistent. Likely missing calls to "
158  "observer on mutations.");
159  }
160  }
161 #endif
162  return MFChanged;
163 }
CombinerInfo.h
llvm::MachineFunctionProperties::hasProperty
bool hasProperty(Property P) const
Definition: MachineFunction.h:192
MI
IRTranslator LLVM IR MI
Definition: IRTranslator.cpp:109
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
llvm::GISelWorkList::deferred_insert
void deferred_insert(MachineInstr *I)
Definition: GISelWorkList.h:50
llvm::GISelCSEInfo
The CSE Analysis object.
Definition: CSEInfo.h:69
llvm::Combiner::Builder
std::unique_ptr< MachineIRBuilder > Builder
Definition: Combiner.h:40
llvm::MachineOptimizationRemarkEmitter
The optimization diagnostic interface.
Definition: MachineOptimizationRemarkEmitter.h:151
llvm::SmallPtrSet
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
Definition: SmallPtrSet.h:450
llvm::CombinerInfo::combine
virtual bool combine(GISelChangeObserver &Observer, MachineInstr &MI, MachineIRBuilder &B) const =0
Attempt to combine instructions using MI as the root.
llvm::errs
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
Definition: raw_ostream.cpp:891
MachineIRBuilder.h
llvm::CombinerInfo
Definition: CombinerInfo.h:26
endif
__FakeVCSRevision h endif() endif() set(generated_files "$
Definition: CMakeLists.txt:16
LLVM_DEBUG
#define LLVM_DEBUG(X)
Definition: Debug.h:101
llvm::dbgs
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
CSEInfo.h
llvm::MachineFunction::getRegInfo
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Definition: MachineFunction.h:667
llvm::RAIIDelegateInstaller
A simple RAII based Delegate installer.
Definition: GISelChangeObserver.h:108
E
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Utils.h
llvm::MachineFunction::getProperties
const MachineFunctionProperties & getProperties() const
Get the function properties.
Definition: MachineFunction.h:748
CSEMIRBuilder.h
B
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
llvm::Combiner::MRI
MachineRegisterInfo * MRI
Definition: Combiner.h:38
llvm::salvageDebugInfo
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:1361
Info
Analysis containing CSE Info
Definition: CSEInfo.cpp:27
llvm::MachineBasicBlock
Definition: MachineBasicBlock.h:94
llvm::Pass::print
virtual void print(raw_ostream &OS, const Module *M) const
print - Print out the internal state of the pass.
Definition: Pass.cpp:130
MachineOptimizationRemarkEmitter.h
===- MachineOptimizationRemarkEmitter.h - Opt Diagnostics -*- C++ -*-—===//
llvm::TargetPassConfig
Target-Independent Code Generator Pass Configuration Options.
Definition: TargetPassConfig.h:84
llvm::MachineIRBuilder
Helper class to build MachineInstr.
Definition: MachineIRBuilder.h:221
llvm::MachineInstr
Representation of each machine instruction.
Definition: MachineInstr.h:66
llvm::make_early_inc_range
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:716
llvm::MachineFunction::getName
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
Definition: MachineFunction.cpp:567
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
NDEBUG
#define NDEBUG
Definition: regutils.h:48
llvm::isTriviallyDead
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:213
llvm::GICombinerOptionCategory
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.")
llvm::MachineFunction
Definition: MachineFunction.h:257
llvm::GISelWorkList::pop_back_val
MachineInstr * pop_back_val()
Definition: GISelWorkList.h:102
Combiner.h
llvm::GISelChangeObserver
Abstract class that contains various methods for clients to notify about changes.
Definition: GISelChangeObserver.h:29
MORE
#define MORE()
Definition: regcomp.c:252
GISelWorkList.h
MBB
MachineBasicBlock & MBB
Definition: AArch64SLSHardening.cpp:74
llvm::MachineFunctionProperties::Property::FailedISel
@ FailedISel
llvm::post_order
iterator_range< po_iterator< T > > post_order(const T &G)
Definition: PostOrderIterator.h:189
llvm::GISelCSEInfo::verify
Error verify()
Definition: CSEInfo.cpp:272
PostOrderIterator.h
llvm::Combiner::Combiner
Combiner(CombinerInfo &CombinerInfo, const TargetPassConfig *TPC)
Definition: Combiner.cpp:90
llvm::GISelWorkList
Definition: GISelWorkList.h:27
llvm::GISelObserverWrapper::addObserver
void addObserver(GISelChangeObserver *O)
Definition: GISelChangeObserver.h:75
llvm::reverse
auto reverse(ContainerTy &&C)
Definition: STLExtras.h:485
llvm::GISelObserverWrapper
Simple wrapper observer that takes several observers, and calls each one for each event.
Definition: GISelChangeObserver.h:66
llvm::Combiner::combineMachineInstrs
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:95
GISelChangeObserver.h
llvm::Combiner::CInfo
CombinerInfo & CInfo
Definition: Combiner.h:36
llvm::GISelWorkList::empty
bool empty() const
Definition: GISelWorkList.h:38
Debug.h
llvm::SmallPtrSetImpl::insert
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
Definition: SmallPtrSet.h:365
llvm::GISelWorkList::finalize
void finalize()
Definition: GISelWorkList.h:61
llvm::cl::OptionCategory
Definition: CommandLine.h:181