mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-23 01:24:30 +00:00
Make load / store optimizer use register scavenger.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@34986 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -59,6 +59,8 @@ namespace {
|
|||||||
typedef SmallVector<MemOpQueueEntry,8> MemOpQueue;
|
typedef SmallVector<MemOpQueueEntry,8> MemOpQueue;
|
||||||
typedef MemOpQueue::iterator MemOpQueueIter;
|
typedef MemOpQueue::iterator MemOpQueueIter;
|
||||||
|
|
||||||
|
void AdvanceRS(MachineBasicBlock *MBB, MemOpQueue &MemOps);
|
||||||
|
|
||||||
SmallVector<MachineBasicBlock::iterator, 4>
|
SmallVector<MachineBasicBlock::iterator, 4>
|
||||||
MergeLDR_STR(MachineBasicBlock &MBB, unsigned SIndex, unsigned Base,
|
MergeLDR_STR(MachineBasicBlock &MBB, unsigned SIndex, unsigned Base,
|
||||||
int Opcode, unsigned Size, MemOpQueue &MemOps);
|
int Opcode, unsigned Size, MemOpQueue &MemOps);
|
||||||
@ -103,8 +105,9 @@ static int getLoadStoreMultipleOpcode(int Opcode) {
|
|||||||
/// registers in Regs as the register operands that would be loaded / stored.
|
/// registers in Regs as the register operands that would be loaded / stored.
|
||||||
/// It returns true if the transformation is done.
|
/// It returns true if the transformation is done.
|
||||||
static bool mergeOps(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
|
static bool mergeOps(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
|
||||||
int Offset, unsigned Base, int Opcode,
|
int Offset, unsigned Base, bool BaseKill, int Opcode,
|
||||||
SmallVector<unsigned, 8> &Regs,
|
SmallVector<std::pair<unsigned, bool>, 8> &Regs,
|
||||||
|
RegScavenger *RS,
|
||||||
const TargetInstrInfo *TII) {
|
const TargetInstrInfo *TII) {
|
||||||
// Only a single register to load / store. Don't bother.
|
// Only a single register to load / store. Don't bother.
|
||||||
unsigned NumRegs = Regs.size();
|
unsigned NumRegs = Regs.size();
|
||||||
@ -130,10 +133,12 @@ static bool mergeOps(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
|
|||||||
if (Opcode == ARM::LDR)
|
if (Opcode == ARM::LDR)
|
||||||
// If it is a load, then just use one of the destination register to
|
// If it is a load, then just use one of the destination register to
|
||||||
// use as the new base.
|
// use as the new base.
|
||||||
NewBase = Regs[NumRegs-1];
|
NewBase = Regs[NumRegs-1].first;
|
||||||
else {
|
else {
|
||||||
// FIXME: Try scavenging a register to use as a new base.
|
// Try to find a free register to use as a new base.
|
||||||
NewBase = ARM::R12;
|
NewBase = RS ? RS->FindUnusedReg(&ARM::GPRRegClass) : (unsigned)ARM::R12;
|
||||||
|
if (NewBase == 0)
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
int BaseOpc = ARM::ADDri;
|
int BaseOpc = ARM::ADDri;
|
||||||
if (Offset < 0) {
|
if (Offset < 0) {
|
||||||
@ -143,52 +148,78 @@ static bool mergeOps(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
|
|||||||
int ImmedOffset = ARM_AM::getSOImmVal(Offset);
|
int ImmedOffset = ARM_AM::getSOImmVal(Offset);
|
||||||
if (ImmedOffset == -1)
|
if (ImmedOffset == -1)
|
||||||
return false; // Probably not worth it then.
|
return false; // Probably not worth it then.
|
||||||
BuildMI(MBB, MBBI, TII->get(BaseOpc), NewBase).addReg(Base).addImm(ImmedOffset);
|
|
||||||
|
BuildMI(MBB, MBBI, TII->get(BaseOpc), NewBase)
|
||||||
|
.addReg(Base, false, false, BaseKill).addImm(ImmedOffset);
|
||||||
Base = NewBase;
|
Base = NewBase;
|
||||||
|
BaseKill = true; // New base is always killed right its use.
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isDPR = Opcode == ARM::FLDD || Opcode == ARM::FSTD;
|
bool isDPR = Opcode == ARM::FLDD || Opcode == ARM::FSTD;
|
||||||
bool isDef = Opcode == ARM::LDR || Opcode == ARM::FLDS || Opcode == ARM::FLDD;
|
bool isDef = Opcode == ARM::LDR || Opcode == ARM::FLDS || Opcode == ARM::FLDD;
|
||||||
Opcode = getLoadStoreMultipleOpcode(Opcode);
|
Opcode = getLoadStoreMultipleOpcode(Opcode);
|
||||||
MachineInstrBuilder MIB = (isAM4)
|
MachineInstrBuilder MIB = (isAM4)
|
||||||
? BuildMI(MBB, MBBI, TII->get(Opcode)).addReg(Base)
|
? BuildMI(MBB, MBBI, TII->get(Opcode)).addReg(Base, false, false, BaseKill)
|
||||||
.addImm(ARM_AM::getAM4ModeImm(Mode))
|
.addImm(ARM_AM::getAM4ModeImm(Mode))
|
||||||
: BuildMI(MBB, MBBI, TII->get(Opcode)).addReg(Base)
|
: BuildMI(MBB, MBBI, TII->get(Opcode)).addReg(Base, false, false, BaseKill)
|
||||||
.addImm(ARM_AM::getAM5Opc(Mode, false, isDPR ? NumRegs<<1 : NumRegs));
|
.addImm(ARM_AM::getAM5Opc(Mode, false, isDPR ? NumRegs<<1 : NumRegs));
|
||||||
for (unsigned i = 0; i != NumRegs; ++i)
|
for (unsigned i = 0; i != NumRegs; ++i)
|
||||||
MIB = MIB.addReg(Regs[i], Opcode == isDef);
|
MIB = MIB.addReg(Regs[i].first, isDef, false, Regs[i].second);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// AdvanceRS - Advance register scavenger to just before the earliest memory
|
||||||
|
/// op that is being merged.
|
||||||
|
void ARMLoadStoreOpt::AdvanceRS(MachineBasicBlock *MBB, MemOpQueue &MemOps) {
|
||||||
|
MachineBasicBlock::iterator Loc = MemOps[0].MBBI;
|
||||||
|
unsigned Position = MemOps[0].Position;
|
||||||
|
for (unsigned i = 1, e = MemOps.size(); i != e; ++i) {
|
||||||
|
if (MemOps[i].Position < Position) {
|
||||||
|
Position = MemOps[i].Position;
|
||||||
|
Loc = MemOps[i].MBBI;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Loc != MBB->begin())
|
||||||
|
RS->forward(prior(Loc));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// MergeLDR_STR - Merge a number of load / store instructions into one or more
|
||||||
|
/// load / store multiple instructions.
|
||||||
SmallVector<MachineBasicBlock::iterator, 4>
|
SmallVector<MachineBasicBlock::iterator, 4>
|
||||||
ARMLoadStoreOpt::MergeLDR_STR(MachineBasicBlock &MBB,
|
ARMLoadStoreOpt::MergeLDR_STR(MachineBasicBlock &MBB,
|
||||||
unsigned SIndex, unsigned Base, int Opcode,
|
unsigned SIndex, unsigned Base, int Opcode,
|
||||||
unsigned Size, MemOpQueue &MemOps) {
|
unsigned Size, MemOpQueue &MemOps) {
|
||||||
bool isAM4 = Opcode == ARM::LDR || Opcode == ARM::STR;
|
if (RS && SIndex == 0)
|
||||||
|
AdvanceRS(&MBB, MemOps);
|
||||||
|
|
||||||
SmallVector<MachineBasicBlock::iterator, 4> Merges;
|
SmallVector<MachineBasicBlock::iterator, 4> Merges;
|
||||||
|
SmallVector<std::pair<unsigned,bool>, 8> Regs;
|
||||||
|
bool isAM4 = Opcode == ARM::LDR || Opcode == ARM::STR;
|
||||||
int Offset = MemOps[SIndex].Offset;
|
int Offset = MemOps[SIndex].Offset;
|
||||||
int SOffset = Offset;
|
int SOffset = Offset;
|
||||||
unsigned Pos = MemOps[SIndex].Position;
|
unsigned Pos = MemOps[SIndex].Position;
|
||||||
MachineBasicBlock::iterator Loc = MemOps[SIndex].MBBI;
|
MachineBasicBlock::iterator Loc = MemOps[SIndex].MBBI;
|
||||||
SmallVector<unsigned, 8> Regs;
|
|
||||||
unsigned PReg = MemOps[SIndex].MBBI->getOperand(0).getReg();
|
unsigned PReg = MemOps[SIndex].MBBI->getOperand(0).getReg();
|
||||||
unsigned PRegNum = ARMRegisterInfo::getRegisterNumbering(PReg);
|
unsigned PRegNum = ARMRegisterInfo::getRegisterNumbering(PReg);
|
||||||
Regs.push_back(PReg);
|
bool isKill = MemOps[SIndex].MBBI->getOperand(0).isKill();
|
||||||
|
Regs.push_back(std::make_pair(PReg, isKill));
|
||||||
for (unsigned i = SIndex+1, e = MemOps.size(); i != e; ++i) {
|
for (unsigned i = SIndex+1, e = MemOps.size(); i != e; ++i) {
|
||||||
int NewOffset = MemOps[i].Offset;
|
int NewOffset = MemOps[i].Offset;
|
||||||
unsigned Reg = MemOps[i].MBBI->getOperand(0).getReg();
|
unsigned Reg = MemOps[i].MBBI->getOperand(0).getReg();
|
||||||
unsigned RegNum = ARMRegisterInfo::getRegisterNumbering(Reg);
|
unsigned RegNum = ARMRegisterInfo::getRegisterNumbering(Reg);
|
||||||
|
isKill = MemOps[i].MBBI->getOperand(0).isKill();
|
||||||
// AM4 - register numbers in ascending order.
|
// AM4 - register numbers in ascending order.
|
||||||
// AM5 - consecutive register numbers in ascending order.
|
// AM5 - consecutive register numbers in ascending order.
|
||||||
if (NewOffset == Offset + (int)Size &&
|
if (NewOffset == Offset + (int)Size &&
|
||||||
((isAM4 && RegNum > PRegNum) || RegNum == PRegNum+1)) {
|
((isAM4 && RegNum > PRegNum) || RegNum == PRegNum+1)) {
|
||||||
Offset += Size;
|
Offset += Size;
|
||||||
Regs.push_back(Reg);
|
Regs.push_back(std::make_pair(Reg, isKill));
|
||||||
PRegNum = RegNum;
|
PRegNum = RegNum;
|
||||||
} else {
|
} else {
|
||||||
// Can't merge this in. Try merge the earlier ones first.
|
// Can't merge this in. Try merge the earlier ones first.
|
||||||
if (mergeOps(MBB, ++Loc, SOffset, Base, Opcode, Regs, TII)) {
|
if (mergeOps(MBB, ++Loc, SOffset, Base, false, Opcode, Regs, RS, TII)) {
|
||||||
Merges.push_back(prior(Loc));
|
Merges.push_back(prior(Loc));
|
||||||
for (unsigned j = SIndex; j < i; ++j) {
|
for (unsigned j = SIndex; j < i; ++j) {
|
||||||
MBB.erase(MemOps[j].MBBI);
|
MBB.erase(MemOps[j].MBBI);
|
||||||
@ -207,7 +238,8 @@ ARMLoadStoreOpt::MergeLDR_STR(MachineBasicBlock &MBB,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mergeOps(MBB, ++Loc, SOffset, Base, Opcode, Regs, TII)) {
|
bool BaseKill = Loc->findRegisterUseOperand(Base, true) != NULL;
|
||||||
|
if (mergeOps(MBB, ++Loc, SOffset, Base, BaseKill, Opcode, Regs, RS, TII)) {
|
||||||
Merges.push_back(prior(Loc));
|
Merges.push_back(prior(Loc));
|
||||||
for (unsigned i = SIndex, e = MemOps.size(); i != e; ++i) {
|
for (unsigned i = SIndex, e = MemOps.size(); i != e; ++i) {
|
||||||
MBB.erase(MemOps[i].MBBI);
|
MBB.erase(MemOps[i].MBBI);
|
||||||
@ -381,6 +413,7 @@ static bool mergeBaseUpdateLoadStore(MachineBasicBlock &MBB,
|
|||||||
const TargetInstrInfo *TII) {
|
const TargetInstrInfo *TII) {
|
||||||
MachineInstr *MI = MBBI;
|
MachineInstr *MI = MBBI;
|
||||||
unsigned Base = MI->getOperand(1).getReg();
|
unsigned Base = MI->getOperand(1).getReg();
|
||||||
|
bool BaseKill = MI->getOperand(1).isKill();
|
||||||
unsigned Bytes = getLSMultipleTransferSize(MI);
|
unsigned Bytes = getLSMultipleTransferSize(MI);
|
||||||
int Opcode = MI->getOpcode();
|
int Opcode = MI->getOpcode();
|
||||||
bool isAM2 = Opcode == ARM::LDR || Opcode == ARM::STR;
|
bool isAM2 = Opcode == ARM::LDR || Opcode == ARM::STR;
|
||||||
@ -434,18 +467,23 @@ static bool mergeBaseUpdateLoadStore(MachineBasicBlock &MBB,
|
|||||||
true, isDPR ? 2 : 1);
|
true, isDPR ? 2 : 1);
|
||||||
if (isLd) {
|
if (isLd) {
|
||||||
if (isAM2)
|
if (isAM2)
|
||||||
|
// LDR_PRE, LDR_POST;
|
||||||
BuildMI(MBB, MBBI, TII->get(NewOpc), MI->getOperand(0).getReg())
|
BuildMI(MBB, MBBI, TII->get(NewOpc), MI->getOperand(0).getReg())
|
||||||
.addReg(Base, true).addReg(Base).addReg(0).addImm(Offset);
|
.addReg(Base, true)
|
||||||
|
.addReg(Base).addReg(0).addImm(Offset);
|
||||||
else
|
else
|
||||||
BuildMI(MBB, MBBI, TII->get(NewOpc)).addReg(Base)
|
BuildMI(MBB, MBBI, TII->get(NewOpc)).addReg(Base, false, false, BaseKill)
|
||||||
.addImm(Offset).addReg(MI->getOperand(0).getReg(), true);
|
.addImm(Offset).addReg(MI->getOperand(0).getReg(), true);
|
||||||
} else {
|
} else {
|
||||||
|
MachineOperand &MO = MI->getOperand(0);
|
||||||
if (isAM2)
|
if (isAM2)
|
||||||
BuildMI(MBB, MBBI, TII->get(NewOpc), Base).addReg(MI->getOperand(0).getReg())
|
// STR_PRE, STR_POST;
|
||||||
|
BuildMI(MBB, MBBI, TII->get(NewOpc), Base)
|
||||||
|
.addReg(MO.getReg(), false, false, MO.isKill())
|
||||||
.addReg(Base).addReg(0).addImm(Offset);
|
.addReg(Base).addReg(0).addImm(Offset);
|
||||||
else
|
else
|
||||||
BuildMI(MBB, MBBI, TII->get(NewOpc)).addReg(Base)
|
BuildMI(MBB, MBBI, TII->get(NewOpc)).addReg(Base)
|
||||||
.addImm(Offset).addReg(MI->getOperand(0).getReg(), false);
|
.addImm(Offset).addReg(MO.getReg(), false, false, MO.isKill());
|
||||||
}
|
}
|
||||||
MBB.erase(MBBI);
|
MBB.erase(MBBI);
|
||||||
|
|
||||||
@ -494,7 +532,6 @@ bool ARMLoadStoreOpt::LoadStoreMultipleOpti(MachineBasicBlock &MBB) {
|
|||||||
int Opcode = MBBI->getOpcode();
|
int Opcode = MBBI->getOpcode();
|
||||||
bool isAM2 = Opcode == ARM::LDR || Opcode == ARM::STR;
|
bool isAM2 = Opcode == ARM::LDR || Opcode == ARM::STR;
|
||||||
unsigned Size = getLSMultipleTransferSize(MBBI);
|
unsigned Size = getLSMultipleTransferSize(MBBI);
|
||||||
|
|
||||||
unsigned Base = MBBI->getOperand(1).getReg();
|
unsigned Base = MBBI->getOperand(1).getReg();
|
||||||
unsigned OffIdx = MBBI->getNumOperands()-1;
|
unsigned OffIdx = MBBI->getNumOperands()-1;
|
||||||
unsigned OffField = MBBI->getOperand(OffIdx).getImm();
|
unsigned OffField = MBBI->getOperand(OffIdx).getImm();
|
||||||
@ -564,7 +601,7 @@ bool ARMLoadStoreOpt::LoadStoreMultipleOpti(MachineBasicBlock &MBB) {
|
|||||||
if (TryMerge) {
|
if (TryMerge) {
|
||||||
if (NumMemOps > 1) {
|
if (NumMemOps > 1) {
|
||||||
SmallVector<MachineBasicBlock::iterator,4> MBBII =
|
SmallVector<MachineBasicBlock::iterator,4> MBBII =
|
||||||
MergeLDR_STR(MBB, 0, CurrBase, CurrOpc, CurrSize,MemOps);
|
MergeLDR_STR(MBB, 0, CurrBase, CurrOpc, CurrSize, MemOps);
|
||||||
// Try folding preceeding/trailing base inc/dec into the generated
|
// Try folding preceeding/trailing base inc/dec into the generated
|
||||||
// LDM/STM ops.
|
// LDM/STM ops.
|
||||||
for (unsigned i = 0, e = MBBII.size(); i < e; ++i)
|
for (unsigned i = 0, e = MBBII.size(); i < e; ++i)
|
||||||
|
Reference in New Issue
Block a user