mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-08-07 12:28:24 +00:00
ExecutionDepsFix: Correctly handle wide registers.
The ExecutionDepsFix previously mapped each register to 1 or zero registers of the register class it was called with and therefore simulating liveness for. This was problematic for cases involving wider registers like Q0 on ARM where ExecutionDepsFix gets invoked for the Dxx registers. In these cases the wide register would get mapped to the last matching D register, while it should have been all matching D registers. This commit changes the AliasMap to use a SmallVector to map registers to potentially multiple destination regclass registers. This is required to avoid regressions with subregister liveness tracking enabled. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@224447 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -22,6 +22,7 @@
|
||||
|
||||
#include "llvm/CodeGen/Passes.h"
|
||||
#include "llvm/ADT/PostOrderIterator.h"
|
||||
#include "llvm/ADT/iterator_range.h"
|
||||
#include "llvm/CodeGen/LivePhysRegs.h"
|
||||
#include "llvm/CodeGen/MachineFunctionPass.h"
|
||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||
@@ -136,7 +137,7 @@ class ExeDepsFix : public MachineFunctionPass {
|
||||
MachineFunction *MF;
|
||||
const TargetInstrInfo *TII;
|
||||
const TargetRegisterInfo *TRI;
|
||||
std::vector<int> AliasMap;
|
||||
std::vector<SmallVector<int, 1>> AliasMap;
|
||||
const unsigned NumRegs;
|
||||
LiveReg *LiveRegs;
|
||||
typedef DenseMap<MachineBasicBlock*, LiveReg*> LiveOutMap;
|
||||
@@ -172,8 +173,8 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
// Register mapping.
|
||||
int regIndex(unsigned Reg);
|
||||
iterator_range<SmallVectorImpl<int>::const_iterator>
|
||||
regIndizes(unsigned Reg) const;
|
||||
|
||||
// DomainValue allocation.
|
||||
DomainValue *alloc(int domain = -1);
|
||||
@@ -204,11 +205,13 @@ private:
|
||||
|
||||
char ExeDepsFix::ID = 0;
|
||||
|
||||
/// Translate TRI register number to an index into our smaller tables of
|
||||
/// interesting registers. Return -1 for boring registers.
|
||||
int ExeDepsFix::regIndex(unsigned Reg) {
|
||||
/// Translate TRI register number to a list of indizes into our stmaller tables
|
||||
/// of interesting registers.
|
||||
iterator_range<SmallVectorImpl<int>::const_iterator>
|
||||
ExeDepsFix::regIndizes(unsigned Reg) const {
|
||||
assert(Reg < AliasMap.size() && "Invalid register");
|
||||
return AliasMap[Reg];
|
||||
const auto &Entry = AliasMap[Reg];
|
||||
return make_range(Entry.begin(), Entry.end());
|
||||
}
|
||||
|
||||
DomainValue *ExeDepsFix::alloc(int domain) {
|
||||
@@ -375,14 +378,13 @@ void ExeDepsFix::enterBasicBlock(MachineBasicBlock *MBB) {
|
||||
if (MBB->pred_empty()) {
|
||||
for (MachineBasicBlock::livein_iterator i = MBB->livein_begin(),
|
||||
e = MBB->livein_end(); i != e; ++i) {
|
||||
int rx = regIndex(*i);
|
||||
if (rx < 0)
|
||||
continue;
|
||||
for (int rx : regIndizes(*i)) {
|
||||
// Treat function live-ins as if they were defined just before the first
|
||||
// instruction. Usually, function arguments are set up immediately
|
||||
// before the call.
|
||||
LiveRegs[rx].Def = -1;
|
||||
}
|
||||
}
|
||||
DEBUG(dbgs() << "BB#" << MBB->getNumber() << ": entry\n");
|
||||
return;
|
||||
}
|
||||
@@ -472,16 +474,14 @@ void ExeDepsFix::visitInstr(MachineInstr *MI) {
|
||||
/// or undef use.
|
||||
bool ExeDepsFix::shouldBreakDependence(MachineInstr *MI, unsigned OpIdx,
|
||||
unsigned Pref) {
|
||||
int rx = regIndex(MI->getOperand(OpIdx).getReg());
|
||||
if (rx < 0)
|
||||
return false;
|
||||
|
||||
unsigned reg = MI->getOperand(OpIdx).getReg();
|
||||
for (int rx : regIndizes(reg)) {
|
||||
unsigned Clearance = CurInstr - LiveRegs[rx].Def;
|
||||
DEBUG(dbgs() << "Clearance: " << Clearance << ", want " << Pref);
|
||||
|
||||
if (Pref > Clearance) {
|
||||
DEBUG(dbgs() << ": Break dependency.\n");
|
||||
return true;
|
||||
continue;
|
||||
}
|
||||
// The current clearance seems OK, but we may be ignoring a def from a
|
||||
// back-edge.
|
||||
@@ -493,6 +493,8 @@ bool ExeDepsFix::shouldBreakDependence(MachineInstr *MI, unsigned OpIdx,
|
||||
DEBUG(dbgs() << ": Wait for back-edge to resolve.\n");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Update def-ages for registers defined by MI.
|
||||
// If Kill is set, also kill off DomainValues clobbered by the defs.
|
||||
@@ -519,10 +521,7 @@ void ExeDepsFix::processDefs(MachineInstr *MI, bool Kill) {
|
||||
break;
|
||||
if (MO.isUse())
|
||||
continue;
|
||||
int rx = regIndex(MO.getReg());
|
||||
if (rx < 0)
|
||||
continue;
|
||||
|
||||
for (int rx : regIndizes(MO.getReg())) {
|
||||
// This instruction explicitly defines rx.
|
||||
DEBUG(dbgs() << TRI->getName(RC->getRegister(rx)) << ":\t" << CurInstr
|
||||
<< '\t' << *MI);
|
||||
@@ -540,6 +539,7 @@ void ExeDepsFix::processDefs(MachineInstr *MI, bool Kill) {
|
||||
if (Kill)
|
||||
kill(rx);
|
||||
}
|
||||
}
|
||||
++CurInstr;
|
||||
}
|
||||
|
||||
@@ -587,21 +587,21 @@ void ExeDepsFix::visitHardInstr(MachineInstr *mi, unsigned domain) {
|
||||
e = mi->getDesc().getNumOperands(); i != e; ++i) {
|
||||
MachineOperand &mo = mi->getOperand(i);
|
||||
if (!mo.isReg()) continue;
|
||||
int rx = regIndex(mo.getReg());
|
||||
if (rx < 0) continue;
|
||||
for (int rx : regIndizes(mo.getReg())) {
|
||||
force(rx, domain);
|
||||
}
|
||||
}
|
||||
|
||||
// Kill all defs and force them.
|
||||
for (unsigned i = 0, e = mi->getDesc().getNumDefs(); i != e; ++i) {
|
||||
MachineOperand &mo = mi->getOperand(i);
|
||||
if (!mo.isReg()) continue;
|
||||
int rx = regIndex(mo.getReg());
|
||||
if (rx < 0) continue;
|
||||
for (int rx : regIndizes(mo.getReg())) {
|
||||
kill(rx);
|
||||
force(rx, domain);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// A soft instruction can be changed to work in other domains given by mask.
|
||||
void ExeDepsFix::visitSoftInstr(MachineInstr *mi, unsigned mask) {
|
||||
@@ -616,9 +616,10 @@ void ExeDepsFix::visitSoftInstr(MachineInstr *mi, unsigned mask) {
|
||||
e = mi->getDesc().getNumOperands(); i != e; ++i) {
|
||||
MachineOperand &mo = mi->getOperand(i);
|
||||
if (!mo.isReg()) continue;
|
||||
int rx = regIndex(mo.getReg());
|
||||
if (rx < 0) continue;
|
||||
if (DomainValue *dv = LiveRegs[rx].Value) {
|
||||
for (int rx : regIndizes(mo.getReg())) {
|
||||
DomainValue *dv = LiveRegs[rx].Value;
|
||||
if (dv == nullptr)
|
||||
continue;
|
||||
// Bitmask of domains that dv and available have in common.
|
||||
unsigned common = dv->getCommonDomains(available);
|
||||
// Is it possible to use this collapsed register for free?
|
||||
@@ -711,14 +712,14 @@ void ExeDepsFix::visitSoftInstr(MachineInstr *mi, unsigned mask) {
|
||||
ii != ee; ++ii) {
|
||||
MachineOperand &mo = *ii;
|
||||
if (!mo.isReg()) continue;
|
||||
int rx = regIndex(mo.getReg());
|
||||
if (rx < 0) continue;
|
||||
for (int rx : regIndizes(mo.getReg())) {
|
||||
if (!LiveRegs[rx].Value || (mo.isDef() && LiveRegs[rx].Value != dv)) {
|
||||
kill(rx);
|
||||
setLiveReg(rx, dv);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ExeDepsFix::runOnMachineFunction(MachineFunction &mf) {
|
||||
MF = &mf;
|
||||
@@ -743,13 +744,13 @@ bool ExeDepsFix::runOnMachineFunction(MachineFunction &mf) {
|
||||
|
||||
// Initialize the AliasMap on the first use.
|
||||
if (AliasMap.empty()) {
|
||||
// Given a PhysReg, AliasMap[PhysReg] is either the relevant index into RC,
|
||||
// or -1.
|
||||
AliasMap.resize(TRI->getNumRegs(), -1);
|
||||
// Given a PhysReg, AliasMap[PhysReg] returns a list of indices into RC and
|
||||
// therefore the LiveRegs array.
|
||||
AliasMap.resize(TRI->getNumRegs());
|
||||
for (unsigned i = 0, e = RC->getNumRegs(); i != e; ++i)
|
||||
for (MCRegAliasIterator AI(RC->getRegister(i), TRI, true);
|
||||
AI.isValid(); ++AI)
|
||||
AliasMap[*AI] = i;
|
||||
AliasMap[*AI].push_back(i);
|
||||
}
|
||||
|
||||
MachineBasicBlock *Entry = MF->begin();
|
||||
|
Reference in New Issue
Block a user