LLVM 18.0.0git
Localizer.cpp
Go to the documentation of this file.
1//===- Localizer.cpp ---------------------- Localize some instrs -*- C++ -*-==//
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/// \file
9/// This file implements the Localizer class.
10//===----------------------------------------------------------------------===//
11
13#include "llvm/ADT/DenseMap.h"
14#include "llvm/ADT/STLExtras.h"
20#include "llvm/Support/Debug.h"
21
22#define DEBUG_TYPE "localizer"
23
24using namespace llvm;
25
26char Localizer::ID = 0;
28 "Move/duplicate certain instructions close to their use",
29 false, false)
32 "Move/duplicate certain instructions close to their use",
34
36 : MachineFunctionPass(ID), DoNotRunPass(F) {}
37
39 : Localizer([](const MachineFunction &) { return false; }) {}
40
41void Localizer::init(MachineFunction &MF) {
42 MRI = &MF.getRegInfo();
43 TTI = &getAnalysis<TargetTransformInfoWrapperPass>().getTTI(MF.getFunction());
44}
45
50}
51
52bool Localizer::isLocalUse(MachineOperand &MOUse, const MachineInstr &Def,
53 MachineBasicBlock *&InsertMBB) {
54 MachineInstr &MIUse = *MOUse.getParent();
55 InsertMBB = MIUse.getParent();
56 if (MIUse.isPHI())
57 InsertMBB = MIUse.getOperand(MOUse.getOperandNo() + 1).getMBB();
58 return InsertMBB == Def.getParent();
59}
60
61bool Localizer::isNonUniquePhiValue(MachineOperand &Op) const {
62 MachineInstr *MI = Op.getParent();
63 if (!MI->isPHI())
64 return false;
65
66 Register SrcReg = Op.getReg();
67 for (unsigned Idx = 1; Idx < MI->getNumOperands(); Idx += 2) {
68 auto &MO = MI->getOperand(Idx);
69 if (&MO != &Op && MO.isReg() && MO.getReg() == SrcReg)
70 return true;
71 }
72 return false;
73}
74
75bool Localizer::localizeInterBlock(MachineFunction &MF,
76 LocalizedSetVecT &LocalizedInstrs) {
77 bool Changed = false;
79
80 // Since the IRTranslator only emits constants into the entry block, and the
81 // rest of the GISel pipeline generally emits constants close to their users,
82 // we only localize instructions in the entry block here. This might change if
83 // we start doing CSE across blocks.
84 auto &MBB = MF.front();
85 auto &TL = *MF.getSubtarget().getTargetLowering();
87 if (!TL.shouldLocalize(MI, TTI))
88 continue;
89 LLVM_DEBUG(dbgs() << "Should localize: " << MI);
90 assert(MI.getDesc().getNumDefs() == 1 &&
91 "More than one definition not supported yet");
92 Register Reg = MI.getOperand(0).getReg();
93 // Check if all the users of MI are local.
94 // We are going to invalidation the list of use operands, so we
95 // can't use range iterator.
96 for (MachineOperand &MOUse :
98 // Check if the use is already local.
99 MachineBasicBlock *InsertMBB;
100 LLVM_DEBUG(MachineInstr &MIUse = *MOUse.getParent();
101 dbgs() << "Checking use: " << MIUse
102 << " #Opd: " << MOUse.getOperandNo() << '\n');
103 if (isLocalUse(MOUse, MI, InsertMBB)) {
104 // Even if we're in the same block, if the block is very large we could
105 // still have many long live ranges. Try to do intra-block localization
106 // too.
107 LocalizedInstrs.insert(&MI);
108 continue;
109 }
110
111 // If the use is a phi operand that's not unique, don't try to localize.
112 // If we do, we can cause unnecessary instruction bloat by duplicating
113 // into each predecessor block, when the existing one is sufficient and
114 // allows for easier optimization later.
115 if (isNonUniquePhiValue(MOUse))
116 continue;
117
118 LLVM_DEBUG(dbgs() << "Fixing non-local use\n");
119 Changed = true;
120 auto MBBAndReg = std::make_pair(InsertMBB, Reg);
121 auto NewVRegIt = MBBWithLocalDef.find(MBBAndReg);
122 if (NewVRegIt == MBBWithLocalDef.end()) {
123 // Create the localized instruction.
124 MachineInstr *LocalizedMI = MF.CloneMachineInstr(&MI);
125 LocalizedInstrs.insert(LocalizedMI);
126 MachineInstr &UseMI = *MOUse.getParent();
127 if (MRI->hasOneUse(Reg) && !UseMI.isPHI())
128 InsertMBB->insert(UseMI, LocalizedMI);
129 else
130 InsertMBB->insert(InsertMBB->SkipPHIsAndLabels(InsertMBB->begin()),
131 LocalizedMI);
132
133 // Set a new register for the definition.
134 Register NewReg = MRI->cloneVirtualRegister(Reg);
135 LocalizedMI->getOperand(0).setReg(NewReg);
136 NewVRegIt =
137 MBBWithLocalDef.insert(std::make_pair(MBBAndReg, NewReg)).first;
138 LLVM_DEBUG(dbgs() << "Inserted: " << *LocalizedMI);
139 }
140 LLVM_DEBUG(dbgs() << "Update use with: " << printReg(NewVRegIt->second)
141 << '\n');
142 // Update the user reg.
143 MOUse.setReg(NewVRegIt->second);
144 }
145 }
146 return Changed;
147}
148
149bool Localizer::localizeIntraBlock(LocalizedSetVecT &LocalizedInstrs) {
150 bool Changed = false;
151
152 // For each already-localized instruction which has multiple users, then we
153 // scan the block top down from the current position until we hit one of them.
154
155 // FIXME: Consider doing inst duplication if live ranges are very long due to
156 // many users, but this case may be better served by regalloc improvements.
157
158 for (MachineInstr *MI : LocalizedInstrs) {
159 Register Reg = MI->getOperand(0).getReg();
160 MachineBasicBlock &MBB = *MI->getParent();
161 // All of the user MIs of this reg.
163 for (MachineInstr &UseMI : MRI->use_nodbg_instructions(Reg)) {
164 if (!UseMI.isPHI())
165 Users.insert(&UseMI);
166 }
167 // If all the users were PHIs then they're not going to be in our block,
168 // don't try to move this instruction.
169 if (Users.empty())
170 continue;
171
173 ++II;
174 while (II != MBB.end() && !Users.count(&*II))
175 ++II;
176
177 assert(II != MBB.end() && "Didn't find the user in the MBB");
178 LLVM_DEBUG(dbgs() << "Intra-block: moving " << *MI << " before " << *II
179 << '\n');
180
181 MI->removeFromParent();
182 MBB.insert(II, MI);
183 Changed = true;
184
185 // If the instruction (constant) being localized has single user, we can
186 // propagate debug location from user.
187 if (Users.size() == 1) {
188 const auto &DefDL = MI->getDebugLoc();
189 const auto &UserDL = (*Users.begin())->getDebugLoc();
190
191 if ((!DefDL || DefDL.getLine() == 0) && UserDL && UserDL.getLine() != 0) {
192 MI->setDebugLoc(UserDL);
193 }
194 }
195 }
196 return Changed;
197}
198
200 // If the ISel pipeline failed, do not bother running that pass.
201 if (MF.getProperties().hasProperty(
203 return false;
204
205 // Don't run the pass if the target asked so.
206 if (DoNotRunPass(MF))
207 return false;
208
209 LLVM_DEBUG(dbgs() << "Localize instructions for: " << MF.getName() << '\n');
210
211 init(MF);
212
213 // Keep track of the instructions we localized. We'll do a second pass of
214 // intra-block localization to further reduce live ranges.
215 LocalizedSetVecT LocalizedInstrs;
216
217 bool Changed = localizeInterBlock(MF, LocalizedInstrs);
218 Changed |= localizeIntraBlock(LocalizedInstrs);
219 return Changed;
220}
MachineInstrBuilder & UseMI
aarch64 promote const
MachineBasicBlock & MBB
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
Performs the initial survey of the specified function
#define LLVM_DEBUG(X)
Definition: Debug.h:101
This file defines the DenseMap class.
IRTranslator LLVM IR MI
iv Induction Variable Users
Definition: IVUsers.cpp:48
Select target instructions out of generic instructions
Move duplicate certain instructions close to their use
Definition: Localizer.cpp:32
#define DEBUG_TYPE
Definition: Localizer.cpp:22
#define F(x, y, z)
Definition: MD5.cpp:55
static DebugLoc getDebugLoc(MachineBasicBlock::instr_iterator FirstMI, MachineBasicBlock::instr_iterator LastMI)
Return the first found DebugLoc that has a DILocation, given a range of instructions.
#define INITIALIZE_PASS_DEPENDENCY(depName)
Definition: PassSupport.h:55
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:59
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:52
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file contains some templates that are useful if you are working with the STL at all.
This file describes how to lower LLVM code to machine code.
This pass exposes codegen information to IR-level passes.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
This class represents an Operation in the Expression.
iterator find(const_arg_type_t< KeyT > Val)
Definition: DenseMap.h:155
iterator end()
Definition: DenseMap.h:84
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition: DenseMap.h:220
This pass implements the localization mechanism described at the top of this file.
Definition: Localizer.h:43
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
Definition: Localizer.cpp:46
static char ID
Definition: Localizer.h:45
bool runOnMachineFunction(MachineFunction &MF) override
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
Definition: Localizer.cpp:199
instr_iterator insert(instr_iterator I, MachineInstr *M)
Insert MI into the instruction list before I, possibly inside a bundle.
iterator SkipPHIsAndLabels(iterator I)
Return the first instruction in MBB after I that is not a PHI or a label.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
bool hasProperty(Property P) const
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
const MachineFunctionProperties & getProperties() const
Get the function properties.
MachineInstr * CloneMachineInstr(const MachineInstr *Orig)
Create a new MachineInstr which is a copy of Orig, identical in all ways except the instruction has n...
const MachineBasicBlock & front() const
Representation of each machine instruction.
Definition: MachineInstr.h:68
const MachineBasicBlock * getParent() const
Definition: MachineInstr.h:326
bool isPHI() const
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:553
MachineOperand class - Representation of each machine instruction operand.
unsigned getOperandNo() const
Returns the index of this operand in the instruction that it belongs to.
MachineBasicBlock * getMBB() const
void setReg(Register Reg)
Change the register this operand corresponds to.
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
bool hasOneUse(Register RegNo) const
hasOneUse - Return true if there is exactly one instruction using the specified register.
iterator_range< use_instr_nodbg_iterator > use_nodbg_instructions(Register Reg) const
Register cloneVirtualRegister(Register VReg, StringRef Name="")
Create and return a new virtual register in the function with the same attributes as the given regist...
iterator_range< use_iterator > use_operands(Register Reg) const
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
Definition: SmallPtrSet.h:451
A SetVector that performs no allocations if smaller than a certain size.
Definition: SetVector.h:370
virtual const TargetLowering * getTargetLowering() const
Wrapper pass for TargetTransformInfo.
This pass provides access to the codegen interfaces that are needed for IR-level transformations.
Reg
All possible values of the reg field in the ModR/M byte.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
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:666
auto reverse(ContainerTy &&C)
Definition: STLExtras.h:429
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
void getSelectionDAGFallbackAnalysisUsage(AnalysisUsage &AU)
Modify analysis usage so it preserves passes required for the SelectionDAG fallback.
Definition: Utils.cpp:922
Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
Implement std::hash so that hash_code can be used in STL containers.
Definition: BitVector.h:858