LLVM  9.0.0svn
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 
24 #include "llvm/Support/Debug.h"
25 
26 #define DEBUG_TYPE "gi-combiner"
27 
28 using namespace llvm;
29 
30 namespace {
31 /// This class acts as the glue the joins the CombinerHelper to the overall
32 /// Combine algorithm. The CombinerHelper is intended to report the
33 /// modifications it makes to the MIR to the GISelChangeObserver and the
34 /// observer subclass will act on these events. In this case, instruction
35 /// erasure will cancel any future visits to the erased instruction and
36 /// instruction creation will schedule that instruction for a future visit.
37 /// Other Combiner implementations may require more complex behaviour from
38 /// their GISelChangeObserver subclass.
39 class WorkListMaintainer : public GISelChangeObserver {
40  using WorkListTy = GISelWorkList<512>;
41  WorkListTy &WorkList;
42  /// The instructions that have been created but we want to report once they
43  /// have their operands. This is only maintained if debug output is requested.
45 
46 public:
47  WorkListMaintainer(WorkListTy &WorkList)
48  : GISelChangeObserver(), WorkList(WorkList) {}
49  virtual ~WorkListMaintainer() {
50  }
51 
52  void erasingInstr(MachineInstr &MI) override {
53  LLVM_DEBUG(dbgs() << "Erasing: " << MI << "\n");
54  WorkList.remove(&MI);
55  }
56  void createdInstr(MachineInstr &MI) override {
57  LLVM_DEBUG(dbgs() << "Creating: " << MI << "\n");
58  WorkList.insert(&MI);
59  LLVM_DEBUG(CreatedInstrs.insert(&MI));
60  }
61  void changingInstr(MachineInstr &MI) override {
62  LLVM_DEBUG(dbgs() << "Changing: " << MI << "\n");
63  WorkList.insert(&MI);
64  }
65  void changedInstr(MachineInstr &MI) override {
66  LLVM_DEBUG(dbgs() << "Changed: " << MI << "\n");
67  WorkList.insert(&MI);
68  }
69 
70  void reportFullyCreatedInstrs() {
71  LLVM_DEBUG(for (const auto *MI
72  : CreatedInstrs) {
73  dbgs() << "Created: ";
74  MI->print(dbgs());
75  });
76  LLVM_DEBUG(CreatedInstrs.clear());
77  }
78 };
79 }
80 
82  : CInfo(Info), TPC(TPC) {
83  (void)this->TPC; // FIXME: Remove when used.
84 }
85 
87  GISelCSEInfo *CSEInfo) {
88  // If the ISel pipeline failed, do not bother running this pass.
89  // FIXME: Should this be here or in individual combiner passes.
90  if (MF.getProperties().hasProperty(
92  return false;
93 
94  Builder =
95  CSEInfo ? make_unique<CSEMIRBuilder>() : make_unique<MachineIRBuilder>();
96  MRI = &MF.getRegInfo();
97  Builder->setMF(MF);
98  if (CSEInfo)
99  Builder->setCSEInfo(CSEInfo);
100 
101  LLVM_DEBUG(dbgs() << "Generic MI Combiner for: " << MF.getName() << '\n');
102 
103  MachineOptimizationRemarkEmitter MORE(MF, /*MBFI=*/nullptr);
104 
105  bool MFChanged = false;
106  bool Changed;
107  MachineIRBuilder &B = *Builder.get();
108 
109  do {
110  // Collect all instructions. Do a post order traversal for basic blocks and
111  // insert with list bottom up, so while we pop_back_val, we'll traverse top
112  // down RPOT.
113  Changed = false;
114  GISelWorkList<512> WorkList;
115  WorkListMaintainer Observer(WorkList);
116  GISelObserverWrapper WrapperObserver(&Observer);
117  if (CSEInfo)
118  WrapperObserver.addObserver(CSEInfo);
119  RAIIDelegateInstaller DelInstall(MF, &WrapperObserver);
120  for (MachineBasicBlock *MBB : post_order(&MF)) {
121  if (MBB->empty())
122  continue;
123  for (auto MII = MBB->rbegin(), MIE = MBB->rend(); MII != MIE;) {
124  MachineInstr *CurMI = &*MII;
125  ++MII;
126  // Erase dead insts before even adding to the list.
127  if (isTriviallyDead(*CurMI, *MRI)) {
128  LLVM_DEBUG(dbgs() << *CurMI << "Is dead; erasing.\n");
130  continue;
131  }
132  WorkList.deferred_insert(CurMI);
133  }
134  }
135  WorkList.finalize();
136  // Main Loop. Process the instructions here.
137  while (!WorkList.empty()) {
138  MachineInstr *CurrInst = WorkList.pop_back_val();
139  LLVM_DEBUG(dbgs() << "\nTry combining " << *CurrInst;);
140  Changed |= CInfo.combine(WrapperObserver, *CurrInst, B);
141  Observer.reportFullyCreatedInstrs();
142  }
143  MFChanged |= Changed;
144  } while (Changed);
145 
146  return MFChanged;
147 }
A simple RAII based CSEInfo installer.
The CSE Analysis object.
Definition: CSEInfo.h:71
void deferred_insert(MachineInstr *I)
Definition: GISelWorkList.h:54
This class represents lattice values for constants.
Definition: AllocatorList.h:23
const MachineFunctionProperties & getProperties() const
Get the function properties.
bool empty() const
Definition: GISelWorkList.h:42
Combiner(CombinerInfo &CombinerInfo, const TargetPassConfig *TPC)
Definition: Combiner.cpp:81
virtual bool combine(GISelChangeObserver &Observer, MachineInstr &MI, MachineIRBuilder &B) const =0
Attempt to combine instructions using MI as the root.
Target-Independent Code Generator Pass Configuration Options.
void eraseFromParentAndMarkDBGValuesForRemoval()
Unlink &#39;this&#39; from the containing basic block and delete it.
Analysis containing CSE Info
Definition: CSEInfo.cpp:20
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
===- MachineOptimizationRemarkEmitter.h - Opt Diagnostics -*- C++ -*-—===//
Abstract class that contains various methods for clients to notify about changes. ...
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
CombinerInfo & CInfo
Definition: Combiner.h:37
This file implements a version of MachineIRBuilder which CSEs insts within a MachineBasicBlock.
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:370
Helper class to build MachineInstr.
iterator_range< po_iterator< T > > post_order(const T &G)
void print(raw_ostream &OS, bool IsStandalone=true, bool SkipOpers=false, bool SkipDebugLoc=false, bool AddNewLine=true, const TargetInstrInfo *TII=nullptr) const
Print this MI to OS.
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:86
std::unique_ptr< MachineIRBuilder > Builder
Definition: Combiner.h:41
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements...
Definition: SmallPtrSet.h:417
The optimization diagnostic interface.
#define MORE()
Definition: regcomp.c:251
MachineInstr * pop_back_val()
This file declares the MachineIRBuilder class.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:132
MachineRegisterInfo * MRI
Definition: Combiner.h:39
bool isTriviallyDead(const MachineInstr &MI, const MachineRegisterInfo &MRI)
Check whether an instruction MI is dead: it only defines dead virtual registers, and doesn&#39;t have oth...
Definition: Utils.cpp:160
Representation of each machine instruction.
Definition: MachineInstr.h:63
void addObserver(GISelChangeObserver *O)
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
bool hasProperty(Property P) const
IRTranslator LLVM IR MI
Simple wrapper observer that takes several observers, and calls each one for each event...
#define LLVM_DEBUG(X)
Definition: Debug.h:122