21#define DEBUG_TYPE "reaching-defs-analysis"
39 OS <<
"Reaching definitions for for machine function: " << MF.
getName()
46 "Reaching Definitions Analysis",
false,
true)
61 MachineFunctionAnalysisManager::Invalidator &) {
65 return !PAC.preserved() &&
108 int DefFrameIndex = 0;
109 int SrcFrameIndex = 0;
110 if (
TII->isStoreToStackSlot(
MI, DefFrameIndex) ||
111 TII->isStackSlotCopy(
MI, DefFrameIndex, SrcFrameIndex))
112 return DefFrameIndex == FrameIndex;
118 assert(MBBNumber < MBBReachingDefs.numBlockIDs() &&
119 "Unexpected basic block number.");
120 MBBReachingDefs.startBasicBlock(MBBNumber, NumRegUnits);
127 if (LiveRegs.empty())
128 LiveRegs.assign(NumRegUnits, ReachingDefDefaultVal);
133 for (MCRegUnit Unit : TRI->regunits(LI.PhysReg)) {
137 if (LiveRegs[
static_cast<unsigned>(Unit)] != -1) {
138 LiveRegs[
static_cast<unsigned>(
Unit)] = -1;
139 MBBReachingDefs.append(MBBNumber, Unit, -1);
149 assert(
unsigned(pred->getNumber()) < MBBOutRegsInfos.size() &&
150 "Should have pre-allocated MBBInfos for all MBBs");
151 const LiveRegsDefInfo &Incoming = MBBOutRegsInfos[pred->getNumber()];
154 if (Incoming.empty())
158 for (
unsigned Unit = 0;
Unit != NumRegUnits; ++
Unit)
159 LiveRegs[Unit] = std::max(LiveRegs[Unit], Incoming[Unit]);
163 for (
unsigned Unit = 0;
Unit != NumRegUnits; ++
Unit)
164 if (LiveRegs[Unit] != ReachingDefDefaultVal)
165 MBBReachingDefs.append(MBBNumber,
static_cast<MCRegUnit
>(Unit),
170 assert(!LiveRegs.empty() &&
"Must enter basic block first.");
172 assert(MBBNumber < MBBOutRegsInfos.size() &&
173 "Unexpected basic block number.");
175 MBBOutRegsInfos[MBBNumber] = LiveRegs;
181 for (
int &OutLiveReg : MBBOutRegsInfos[MBBNumber])
182 if (OutLiveReg != ReachingDefDefaultVal)
183 OutLiveReg -= CurInstr;
188 assert(!
MI->isDebugInstr() &&
"Won't process debug instructions");
190 unsigned MBBNumber =
MI->getParent()->getNumber();
191 assert(MBBNumber < MBBReachingDefs.numBlockIDs() &&
192 "Unexpected basic block number.");
194 for (
auto &MO :
MI->operands()) {
199 MBBFrameObjsReachingDefs[{MBBNumber,
FrameIndex}].push_back(CurInstr);
203 for (MCRegUnit Unit : TRI->regunits(MO.getReg().asMCReg())) {
209 if (LiveRegs[
static_cast<unsigned>(Unit)] != CurInstr) {
210 LiveRegs[
static_cast<unsigned>(
Unit)] = CurInstr;
211 MBBReachingDefs.append(MBBNumber, Unit, CurInstr);
215 InstIds[
MI] = CurInstr;
221 assert(MBBNumber < MBBReachingDefs.numBlockIDs() &&
222 "Unexpected basic block number.");
227 int NumInsts = std::distance(NonDbgInsts.begin(), NonDbgInsts.end());
232 assert(
unsigned(pred->getNumber()) < MBBOutRegsInfos.size() &&
233 "Should have pre-allocated MBBInfos for all MBBs");
234 const LiveRegsDefInfo &Incoming = MBBOutRegsInfos[pred->getNumber()];
236 if (Incoming.empty())
239 for (
unsigned Unit = 0;
Unit != NumRegUnits; ++
Unit) {
241 if (Def == ReachingDefDefaultVal)
244 auto Defs = MBBReachingDefs.defs(MBBNumber,
static_cast<MCRegUnit
>(Unit));
245 if (!Defs.empty() && Defs.front() < 0) {
246 if (Defs.front() >= Def)
250 MBBReachingDefs.replaceFront(MBBNumber,
static_cast<MCRegUnit
>(Unit),
254 MBBReachingDefs.prepend(MBBNumber,
static_cast<MCRegUnit
>(Unit), Def);
259 if (MBBOutRegsInfos[MBBNumber][Unit] < Def - NumInsts)
260 MBBOutRegsInfos[MBBNumber][
Unit] =
Def - NumInsts;
265void ReachingDefInfo::processBasicBlock(
267 MachineBasicBlock *
MBB = TraversedMBB.
MBB;
269 << (!TraversedMBB.
IsDone ?
": incomplete\n"
270 :
": all preds known\n"));
274 reprocessBasicBlock(
MBB);
278 enterBasicBlock(
MBB);
279 for (MachineInstr &
MI :
282 leaveBasicBlock(
MBB);
290 LLVM_DEBUG(
dbgs() <<
"********** REACHING DEFINITION ANALYSIS **********\n");
296 OS <<
"RDA results for " << MF->getName() <<
"\n";
305 int FrameIndex = MO.getIndex();
307 }
else if (MO.isReg()) {
327 OS << Num <<
": " <<
MI <<
"\n";
328 InstToNumMap[&
MI] = Num;
341 MBBOutRegsInfos.clear();
342 MBBReachingDefs.clear();
343 MBBFrameObjsReachingDefs.clear();
355 NumRegUnits = TRI->getNumRegUnits();
356 NumStackObjects = MF->getFrameInfo().getNumObjects();
357 ObjectIndexBegin = MF->getFrameInfo().getObjectIndexBegin();
358 MBBReachingDefs.init(MF->getNumBlockIDs());
360 MBBOutRegsInfos.resize(MF->getNumBlockIDs());
362 TraversedMBBOrder = Traversal.
traverse(*MF);
368 processBasicBlock(TraversedMBB);
371 for (
unsigned MBBNumber = 0, NumBlockIDs = MF->getNumBlockIDs();
372 MBBNumber != NumBlockIDs; ++MBBNumber) {
373 for (
unsigned Unit = 0; Unit != NumRegUnits; ++Unit) {
374 int LastDef = ReachingDefDefaultVal;
376 MBBReachingDefs.defs(MBBNumber,
static_cast<MCRegUnit
>(Unit))) {
377 assert(Def > LastDef &&
"Defs must be sorted and unique");
386 assert(InstIds.count(
MI) &&
"Unexpected machine instuction.");
387 int InstId = InstIds.lookup(
MI);
388 int DefRes = ReachingDefDefaultVal;
389 unsigned MBBNumber =
MI->getParent()->getNumber();
390 assert(MBBNumber < MBBReachingDefs.numBlockIDs() &&
391 "Unexpected basic block number.");
392 int LatestDef = ReachingDefDefaultVal;
396 int FrameIndex = Reg.stackSlotIndex();
397 auto Lookup = MBBFrameObjsReachingDefs.find({MBBNumber, FrameIndex});
398 if (
Lookup == MBBFrameObjsReachingDefs.end())
400 auto &Defs =
Lookup->second;
401 for (
int Def : Defs) {
406 LatestDef = std::max(LatestDef, DefRes);
410 for (MCRegUnit Unit : TRI->regunits(Reg)) {
411 for (
int Def : MBBReachingDefs.defs(MBBNumber, Unit)) {
416 LatestDef = std::max(LatestDef, DefRes);
432 if (ParentA != ParentB)
440 assert(
static_cast<size_t>(
MBB->getNumber()) <
442 "Unexpected basic block number.");
443 assert(InstId <
static_cast<int>(
MBB->size()) &&
444 "Unexpected instruction id.");
449 for (
auto &
MI : *
MBB) {
450 auto F = InstIds.find(&
MI);
451 if (
F != InstIds.end() &&
F->second == InstId)
459 assert(InstIds.count(
MI) &&
"Unexpected machine instuction.");
468 InstSet &
Uses)
const {
471 while (++
MI !=
MBB->end()) {
472 if (
MI->isDebugInstr())
477 if (getReachingLocalMIDef(&*
MI, Reg) != Def)
480 for (
auto &MO :
MI->operands()) {
492 InstSet &
Uses)
const {
495 for (
auto &MO :
MI.operands()) {
503 auto Last =
MBB->getLastNonDebugInstr();
510 InstSet &
Uses)
const {
523 while (!ToVisit.
empty()) {
535 InstSet &Defs)
const {
541 for (
auto *
MBB :
MI->getParent()->predecessors())
546 InstSet &Defs)
const {
552 InstSet &Defs, BlockSet &VisitedBBs)
const {
558 LiveRegs.addLiveOuts(*
MBB);
559 if (Reg.isPhysical() && LiveRegs.available(Reg))
565 for (
auto *Pred :
MBB->predecessors())
573 if (LocalDef && InstIds.lookup(LocalDef) < InstIds.lookup(
MI))
590 unsigned Idx)
const {
591 assert(
MI->getOperand(Idx).isReg() &&
"Expected register operand");
604 LiveRegs.addLiveOuts(*
MBB);
607 if (!LiveRegs.available(Reg))
614 LiveRegs.stepBackward(
Last);
615 if (!LiveRegs.available(Reg))
616 return InstIds.lookup(&
Last) > InstIds.lookup(
MI);
623 auto Last =
MBB->getLastNonDebugInstr();
629 return Def == getReachingLocalMIDef(
MI, Reg);
638 LiveRegs.addLiveOuts(*
MBB);
639 if (Reg.isPhysical() && LiveRegs.available(Reg))
642 auto Last =
MBB->getLastNonDebugInstr();
648 for (
auto &MO :
Last->operands())
658 LiveRegs.addLiveOuts(*
MBB);
659 if (Reg.isPhysical() && LiveRegs.available(Reg))
662 auto Last =
MBB->getLastNonDebugInstr();
667 int FrameIndex = Reg.stackSlotIndex();
674 for (
auto &MO :
Last->operands())
678 return Def < 0 ? nullptr : getInstFromId(
MBB, Def);
682 return MI.mayLoadOrStore() ||
MI.mayRaiseFPException() ||
683 MI.hasUnmodeledSideEffects() ||
MI.isTerminator() ||
684 MI.isCall() ||
MI.isBarrier() ||
MI.isBranch() ||
MI.isReturn();
690template <
typename Iterator>
695 SmallSet<Register, 2> Defs;
709 for (
auto I = ++Iterator(From),
E = Iterator(To);
I !=
E; ++
I) {
712 for (
auto &MO :
I->operands())
713 if (MO.isReg() && MO.getReg() && Defs.
count(MO.getReg()))
723 for (
auto I = Iterator(From), E = From->
getParent()->
end();
I != E; ++
I)
725 return isSafeToMove<Iterator>(From, To);
735 return isSafeToMove<Iterator>(From, To);
763 for (
auto &MO :
MI->operands()) {
770 for (
auto *
I :
Uses) {
782 InstSet &Dead)
const {
788 unsigned LiveDefs = 0;
789 for (
auto &MO : Def->operands()) {
804 for (
auto &MO :
MI->operands()) {
808 if (
IsDead(Def, MO.getReg()))
822 if (
auto *Def = getReachingLocalMIDef(
MI, Reg)) {
835 for (
auto E =
MBB->end();
I != E; ++
I) {
838 for (
auto &MO :
I->operands())
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
ReachingDefInfo InstSet InstSet & Ignore
ReachingDefInfo InstSet & ToRemove
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
const HexagonInstrInfo * TII
Register const TargetRegisterInfo * TRI
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
static bool isValidRegUseOf(const MachineOperand &MO, Register Reg, const TargetRegisterInfo *TRI)
static bool mayHaveSideEffects(MachineInstr &MI)
static bool isValidReg(const MachineOperand &MO)
static bool isFIDef(const MachineInstr &MI, int FrameIndex, const TargetInstrInfo *TII)
static bool isValidRegDef(const MachineOperand &MO)
static bool isValidRegDefOf(const MachineOperand &MO, Register Reg, const TargetRegisterInfo *TRI)
static bool isValidRegUse(const MachineOperand &MO)
Remove Loads Into Fake Uses
This file defines generic set operations that may be used on set's of different types,...
This file defines the SmallSet class.
static int Lookup(ArrayRef< TableEntry > Table, unsigned Opcode)
This templated class represents "all analyses that operate over <aparticular IR unit>" (e....
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent the analysis usage information of a pass.
void setPreservesAll()
Set by analyses that do not transform their input at all.
Represents analyses that only rely on functions' control flow.
A set of register units used to track register liveness.
This class provides the basic blocks traversal order used by passes like ReachingDefAnalysis and Exec...
TraversalOrder traverse(MachineFunction &MF)
unsigned numBlockIDs() const
An RAII based helper class to modify MachineFunctionProperties when running pass.
instr_iterator instr_begin()
iterator_range< livein_iterator > liveins() const
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
MachineInstrBundleIterator< MachineInstr, true > reverse_iterator
instr_iterator instr_end()
iterator_range< pred_iterator > predecessors()
MachineInstrBundleIterator< MachineInstr > iterator
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.
Properties which a MachineFunction may have at a given point in time.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
Representation of each machine instruction.
const MachineBasicBlock * getParent() const
MachineOperand class - Representation of each machine instruction operand.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
Register getReg() const
getReg - Returns the register number.
static LLVM_ABI PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalysisChecker getChecker() const
Build a checker for this PreservedAnalyses and the specified analysis type.
Result run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
bool runOnMachineFunction(MachineFunction &F) override
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
MachineFunctionProperties getRequiredProperties() const override
This class provides the reaching def analysis.
MachineInstr * getUniqueReachingMIDef(MachineInstr *MI, Register Reg) const
If a single MachineInstr creates the reaching definition, then return it.
bool isReachingDefLiveOut(MachineInstr *MI, Register Reg) const
Return whether the reaching def for MI also is live out of its parent block.
bool isSafeToMoveForwards(MachineInstr *From, MachineInstr *To) const
Return whether From can be moved forwards to just before To.
int getReachingDef(MachineInstr *MI, Register Reg) const
Provides the instruction id of the closest reaching def instruction of Reg that reaches MI,...
void run(MachineFunction &mf)
void getReachingLocalUses(MachineInstr *MI, Register Reg, InstSet &Uses) const
Provides the uses, in the same block as MI, of register that MI defines.
int getClearance(MachineInstr *MI, Register Reg) const
Provides the clearance - the number of instructions since the closest reaching def instuction of Reg ...
bool isRegDefinedAfter(MachineInstr *MI, Register Reg) const
Return whether the given register is defined after MI.
void init()
Initialize data structures.
void print(raw_ostream &OS)
bool hasLocalDefBefore(MachineInstr *MI, Register Reg) const
Provide whether the register has been defined in the same basic block as, and before,...
void reset()
Re-run the analysis.
void getGlobalUses(MachineInstr *MI, Register Reg, InstSet &Uses) const
Collect the users of the value stored in Reg, which is defined by MI.
MachineInstr * getMIOperand(MachineInstr *MI, unsigned Idx) const
If a single MachineInstr creates the reaching definition, for MIs operand at Idx, then return it.
void getLiveOuts(MachineBasicBlock *MBB, Register Reg, InstSet &Defs, BlockSet &VisitedBBs) const
Search MBB for a definition of Reg and insert it into Defs.
void traverse()
Traverse the machine function, mapping definitions.
bool isSafeToMoveBackwards(MachineInstr *From, MachineInstr *To) const
Return whether From can be moved backwards to just after To.
void collectKilledOperands(MachineInstr *MI, InstSet &Dead) const
Assuming MI is dead, recursively search the incoming operands which are killed by MI and collect thos...
bool hasSameReachingDef(MachineInstr *A, MachineInstr *B, Register Reg) const
Return whether A and B use the same def of Reg.
bool isRegUsedAfter(MachineInstr *MI, Register Reg) const
Return whether the given register is used after MI, whether it's a local use or a live out.
void getGlobalReachingDefs(MachineInstr *MI, Register Reg, InstSet &Defs) const
Collect all possible definitions of the value stored in Reg, which is used by MI.
bool isSafeToRemove(MachineInstr *MI, InstSet &ToRemove) const
Return whether removing this instruction will have no effect on the program, returning the redundant ...
MachineInstr * getLocalLiveOutMIDef(MachineBasicBlock *MBB, Register Reg) const
Return the local MI that produces the live out value for Reg, or nullptr for a non-live out or non-lo...
bool invalidate(MachineFunction &F, const PreservedAnalyses &PA, MachineFunctionAnalysisManager::Invalidator &)
Handle invalidation explicitly.
bool getLiveInUses(MachineBasicBlock *MBB, Register Reg, InstSet &Uses) const
For the given block, collect the instructions that use the live-in value of the provided register.
bool isSafeToDefRegAt(MachineInstr *MI, Register Reg) const
Return whether a MachineInstr could be inserted at MI and safely define the given register without af...
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
Wrapper class representing virtual and physical registers.
static Register index2StackSlot(int FI)
Convert a non-negative frame index to a stack slot register value.
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
size_type count(const T &V) const
count - Return 1 if the element is in the set, 0 otherwise.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
TargetInstrInfo - Interface to description of machine instruction set.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
TargetSubtargetInfo - Generic base class for all target subtargets.
virtual const TargetInstrInfo * getInstrInfo() const
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
This class implements an extremely fast bulk output stream that can only output to a stream.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
NodeAddr< DefNode * > Def
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI void initializeReachingDefInfoWrapperPassPass(PassRegistry &)
bool set_is_subset(const S1Ty &S1, const S2Ty &S2)
set_is_subset(A, B) - Return true iff A in B
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
LLVM_ABI Printable printRegUnit(MCRegUnit Unit, const TargetRegisterInfo *TRI)
Create Printable object to print register units on a raw_ostream.
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
auto instructionsWithoutDebug(IterT It, IterT End, bool SkipPseudoOp=true)
Construct a range iterator which begins at It and moves forwards until End is reached,...
LLVM_ABI Printable printMBBReference(const MachineBasicBlock &MBB)
Prints a machine basic block reference.
A special type used by analysis passes to provide an address that identifies that particular analysis...
Incoming for lane maks phi as machine instruction, incoming register Reg and incoming block Block are...
MachineBasicBlock * MBB
The basic block.
bool IsDone
True if the block that is ready for its final round of processing.
bool PrimaryPass
True if this is the first time we process the basic block.