2018-01-22 11:06:50 +01:00
|
|
|
//===---- ReachingDefAnalysis.cpp - Reaching Def Analysis ---*- C++ -*-----===//
|
|
|
|
//
|
2019-01-19 09:50:56 +01:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2018-01-22 11:06:50 +01:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2020-01-29 09:26:11 +01:00
|
|
|
#include "llvm/ADT/SmallSet.h"
|
2019-11-26 11:03:25 +01:00
|
|
|
#include "llvm/CodeGen/LivePhysRegs.h"
|
2018-01-22 11:06:50 +01:00
|
|
|
#include "llvm/CodeGen/ReachingDefAnalysis.h"
|
|
|
|
#include "llvm/CodeGen/TargetRegisterInfo.h"
|
|
|
|
#include "llvm/CodeGen/TargetSubtargetInfo.h"
|
2019-10-19 02:22:07 +02:00
|
|
|
#include "llvm/Support/Debug.h"
|
2018-01-22 11:06:50 +01:00
|
|
|
|
|
|
|
using namespace llvm;
|
|
|
|
|
|
|
|
#define DEBUG_TYPE "reaching-deps-analysis"
|
|
|
|
|
|
|
|
char ReachingDefAnalysis::ID = 0;
|
|
|
|
INITIALIZE_PASS(ReachingDefAnalysis, DEBUG_TYPE, "ReachingDefAnalysis", false,
|
|
|
|
true)
|
|
|
|
|
2020-03-10 18:24:04 +01:00
|
|
|
static bool isValidReg(const MachineOperand &MO) {
|
2020-02-28 12:14:42 +01:00
|
|
|
return MO.isReg() && MO.getReg();
|
|
|
|
}
|
|
|
|
|
2020-03-10 18:24:04 +01:00
|
|
|
static bool isValidRegUse(const MachineOperand &MO) {
|
2020-02-28 12:14:42 +01:00
|
|
|
return isValidReg(MO) && MO.isUse();
|
|
|
|
}
|
|
|
|
|
2020-03-10 18:24:04 +01:00
|
|
|
static bool isValidRegUseOf(const MachineOperand &MO, int PhysReg) {
|
2020-02-28 12:14:42 +01:00
|
|
|
return isValidRegUse(MO) && MO.getReg() == PhysReg;
|
|
|
|
}
|
|
|
|
|
2020-03-10 18:24:04 +01:00
|
|
|
static bool isValidRegDef(const MachineOperand &MO) {
|
2020-02-28 12:14:42 +01:00
|
|
|
return isValidReg(MO) && MO.isDef();
|
|
|
|
}
|
|
|
|
|
2020-03-10 18:24:04 +01:00
|
|
|
static bool isValidRegDefOf(const MachineOperand &MO, int PhysReg) {
|
2020-02-28 12:14:42 +01:00
|
|
|
return isValidRegDef(MO) && MO.getReg() == PhysReg;
|
|
|
|
}
|
|
|
|
|
2018-01-22 11:06:50 +01:00
|
|
|
void ReachingDefAnalysis::enterBasicBlock(
|
|
|
|
const LoopTraversal::TraversedMBBInfo &TraversedMBB) {
|
|
|
|
|
|
|
|
MachineBasicBlock *MBB = TraversedMBB.MBB;
|
2018-01-22 14:24:10 +01:00
|
|
|
unsigned MBBNumber = MBB->getNumber();
|
2018-01-22 11:06:50 +01:00
|
|
|
assert(MBBNumber < MBBReachingDefs.size() &&
|
|
|
|
"Unexpected basic block number.");
|
|
|
|
MBBReachingDefs[MBBNumber].resize(NumRegUnits);
|
|
|
|
|
|
|
|
// Reset instruction counter in each basic block.
|
|
|
|
CurInstr = 0;
|
|
|
|
|
|
|
|
// Set up LiveRegs to represent registers entering MBB.
|
|
|
|
// Default values are 'nothing happened a long time ago'.
|
|
|
|
if (LiveRegs.empty())
|
2018-03-20 21:53:21 +01:00
|
|
|
LiveRegs.assign(NumRegUnits, ReachingDefDefaultVal);
|
2018-01-22 11:06:50 +01:00
|
|
|
|
|
|
|
// This is the entry block.
|
|
|
|
if (MBB->pred_empty()) {
|
|
|
|
for (const auto &LI : MBB->liveins()) {
|
|
|
|
for (MCRegUnitIterator Unit(LI.PhysReg, TRI); Unit.isValid(); ++Unit) {
|
|
|
|
// Treat function live-ins as if they were defined just before the first
|
|
|
|
// instruction. Usually, function arguments are set up immediately
|
|
|
|
// before the call.
|
2020-04-05 21:09:49 +02:00
|
|
|
if (LiveRegs[*Unit] != -1) {
|
|
|
|
LiveRegs[*Unit] = -1;
|
|
|
|
MBBReachingDefs[MBBNumber][*Unit].push_back(-1);
|
|
|
|
}
|
2018-01-22 11:06:50 +01:00
|
|
|
}
|
|
|
|
}
|
2018-05-14 14:53:11 +02:00
|
|
|
LLVM_DEBUG(dbgs() << printMBBReference(*MBB) << ": entry\n");
|
2018-01-22 11:06:50 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Try to coalesce live-out registers from predecessors.
|
|
|
|
for (MachineBasicBlock *pred : MBB->predecessors()) {
|
2018-01-22 14:24:10 +01:00
|
|
|
assert(unsigned(pred->getNumber()) < MBBOutRegsInfos.size() &&
|
2018-01-22 11:06:50 +01:00
|
|
|
"Should have pre-allocated MBBInfos for all MBBs");
|
|
|
|
const LiveRegsDefInfo &Incoming = MBBOutRegsInfos[pred->getNumber()];
|
|
|
|
// Incoming is null if this is a backedge from a BB
|
|
|
|
// we haven't processed yet
|
|
|
|
if (Incoming.empty())
|
|
|
|
continue;
|
|
|
|
|
[RDA] Only store most recent reaching def from predecessors (NFCI)
When entering a basic block, RDA inserts reaching definitions coming
from predecessor blocks (which will be negative numbers) in a rather
peculiar way. If you have incoming reaching definitions -4, -3, -2, -1,
it will insert those. If you have incoming reaching definitions
-1, -2, -3, -4, it will insert -1, -1, -1, -1, as the max is taken
at each step. That's probably not what was intended...
However, RDA only actually cares about the most recent reaching
definition from a predecessor (to calculate clearance), so this
ends up working fine as far as behavior is concerned. It does
waste memory on unnecessary reaching definitions though.
This patch changes the implementation to first compute the most
recent reaching definition in one loop, and then insert only that
one in a separate loop.
Differential Revision: https://reviews.llvm.org/D77508
2020-04-05 00:46:20 +02:00
|
|
|
// Find the most recent reaching definition from a predecessor.
|
|
|
|
for (unsigned Unit = 0; Unit != NumRegUnits; ++Unit)
|
2018-01-22 11:06:50 +01:00
|
|
|
LiveRegs[Unit] = std::max(LiveRegs[Unit], Incoming[Unit]);
|
|
|
|
}
|
|
|
|
|
[RDA] Only store most recent reaching def from predecessors (NFCI)
When entering a basic block, RDA inserts reaching definitions coming
from predecessor blocks (which will be negative numbers) in a rather
peculiar way. If you have incoming reaching definitions -4, -3, -2, -1,
it will insert those. If you have incoming reaching definitions
-1, -2, -3, -4, it will insert -1, -1, -1, -1, as the max is taken
at each step. That's probably not what was intended...
However, RDA only actually cares about the most recent reaching
definition from a predecessor (to calculate clearance), so this
ends up working fine as far as behavior is concerned. It does
waste memory on unnecessary reaching definitions though.
This patch changes the implementation to first compute the most
recent reaching definition in one loop, and then insert only that
one in a separate loop.
Differential Revision: https://reviews.llvm.org/D77508
2020-04-05 00:46:20 +02:00
|
|
|
// Insert the most recent reaching definition we found.
|
|
|
|
for (unsigned Unit = 0; Unit != NumRegUnits; ++Unit)
|
|
|
|
if (LiveRegs[Unit] != ReachingDefDefaultVal)
|
|
|
|
MBBReachingDefs[MBBNumber][Unit].push_back(LiveRegs[Unit]);
|
|
|
|
|
2018-05-14 14:53:11 +02:00
|
|
|
LLVM_DEBUG(dbgs() << printMBBReference(*MBB)
|
|
|
|
<< (!TraversedMBB.IsDone ? ": incomplete\n"
|
|
|
|
: ": all preds known\n"));
|
2018-01-22 11:06:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void ReachingDefAnalysis::leaveBasicBlock(
|
|
|
|
const LoopTraversal::TraversedMBBInfo &TraversedMBB) {
|
|
|
|
assert(!LiveRegs.empty() && "Must enter basic block first.");
|
2018-01-22 14:24:10 +01:00
|
|
|
unsigned MBBNumber = TraversedMBB.MBB->getNumber();
|
2018-01-22 11:06:50 +01:00
|
|
|
assert(MBBNumber < MBBOutRegsInfos.size() &&
|
|
|
|
"Unexpected basic block number.");
|
|
|
|
// Save register clearances at end of MBB - used by enterBasicBlock().
|
|
|
|
MBBOutRegsInfos[MBBNumber] = LiveRegs;
|
|
|
|
|
|
|
|
// While processing the basic block, we kept `Def` relative to the start
|
|
|
|
// of the basic block for convenience. However, future use of this information
|
|
|
|
// only cares about the clearance from the end of the block, so adjust
|
|
|
|
// everything to be relative to the end of the basic block.
|
|
|
|
for (int &OutLiveReg : MBBOutRegsInfos[MBBNumber])
|
2020-04-05 19:16:56 +02:00
|
|
|
if (OutLiveReg != ReachingDefDefaultVal)
|
|
|
|
OutLiveReg -= CurInstr;
|
2018-01-22 11:06:50 +01:00
|
|
|
LiveRegs.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ReachingDefAnalysis::processDefs(MachineInstr *MI) {
|
2018-05-09 04:42:00 +02:00
|
|
|
assert(!MI->isDebugInstr() && "Won't process debug instructions");
|
2018-01-22 11:06:50 +01:00
|
|
|
|
2018-01-22 14:24:10 +01:00
|
|
|
unsigned MBBNumber = MI->getParent()->getNumber();
|
2018-01-22 11:06:50 +01:00
|
|
|
assert(MBBNumber < MBBReachingDefs.size() &&
|
|
|
|
"Unexpected basic block number.");
|
2020-02-28 12:14:42 +01:00
|
|
|
|
|
|
|
for (auto &MO : MI->operands()) {
|
|
|
|
if (!isValidRegDef(MO))
|
2018-01-22 11:06:50 +01:00
|
|
|
continue;
|
|
|
|
for (MCRegUnitIterator Unit(MO.getReg(), TRI); Unit.isValid(); ++Unit) {
|
|
|
|
// This instruction explicitly defines the current reg unit.
|
2020-04-05 21:09:49 +02:00
|
|
|
LLVM_DEBUG(dbgs() << printReg(*Unit, TRI) << ":\t" << CurInstr
|
2018-05-14 14:53:11 +02:00
|
|
|
<< '\t' << *MI);
|
2018-01-22 11:06:50 +01:00
|
|
|
|
|
|
|
// How many instructions since this reg unit was last written?
|
2020-04-05 21:09:49 +02:00
|
|
|
if (LiveRegs[*Unit] != CurInstr) {
|
|
|
|
LiveRegs[*Unit] = CurInstr;
|
|
|
|
MBBReachingDefs[MBBNumber][*Unit].push_back(CurInstr);
|
|
|
|
}
|
2018-01-22 11:06:50 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
InstIds[MI] = CurInstr;
|
|
|
|
++CurInstr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ReachingDefAnalysis::processBasicBlock(
|
|
|
|
const LoopTraversal::TraversedMBBInfo &TraversedMBB) {
|
|
|
|
enterBasicBlock(TraversedMBB);
|
|
|
|
for (MachineInstr &MI : *TraversedMBB.MBB) {
|
2018-05-09 04:42:00 +02:00
|
|
|
if (!MI.isDebugInstr())
|
2018-01-22 11:06:50 +01:00
|
|
|
processDefs(&MI);
|
|
|
|
}
|
|
|
|
leaveBasicBlock(TraversedMBB);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ReachingDefAnalysis::runOnMachineFunction(MachineFunction &mf) {
|
|
|
|
MF = &mf;
|
|
|
|
TRI = MF->getSubtarget().getRegisterInfo();
|
2020-02-20 15:58:08 +01:00
|
|
|
LLVM_DEBUG(dbgs() << "********** REACHING DEFINITION ANALYSIS **********\n");
|
|
|
|
init();
|
|
|
|
traverse();
|
|
|
|
return false;
|
|
|
|
}
|
2018-01-22 11:06:50 +01:00
|
|
|
|
2020-02-20 15:58:08 +01:00
|
|
|
void ReachingDefAnalysis::releaseMemory() {
|
|
|
|
// Clear the internal vectors.
|
|
|
|
MBBOutRegsInfos.clear();
|
|
|
|
MBBReachingDefs.clear();
|
|
|
|
InstIds.clear();
|
2018-01-22 11:06:50 +01:00
|
|
|
LiveRegs.clear();
|
2020-02-20 15:58:08 +01:00
|
|
|
}
|
2018-01-22 11:06:50 +01:00
|
|
|
|
2020-02-20 15:58:08 +01:00
|
|
|
void ReachingDefAnalysis::reset() {
|
|
|
|
releaseMemory();
|
|
|
|
init();
|
|
|
|
traverse();
|
|
|
|
}
|
2018-01-22 11:06:50 +01:00
|
|
|
|
2020-02-20 15:58:08 +01:00
|
|
|
void ReachingDefAnalysis::init() {
|
|
|
|
NumRegUnits = TRI->getNumRegUnits();
|
|
|
|
MBBReachingDefs.resize(MF->getNumBlockIDs());
|
2018-01-22 11:06:50 +01:00
|
|
|
// Initialize the MBBOutRegsInfos
|
2020-02-20 15:58:08 +01:00
|
|
|
MBBOutRegsInfos.resize(MF->getNumBlockIDs());
|
|
|
|
LoopTraversal Traversal;
|
|
|
|
TraversedMBBOrder = Traversal.traverse(*MF);
|
|
|
|
}
|
2018-01-22 11:06:50 +01:00
|
|
|
|
2020-02-20 15:58:08 +01:00
|
|
|
void ReachingDefAnalysis::traverse() {
|
2018-01-22 11:06:50 +01:00
|
|
|
// Traverse the basic blocks.
|
2020-02-20 15:58:08 +01:00
|
|
|
for (LoopTraversal::TraversedMBBInfo TraversedMBB : TraversedMBBOrder)
|
2018-01-22 11:06:50 +01:00
|
|
|
processBasicBlock(TraversedMBB);
|
|
|
|
// Sorting all reaching defs found for a ceartin reg unit in a given BB.
|
|
|
|
for (MBBDefsInfo &MBBDefs : MBBReachingDefs) {
|
|
|
|
for (MBBRegUnitDefs &RegUnitDefs : MBBDefs)
|
llvm::sort(C.begin(), C.end(), ...) -> llvm::sort(C, ...)
Summary: The convenience wrapper in STLExtras is available since rL342102.
Reviewers: dblaikie, javed.absar, JDevlieghere, andreadb
Subscribers: MatzeB, sanjoy, arsenm, dschuff, mehdi_amini, sdardis, nemanjai, jvesely, nhaehnle, sbc100, jgravelle-google, eraman, aheejin, kbarton, JDevlieghere, javed.absar, gbedwell, jrtc27, mgrang, atanasyan, steven_wu, george.burgess.iv, dexonsmith, kristina, jsji, llvm-commits
Differential Revision: https://reviews.llvm.org/D52573
llvm-svn: 343163
2018-09-27 04:13:45 +02:00
|
|
|
llvm::sort(RegUnitDefs);
|
2018-01-22 11:06:50 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-23 14:22:13 +01:00
|
|
|
int ReachingDefAnalysis::getReachingDef(MachineInstr *MI, int PhysReg) const {
|
2018-01-22 11:06:50 +01:00
|
|
|
assert(InstIds.count(MI) && "Unexpected machine instuction.");
|
2020-01-23 14:22:13 +01:00
|
|
|
int InstId = InstIds.lookup(MI);
|
2018-03-20 21:53:21 +01:00
|
|
|
int DefRes = ReachingDefDefaultVal;
|
2018-01-22 14:24:10 +01:00
|
|
|
unsigned MBBNumber = MI->getParent()->getNumber();
|
2018-01-22 11:06:50 +01:00
|
|
|
assert(MBBNumber < MBBReachingDefs.size() &&
|
|
|
|
"Unexpected basic block number.");
|
2018-03-20 21:53:21 +01:00
|
|
|
int LatestDef = ReachingDefDefaultVal;
|
2018-01-22 11:06:50 +01:00
|
|
|
for (MCRegUnitIterator Unit(PhysReg, TRI); Unit.isValid(); ++Unit) {
|
|
|
|
for (int Def : MBBReachingDefs[MBBNumber][*Unit]) {
|
|
|
|
if (Def >= InstId)
|
|
|
|
break;
|
|
|
|
DefRes = Def;
|
|
|
|
}
|
|
|
|
LatestDef = std::max(LatestDef, DefRes);
|
|
|
|
}
|
|
|
|
return LatestDef;
|
|
|
|
}
|
|
|
|
|
2020-02-26 12:14:54 +01:00
|
|
|
MachineInstr* ReachingDefAnalysis::getReachingLocalMIDef(MachineInstr *MI,
|
2020-01-23 14:22:13 +01:00
|
|
|
int PhysReg) const {
|
2019-11-26 11:03:25 +01:00
|
|
|
return getInstFromId(MI->getParent(), getReachingDef(MI, PhysReg));
|
|
|
|
}
|
|
|
|
|
2019-11-26 11:25:04 +01:00
|
|
|
bool ReachingDefAnalysis::hasSameReachingDef(MachineInstr *A, MachineInstr *B,
|
2020-01-23 14:22:13 +01:00
|
|
|
int PhysReg) const {
|
2019-11-26 11:25:04 +01:00
|
|
|
MachineBasicBlock *ParentA = A->getParent();
|
|
|
|
MachineBasicBlock *ParentB = B->getParent();
|
|
|
|
if (ParentA != ParentB)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return getReachingDef(A, PhysReg) == getReachingDef(B, PhysReg);
|
|
|
|
}
|
|
|
|
|
2019-11-26 11:03:25 +01:00
|
|
|
MachineInstr *ReachingDefAnalysis::getInstFromId(MachineBasicBlock *MBB,
|
2020-01-23 14:22:13 +01:00
|
|
|
int InstId) const {
|
2019-11-26 11:25:04 +01:00
|
|
|
assert(static_cast<size_t>(MBB->getNumber()) < MBBReachingDefs.size() &&
|
2019-11-26 11:03:25 +01:00
|
|
|
"Unexpected basic block number.");
|
|
|
|
assert(InstId < static_cast<int>(MBB->size()) &&
|
|
|
|
"Unexpected instruction id.");
|
|
|
|
|
|
|
|
if (InstId < 0)
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
for (auto &MI : *MBB) {
|
2020-02-06 15:13:31 +01:00
|
|
|
auto F = InstIds.find(&MI);
|
|
|
|
if (F != InstIds.end() && F->second == InstId)
|
2019-11-26 11:03:25 +01:00
|
|
|
return &MI;
|
|
|
|
}
|
2020-02-06 15:13:31 +01:00
|
|
|
|
2019-11-26 11:03:25 +01:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2020-01-23 14:22:13 +01:00
|
|
|
int
|
|
|
|
ReachingDefAnalysis::getClearance(MachineInstr *MI, MCPhysReg PhysReg) const {
|
2018-01-22 11:06:50 +01:00
|
|
|
assert(InstIds.count(MI) && "Unexpected machine instuction.");
|
2020-01-23 14:22:13 +01:00
|
|
|
return InstIds.lookup(MI) - getReachingDef(MI, PhysReg);
|
2018-01-22 11:06:50 +01:00
|
|
|
}
|
2019-11-26 11:03:25 +01:00
|
|
|
|
2020-01-29 09:26:11 +01:00
|
|
|
bool
|
|
|
|
ReachingDefAnalysis::hasLocalDefBefore(MachineInstr *MI, int PhysReg) const {
|
|
|
|
return getReachingDef(MI, PhysReg) >= 0;
|
|
|
|
}
|
|
|
|
|
2019-11-26 11:25:04 +01:00
|
|
|
void ReachingDefAnalysis::getReachingLocalUses(MachineInstr *Def, int PhysReg,
|
2020-01-28 14:06:07 +01:00
|
|
|
InstSet &Uses) const {
|
2019-11-26 11:25:04 +01:00
|
|
|
MachineBasicBlock *MBB = Def->getParent();
|
|
|
|
MachineBasicBlock::iterator MI = MachineBasicBlock::iterator(Def);
|
|
|
|
while (++MI != MBB->end()) {
|
2020-01-23 17:44:25 +01:00
|
|
|
if (MI->isDebugInstr())
|
|
|
|
continue;
|
|
|
|
|
2019-12-20 10:32:36 +01:00
|
|
|
// If/when we find a new reaching def, we know that there's no more uses
|
|
|
|
// of 'Def'.
|
2020-02-26 12:14:54 +01:00
|
|
|
if (getReachingLocalMIDef(&*MI, PhysReg) != Def)
|
2019-12-20 10:32:36 +01:00
|
|
|
return;
|
|
|
|
|
2019-11-26 11:25:04 +01:00
|
|
|
for (auto &MO : MI->operands()) {
|
2020-02-28 12:14:42 +01:00
|
|
|
if (!isValidRegUseOf(MO, PhysReg))
|
2019-11-26 11:25:04 +01:00
|
|
|
continue;
|
|
|
|
|
2020-01-17 14:08:24 +01:00
|
|
|
Uses.insert(&*MI);
|
2019-11-26 11:25:04 +01:00
|
|
|
if (MO.isKill())
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-11-26 11:03:25 +01:00
|
|
|
|
2020-01-23 14:22:13 +01:00
|
|
|
bool
|
|
|
|
ReachingDefAnalysis::getLiveInUses(MachineBasicBlock *MBB, int PhysReg,
|
2020-01-28 14:06:07 +01:00
|
|
|
InstSet &Uses) const {
|
2020-01-17 14:08:24 +01:00
|
|
|
for (auto &MI : *MBB) {
|
2020-01-23 17:44:25 +01:00
|
|
|
if (MI.isDebugInstr())
|
|
|
|
continue;
|
2020-01-17 14:08:24 +01:00
|
|
|
for (auto &MO : MI.operands()) {
|
2020-02-28 12:14:42 +01:00
|
|
|
if (!isValidRegUseOf(MO, PhysReg))
|
2020-01-17 14:08:24 +01:00
|
|
|
continue;
|
|
|
|
if (getReachingDef(&MI, PhysReg) >= 0)
|
|
|
|
return false;
|
|
|
|
Uses.insert(&MI);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return isReachingDefLiveOut(&MBB->back(), PhysReg);
|
|
|
|
}
|
|
|
|
|
2020-01-23 14:22:13 +01:00
|
|
|
void
|
|
|
|
ReachingDefAnalysis::getGlobalUses(MachineInstr *MI, int PhysReg,
|
2020-01-28 14:06:07 +01:00
|
|
|
InstSet &Uses) const {
|
2020-01-17 14:08:24 +01:00
|
|
|
MachineBasicBlock *MBB = MI->getParent();
|
|
|
|
|
|
|
|
// Collect the uses that each def touches within the block.
|
|
|
|
getReachingLocalUses(MI, PhysReg, Uses);
|
|
|
|
|
|
|
|
// Handle live-out values.
|
|
|
|
if (auto *LiveOut = getLocalLiveOutMIDef(MI->getParent(), PhysReg)) {
|
|
|
|
if (LiveOut != MI)
|
|
|
|
return;
|
|
|
|
|
|
|
|
SmallVector<MachineBasicBlock*, 4> ToVisit;
|
|
|
|
ToVisit.insert(ToVisit.begin(), MBB->successors().begin(),
|
|
|
|
MBB->successors().end());
|
|
|
|
SmallPtrSet<MachineBasicBlock*, 4>Visited;
|
|
|
|
while (!ToVisit.empty()) {
|
|
|
|
MachineBasicBlock *MBB = ToVisit.back();
|
|
|
|
ToVisit.pop_back();
|
|
|
|
if (Visited.count(MBB) || !MBB->isLiveIn(PhysReg))
|
|
|
|
continue;
|
|
|
|
if (getLiveInUses(MBB, PhysReg, Uses))
|
|
|
|
ToVisit.insert(ToVisit.end(), MBB->successors().begin(),
|
|
|
|
MBB->successors().end());
|
|
|
|
Visited.insert(MBB);
|
|
|
|
}
|
|
|
|
}
|
2019-11-26 11:03:25 +01:00
|
|
|
}
|
|
|
|
|
2020-02-26 12:14:54 +01:00
|
|
|
void
|
|
|
|
ReachingDefAnalysis::getLiveOuts(MachineBasicBlock *MBB, int PhysReg,
|
|
|
|
InstSet &Defs, BlockSet &VisitedBBs) const {
|
|
|
|
if (VisitedBBs.count(MBB))
|
|
|
|
return;
|
|
|
|
|
|
|
|
VisitedBBs.insert(MBB);
|
|
|
|
LivePhysRegs LiveRegs(*TRI);
|
|
|
|
LiveRegs.addLiveOuts(*MBB);
|
|
|
|
if (!LiveRegs.contains(PhysReg))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (auto *Def = getLocalLiveOutMIDef(MBB, PhysReg))
|
|
|
|
Defs.insert(Def);
|
|
|
|
else
|
|
|
|
for (auto *Pred : MBB->predecessors())
|
|
|
|
getLiveOuts(Pred, PhysReg, Defs, VisitedBBs);
|
|
|
|
}
|
|
|
|
|
|
|
|
MachineInstr *ReachingDefAnalysis::getUniqueReachingMIDef(MachineInstr *MI,
|
|
|
|
int PhysReg) const {
|
|
|
|
// If there's a local def before MI, return it.
|
|
|
|
MachineInstr *LocalDef = getReachingLocalMIDef(MI, PhysReg);
|
2020-03-03 16:19:57 +01:00
|
|
|
if (LocalDef && InstIds.lookup(LocalDef) < InstIds.lookup(MI))
|
2020-02-26 12:14:54 +01:00
|
|
|
return LocalDef;
|
|
|
|
|
|
|
|
SmallPtrSet<MachineBasicBlock*, 4> VisitedBBs;
|
|
|
|
SmallPtrSet<MachineInstr*, 2> Incoming;
|
|
|
|
for (auto *Pred : MI->getParent()->predecessors())
|
|
|
|
getLiveOuts(Pred, PhysReg, Incoming, VisitedBBs);
|
|
|
|
|
|
|
|
// If we have a local def and an incoming instruction, then there's not a
|
|
|
|
// unique instruction def.
|
|
|
|
if (!Incoming.empty() && LocalDef)
|
|
|
|
return nullptr;
|
|
|
|
else if (Incoming.size() == 1)
|
|
|
|
return *Incoming.begin();
|
|
|
|
else
|
|
|
|
return LocalDef;
|
|
|
|
}
|
|
|
|
|
|
|
|
MachineInstr *ReachingDefAnalysis::getMIOperand(MachineInstr *MI,
|
|
|
|
unsigned Idx) const {
|
|
|
|
assert(MI->getOperand(Idx).isReg() && "Expected register operand");
|
|
|
|
return getUniqueReachingMIDef(MI, MI->getOperand(Idx).getReg());
|
|
|
|
}
|
|
|
|
|
|
|
|
MachineInstr *ReachingDefAnalysis::getMIOperand(MachineInstr *MI,
|
|
|
|
MachineOperand &MO) const {
|
|
|
|
assert(MO.isReg() && "Expected register operand");
|
|
|
|
return getUniqueReachingMIDef(MI, MO.getReg());
|
|
|
|
}
|
|
|
|
|
2020-01-23 14:22:13 +01:00
|
|
|
bool ReachingDefAnalysis::isRegUsedAfter(MachineInstr *MI, int PhysReg) const {
|
2019-11-26 11:03:25 +01:00
|
|
|
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))
|
2020-01-23 14:22:13 +01:00
|
|
|
return InstIds.lookup(&*Last) > InstIds.lookup(MI);
|
2019-11-26 11:03:25 +01:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-01-29 09:26:11 +01:00
|
|
|
bool ReachingDefAnalysis::isRegDefinedAfter(MachineInstr *MI,
|
|
|
|
int PhysReg) const {
|
|
|
|
MachineBasicBlock *MBB = MI->getParent();
|
|
|
|
if (getReachingDef(MI, PhysReg) != getReachingDef(&MBB->back(), PhysReg))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if (auto *Def = getLocalLiveOutMIDef(MBB, PhysReg))
|
2020-02-26 12:14:54 +01:00
|
|
|
return Def == getReachingLocalMIDef(MI, PhysReg);
|
2020-01-29 09:26:11 +01:00
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-01-23 14:22:13 +01:00
|
|
|
bool
|
|
|
|
ReachingDefAnalysis::isReachingDefLiveOut(MachineInstr *MI, int PhysReg) const {
|
2019-12-20 10:32:36 +01:00
|
|
|
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())
|
2020-02-28 12:14:42 +01:00
|
|
|
if (isValidRegDefOf(MO, PhysReg))
|
2019-12-20 10:32:36 +01:00
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
MachineInstr* ReachingDefAnalysis::getLocalLiveOutMIDef(MachineBasicBlock *MBB,
|
2020-01-23 14:22:13 +01:00
|
|
|
int PhysReg) const {
|
2019-12-20 10:32:36 +01:00
|
|
|
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())
|
2020-02-28 12:14:42 +01:00
|
|
|
if (isValidRegDefOf(MO, PhysReg))
|
2019-12-20 10:32:36 +01:00
|
|
|
return Last;
|
|
|
|
|
|
|
|
return Def < 0 ? nullptr : getInstFromId(MBB, Def);
|
|
|
|
}
|
2020-01-29 09:26:11 +01:00
|
|
|
|
2020-02-06 14:53:09 +01:00
|
|
|
static bool mayHaveSideEffects(MachineInstr &MI) {
|
|
|
|
return MI.mayLoadOrStore() || MI.mayRaiseFPException() ||
|
|
|
|
MI.hasUnmodeledSideEffects() || MI.isTerminator() ||
|
|
|
|
MI.isCall() || MI.isBarrier() || MI.isBranch() || MI.isReturn();
|
|
|
|
}
|
|
|
|
|
2020-01-29 09:26:11 +01:00
|
|
|
// Can we safely move 'From' to just before 'To'? To satisfy this, 'From' must
|
|
|
|
// not define a register that is used by any instructions, after and including,
|
|
|
|
// 'To'. These instructions also must not redefine any of Froms operands.
|
|
|
|
template<typename Iterator>
|
|
|
|
bool ReachingDefAnalysis::isSafeToMove(MachineInstr *From,
|
|
|
|
MachineInstr *To) const {
|
|
|
|
if (From->getParent() != To->getParent())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
SmallSet<int, 2> Defs;
|
|
|
|
// First check that From would compute the same value if moved.
|
|
|
|
for (auto &MO : From->operands()) {
|
2020-02-28 12:14:42 +01:00
|
|
|
if (!isValidReg(MO))
|
2020-01-29 09:26:11 +01:00
|
|
|
continue;
|
|
|
|
if (MO.isDef())
|
|
|
|
Defs.insert(MO.getReg());
|
|
|
|
else if (!hasSameReachingDef(From, To, MO.getReg()))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now walk checking that the rest of the instructions will compute the same
|
2020-02-06 14:53:09 +01:00
|
|
|
// value and that we're not overwriting anything. Don't move the instruction
|
|
|
|
// past any memory, control-flow or other ambigious instructions.
|
2020-01-29 09:26:11 +01:00
|
|
|
for (auto I = ++Iterator(From), E = Iterator(To); I != E; ++I) {
|
2020-02-06 14:53:09 +01:00
|
|
|
if (mayHaveSideEffects(*I))
|
|
|
|
return false;
|
2020-01-29 09:26:11 +01:00
|
|
|
for (auto &MO : I->operands())
|
2020-02-06 14:53:09 +01:00
|
|
|
if (MO.isReg() && MO.getReg() && Defs.count(MO.getReg()))
|
2020-01-29 09:26:11 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ReachingDefAnalysis::isSafeToMoveForwards(MachineInstr *From,
|
|
|
|
MachineInstr *To) const {
|
|
|
|
return isSafeToMove<MachineBasicBlock::reverse_iterator>(From, To);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ReachingDefAnalysis::isSafeToMoveBackwards(MachineInstr *From,
|
|
|
|
MachineInstr *To) const {
|
|
|
|
return isSafeToMove<MachineBasicBlock::iterator>(From, To);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ReachingDefAnalysis::isSafeToRemove(MachineInstr *MI,
|
|
|
|
InstSet &ToRemove) const {
|
|
|
|
SmallPtrSet<MachineInstr*, 1> Ignore;
|
|
|
|
SmallPtrSet<MachineInstr*, 2> Visited;
|
|
|
|
return isSafeToRemove(MI, Visited, ToRemove, Ignore);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
ReachingDefAnalysis::isSafeToRemove(MachineInstr *MI, InstSet &ToRemove,
|
|
|
|
InstSet &Ignore) const {
|
|
|
|
SmallPtrSet<MachineInstr*, 2> Visited;
|
|
|
|
return isSafeToRemove(MI, Visited, ToRemove, Ignore);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
ReachingDefAnalysis::isSafeToRemove(MachineInstr *MI, InstSet &Visited,
|
|
|
|
InstSet &ToRemove, InstSet &Ignore) const {
|
|
|
|
if (Visited.count(MI) || Ignore.count(MI))
|
|
|
|
return true;
|
2020-02-06 14:53:09 +01:00
|
|
|
else if (mayHaveSideEffects(*MI)) {
|
2020-01-29 09:26:11 +01:00
|
|
|
// Unless told to ignore the instruction, don't remove anything which has
|
|
|
|
// side effects.
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
Visited.insert(MI);
|
|
|
|
for (auto &MO : MI->operands()) {
|
2020-02-28 12:14:42 +01:00
|
|
|
if (!isValidRegDef(MO))
|
2020-01-29 09:26:11 +01:00
|
|
|
continue;
|
|
|
|
|
|
|
|
SmallPtrSet<MachineInstr*, 4> Uses;
|
|
|
|
getGlobalUses(MI, MO.getReg(), Uses);
|
|
|
|
|
|
|
|
for (auto I : Uses) {
|
|
|
|
if (Ignore.count(I) || ToRemove.count(I))
|
|
|
|
continue;
|
|
|
|
if (!isSafeToRemove(I, Visited, ToRemove, Ignore))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ToRemove.insert(MI);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-03-03 16:19:57 +01:00
|
|
|
void ReachingDefAnalysis::collectKilledOperands(MachineInstr *MI,
|
|
|
|
InstSet &Dead) const {
|
2020-02-24 14:50:46 +01:00
|
|
|
Dead.insert(MI);
|
2020-02-27 11:54:08 +01:00
|
|
|
auto IsDead = [this, &Dead](MachineInstr *Def, int PhysReg) {
|
2020-02-24 14:50:46 +01:00
|
|
|
unsigned LiveDefs = 0;
|
2020-02-28 12:14:42 +01:00
|
|
|
for (auto &MO : Def->operands()) {
|
|
|
|
if (!isValidRegDef(MO))
|
|
|
|
continue;
|
2020-02-24 14:50:46 +01:00
|
|
|
if (!MO.isDead())
|
|
|
|
++LiveDefs;
|
2020-02-28 12:14:42 +01:00
|
|
|
}
|
2020-02-24 14:50:46 +01:00
|
|
|
|
|
|
|
if (LiveDefs > 1)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
SmallPtrSet<MachineInstr*, 4> Uses;
|
|
|
|
getGlobalUses(Def, PhysReg, Uses);
|
2020-02-27 11:54:08 +01:00
|
|
|
for (auto *Use : Uses)
|
|
|
|
if (!Dead.count(Use))
|
|
|
|
return false;
|
|
|
|
return true;
|
2020-02-24 14:50:46 +01:00
|
|
|
};
|
|
|
|
|
2020-02-28 12:14:42 +01:00
|
|
|
for (auto &MO : MI->operands()) {
|
2020-03-03 16:19:57 +01:00
|
|
|
if (!isValidRegUse(MO))
|
2020-02-24 14:50:46 +01:00
|
|
|
continue;
|
2020-03-03 16:19:57 +01:00
|
|
|
if (MachineInstr *Def = getMIOperand(MI, MO))
|
2020-02-24 14:50:46 +01:00
|
|
|
if (IsDead(Def, MO.getReg()))
|
2020-03-03 16:19:57 +01:00
|
|
|
collectKilledOperands(Def, Dead);
|
2020-02-24 14:50:46 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-29 09:26:11 +01:00
|
|
|
bool ReachingDefAnalysis::isSafeToDefRegAt(MachineInstr *MI,
|
|
|
|
int PhysReg) const {
|
|
|
|
SmallPtrSet<MachineInstr*, 1> Ignore;
|
|
|
|
return isSafeToDefRegAt(MI, PhysReg, Ignore);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ReachingDefAnalysis::isSafeToDefRegAt(MachineInstr *MI, int PhysReg,
|
|
|
|
InstSet &Ignore) const {
|
|
|
|
// Check for any uses of the register after MI.
|
|
|
|
if (isRegUsedAfter(MI, PhysReg)) {
|
2020-02-26 12:14:54 +01:00
|
|
|
if (auto *Def = getReachingLocalMIDef(MI, PhysReg)) {
|
2020-01-29 09:26:11 +01:00
|
|
|
SmallPtrSet<MachineInstr*, 2> Uses;
|
|
|
|
getReachingLocalUses(Def, PhysReg, Uses);
|
|
|
|
for (auto *Use : Uses)
|
|
|
|
if (!Ignore.count(Use))
|
|
|
|
return false;
|
|
|
|
} else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
MachineBasicBlock *MBB = MI->getParent();
|
|
|
|
// Check for any defs after MI.
|
|
|
|
if (isRegDefinedAfter(MI, PhysReg)) {
|
|
|
|
auto I = MachineBasicBlock::iterator(MI);
|
|
|
|
for (auto E = MBB->end(); I != E; ++I) {
|
|
|
|
if (Ignore.count(&*I))
|
|
|
|
continue;
|
|
|
|
for (auto &MO : I->operands())
|
2020-02-28 12:14:42 +01:00
|
|
|
if (isValidRegDefOf(MO, PhysReg))
|
2020-01-29 09:26:11 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|