diff options
Diffstat (limited to 'llvm/lib/CodeGen/ReachingDefAnalysis.cpp')
-rw-r--r-- | llvm/lib/CodeGen/ReachingDefAnalysis.cpp | 141 |
1 files changed, 139 insertions, 2 deletions
diff --git a/llvm/lib/CodeGen/ReachingDefAnalysis.cpp b/llvm/lib/CodeGen/ReachingDefAnalysis.cpp index 2850033e6419..3c1f9905afd0 100644 --- a/llvm/lib/CodeGen/ReachingDefAnalysis.cpp +++ b/llvm/lib/CodeGen/ReachingDefAnalysis.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +#include "llvm/CodeGen/LivePhysRegs.h" #include "llvm/CodeGen/ReachingDefAnalysis.h" #include "llvm/CodeGen/TargetRegisterInfo.h" #include "llvm/CodeGen/TargetSubtargetInfo.h" @@ -132,8 +133,6 @@ void ReachingDefAnalysis::processBasicBlock( } bool ReachingDefAnalysis::runOnMachineFunction(MachineFunction &mf) { - if (skipFunction(mf.getFunction())) - return false; MF = &mf; TRI = MF->getSubtarget().getRegisterInfo(); @@ -189,7 +188,145 @@ int ReachingDefAnalysis::getReachingDef(MachineInstr *MI, int PhysReg) { return LatestDef; } +MachineInstr* ReachingDefAnalysis::getReachingMIDef(MachineInstr *MI, int PhysReg) { + return getInstFromId(MI->getParent(), getReachingDef(MI, PhysReg)); +} + +bool ReachingDefAnalysis::hasSameReachingDef(MachineInstr *A, MachineInstr *B, + int PhysReg) { + MachineBasicBlock *ParentA = A->getParent(); + MachineBasicBlock *ParentB = B->getParent(); + if (ParentA != ParentB) + return false; + + return getReachingDef(A, PhysReg) == getReachingDef(B, PhysReg); +} + +MachineInstr *ReachingDefAnalysis::getInstFromId(MachineBasicBlock *MBB, + int InstId) { + assert(static_cast<size_t>(MBB->getNumber()) < MBBReachingDefs.size() && + "Unexpected basic block number."); + assert(InstId < static_cast<int>(MBB->size()) && + "Unexpected instruction id."); + + if (InstId < 0) + return nullptr; + + for (auto &MI : *MBB) { + if (InstIds.count(&MI) && InstIds[&MI] == InstId) + return &MI; + } + return nullptr; +} + int ReachingDefAnalysis::getClearance(MachineInstr *MI, MCPhysReg PhysReg) { assert(InstIds.count(MI) && "Unexpected machine instuction."); return InstIds[MI] - getReachingDef(MI, PhysReg); } + +void ReachingDefAnalysis::getReachingLocalUses(MachineInstr *Def, int PhysReg, + SmallVectorImpl<MachineInstr*> &Uses) { + MachineBasicBlock *MBB = Def->getParent(); + MachineBasicBlock::iterator MI = MachineBasicBlock::iterator(Def); + while (++MI != MBB->end()) { + // If/when we find a new reaching def, we know that there's no more uses + // of 'Def'. + if (getReachingMIDef(&*MI, PhysReg) != Def) + return; + + for (auto &MO : MI->operands()) { + if (!MO.isReg() || !MO.isUse() || MO.getReg() != PhysReg) + continue; + + Uses.push_back(&*MI); + if (MO.isKill()) + return; + } + } +} + +unsigned ReachingDefAnalysis::getNumUses(MachineInstr *Def, int PhysReg) { + SmallVector<MachineInstr*, 4> Uses; + getReachingLocalUses(Def, PhysReg, Uses); + return Uses.size(); +} + +bool ReachingDefAnalysis::isRegUsedAfter(MachineInstr *MI, int PhysReg) { + MachineBasicBlock *MBB = MI->getParent(); + LivePhysRegs LiveRegs(*TRI); + LiveRegs.addLiveOuts(*MBB); + + // Yes if the register is live out of the basic block. + if (LiveRegs.contains(PhysReg)) + return true; + + // Walk backwards through the block to see if the register is live at some + // point. + for (auto Last = MBB->rbegin(), End = MBB->rend(); Last != End; ++Last) { + LiveRegs.stepBackward(*Last); + if (LiveRegs.contains(PhysReg)) + return InstIds[&*Last] > InstIds[MI]; + } + return false; +} + +bool ReachingDefAnalysis::isReachingDefLiveOut(MachineInstr *MI, int PhysReg) { + MachineBasicBlock *MBB = MI->getParent(); + LivePhysRegs LiveRegs(*TRI); + LiveRegs.addLiveOuts(*MBB); + if (!LiveRegs.contains(PhysReg)) + return false; + + MachineInstr *Last = &MBB->back(); + int Def = getReachingDef(MI, PhysReg); + if (getReachingDef(Last, PhysReg) != Def) + return false; + + // Finally check that the last instruction doesn't redefine the register. + for (auto &MO : Last->operands()) + if (MO.isReg() && MO.isDef() && MO.getReg() == PhysReg) + return false; + + return true; +} + +MachineInstr* ReachingDefAnalysis::getLocalLiveOutMIDef(MachineBasicBlock *MBB, + int PhysReg) { + LivePhysRegs LiveRegs(*TRI); + LiveRegs.addLiveOuts(*MBB); + if (!LiveRegs.contains(PhysReg)) + return nullptr; + + MachineInstr *Last = &MBB->back(); + int Def = getReachingDef(Last, PhysReg); + for (auto &MO : Last->operands()) + if (MO.isReg() && MO.isDef() && MO.getReg() == PhysReg) + return Last; + + return Def < 0 ? nullptr : getInstFromId(MBB, Def); +} + +MachineInstr *ReachingDefAnalysis::getInstWithUseBefore(MachineInstr *MI, + int PhysReg) { + auto I = MachineBasicBlock::reverse_iterator(MI); + auto E = MI->getParent()->rend(); + I++; + + for ( ; I != E; I++) + for (auto &MO : I->operands()) + if (MO.isReg() && MO.isUse() && MO.getReg() == PhysReg) + return &*I; + + return nullptr; +} + +void ReachingDefAnalysis::getAllInstWithUseBefore(MachineInstr *MI, + int PhysReg, SmallVectorImpl<MachineInstr*> &Uses) { + MachineInstr *Use = nullptr; + MachineInstr *Pos = MI; + + while ((Use = getInstWithUseBefore(Pos, PhysReg))) { + Uses.push_back(Use); + Pos = Use; + } +} |