mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-12 13:30:51 +00:00
Initial support for load / store multiple opt pass Thumb2 support (post-allocation only). It's kind of there, but not quite. I'll return to this later.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@75190 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
c50a1cbf5f
commit
45032f2801
@ -62,6 +62,7 @@ namespace {
|
|||||||
const TargetRegisterInfo *TRI;
|
const TargetRegisterInfo *TRI;
|
||||||
ARMFunctionInfo *AFI;
|
ARMFunctionInfo *AFI;
|
||||||
RegScavenger *RS;
|
RegScavenger *RS;
|
||||||
|
bool isThumb2;
|
||||||
|
|
||||||
virtual bool runOnMachineFunction(MachineFunction &Fn);
|
virtual bool runOnMachineFunction(MachineFunction &Fn);
|
||||||
|
|
||||||
@ -94,6 +95,15 @@ namespace {
|
|||||||
void AdvanceRS(MachineBasicBlock &MBB, MemOpQueue &MemOps);
|
void AdvanceRS(MachineBasicBlock &MBB, MemOpQueue &MemOps);
|
||||||
bool FixInvalidRegPairOp(MachineBasicBlock &MBB,
|
bool FixInvalidRegPairOp(MachineBasicBlock &MBB,
|
||||||
MachineBasicBlock::iterator &MBBI);
|
MachineBasicBlock::iterator &MBBI);
|
||||||
|
bool MergeBaseUpdateLoadStore(MachineBasicBlock &MBB,
|
||||||
|
MachineBasicBlock::iterator MBBI,
|
||||||
|
const TargetInstrInfo *TII,
|
||||||
|
bool &Advance,
|
||||||
|
MachineBasicBlock::iterator &I);
|
||||||
|
bool MergeBaseUpdateLSMultiple(MachineBasicBlock &MBB,
|
||||||
|
MachineBasicBlock::iterator MBBI,
|
||||||
|
bool &Advance,
|
||||||
|
MachineBasicBlock::iterator &I);
|
||||||
bool LoadStoreMultipleOpti(MachineBasicBlock &MBB);
|
bool LoadStoreMultipleOpti(MachineBasicBlock &MBB);
|
||||||
bool MergeReturnIntoLDM(MachineBasicBlock &MBB);
|
bool MergeReturnIntoLDM(MachineBasicBlock &MBB);
|
||||||
};
|
};
|
||||||
@ -108,6 +118,14 @@ static int getLoadStoreMultipleOpcode(int Opcode) {
|
|||||||
case ARM::STR:
|
case ARM::STR:
|
||||||
NumSTMGened++;
|
NumSTMGened++;
|
||||||
return ARM::STM;
|
return ARM::STM;
|
||||||
|
case ARM::t2LDRi8:
|
||||||
|
case ARM::t2LDRi12:
|
||||||
|
NumLDMGened++;
|
||||||
|
return ARM::t2LDM;
|
||||||
|
case ARM::t2STRi8:
|
||||||
|
case ARM::t2STRi12:
|
||||||
|
NumSTMGened++;
|
||||||
|
return ARM::t2STM;
|
||||||
case ARM::FLDS:
|
case ARM::FLDS:
|
||||||
NumFLDMGened++;
|
NumFLDMGened++;
|
||||||
return ARM::FLDMS;
|
return ARM::FLDMS;
|
||||||
@ -125,6 +143,14 @@ static int getLoadStoreMultipleOpcode(int Opcode) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool isi32Load(unsigned Opc) {
|
||||||
|
return Opc == ARM::LDR || Opc == ARM::t2LDRi12 || Opc == ARM::t2LDRi8;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isi32Store(unsigned Opc) {
|
||||||
|
return Opc == ARM::STR || Opc == ARM::t2STRi12 || Opc == ARM::t2STRi8;
|
||||||
|
}
|
||||||
|
|
||||||
/// MergeOps - Create and insert a LDM or STM with Base as base register and
|
/// MergeOps - Create and insert a LDM or STM with Base as base register and
|
||||||
/// 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.
|
||||||
@ -141,7 +167,7 @@ ARMLoadStoreOpt::MergeOps(MachineBasicBlock &MBB,
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
ARM_AM::AMSubMode Mode = ARM_AM::ia;
|
ARM_AM::AMSubMode Mode = ARM_AM::ia;
|
||||||
bool isAM4 = Opcode == ARM::LDR || Opcode == ARM::STR;
|
bool isAM4 = isi32Load(Opcode) || isi32Store(Opcode);
|
||||||
if (isAM4 && Offset == 4)
|
if (isAM4 && Offset == 4)
|
||||||
Mode = ARM_AM::ib;
|
Mode = ARM_AM::ib;
|
||||||
else if (isAM4 && Offset == -4 * (int)NumRegs + 4)
|
else if (isAM4 && Offset == -4 * (int)NumRegs + 4)
|
||||||
@ -156,7 +182,7 @@ ARMLoadStoreOpt::MergeOps(MachineBasicBlock &MBB,
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
unsigned NewBase;
|
unsigned NewBase;
|
||||||
if (Opcode == ARM::LDR)
|
if (isi32Load(Opcode))
|
||||||
// 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].first;
|
NewBase = Regs[NumRegs-1].first;
|
||||||
@ -166,12 +192,15 @@ ARMLoadStoreOpt::MergeOps(MachineBasicBlock &MBB,
|
|||||||
if (NewBase == 0)
|
if (NewBase == 0)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
int BaseOpc = ARM::ADDri;
|
int BaseOpc = isThumb2 ? ARM::t2ADDri : ARM::ADDri;
|
||||||
if (Offset < 0) {
|
if (Offset < 0) {
|
||||||
BaseOpc = ARM::SUBri;
|
BaseOpc = isThumb2 ? ARM::t2SUBri : ARM::SUBri;
|
||||||
Offset = - Offset;
|
Offset = - Offset;
|
||||||
}
|
}
|
||||||
if (ARM_AM::getSOImmVal(Offset) == -1)
|
int ImmedOffset = isThumb2
|
||||||
|
? ARM_AM::getT2SOImmVal(Offset) : ARM_AM::getSOImmVal(Offset);
|
||||||
|
if (ImmedOffset == -1)
|
||||||
|
// FIXME: Try t2ADDri12 or t2SUBri12?
|
||||||
return false; // Probably not worth it then.
|
return false; // Probably not worth it then.
|
||||||
|
|
||||||
BuildMI(MBB, MBBI, dl, TII->get(BaseOpc), NewBase)
|
BuildMI(MBB, MBBI, dl, TII->get(BaseOpc), NewBase)
|
||||||
@ -207,7 +236,7 @@ ARMLoadStoreOpt::MergeLDR_STR(MachineBasicBlock &MBB, unsigned SIndex,
|
|||||||
ARMCC::CondCodes Pred, unsigned PredReg,
|
ARMCC::CondCodes Pred, unsigned PredReg,
|
||||||
unsigned Scratch, MemOpQueue &MemOps,
|
unsigned Scratch, MemOpQueue &MemOps,
|
||||||
SmallVector<MachineBasicBlock::iterator, 4> &Merges) {
|
SmallVector<MachineBasicBlock::iterator, 4> &Merges) {
|
||||||
bool isAM4 = Opcode == ARM::LDR || Opcode == ARM::STR;
|
bool isAM4 = isi32Load(Opcode) || isi32Store(Opcode);
|
||||||
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;
|
||||||
@ -281,24 +310,54 @@ static ARMCC::CondCodes getInstrPredicate(MachineInstr *MI, unsigned &PredReg) {
|
|||||||
|
|
||||||
static inline bool isMatchingDecrement(MachineInstr *MI, unsigned Base,
|
static inline bool isMatchingDecrement(MachineInstr *MI, unsigned Base,
|
||||||
unsigned Bytes, ARMCC::CondCodes Pred,
|
unsigned Bytes, ARMCC::CondCodes Pred,
|
||||||
unsigned PredReg) {
|
unsigned PredReg, bool isThumb2) {
|
||||||
unsigned MyPredReg = 0;
|
unsigned MyPredReg = 0;
|
||||||
return (MI && MI->getOpcode() == ARM::SUBri &&
|
if (!MI)
|
||||||
MI->getOperand(0).getReg() == Base &&
|
return false;
|
||||||
|
if (isThumb2) {
|
||||||
|
if (MI->getOpcode() != ARM::t2SUBri)
|
||||||
|
return false;
|
||||||
|
// Make sure the offset fits in 8 bits.
|
||||||
|
if (Bytes <= 0 || Bytes >= 0x100)
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
if (MI->getOpcode() != ARM::SUBri)
|
||||||
|
return false;
|
||||||
|
// Make sure the offset fits in 12 bits.
|
||||||
|
if (Bytes <= 0 || Bytes >= 0x1000)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (MI->getOperand(0).getReg() == Base &&
|
||||||
MI->getOperand(1).getReg() == Base &&
|
MI->getOperand(1).getReg() == Base &&
|
||||||
ARM_AM::getAM2Offset(MI->getOperand(2).getImm()) == Bytes &&
|
MI->getOperand(2).getImm() == Bytes &&
|
||||||
getInstrPredicate(MI, MyPredReg) == Pred &&
|
getInstrPredicate(MI, MyPredReg) == Pred &&
|
||||||
MyPredReg == PredReg);
|
MyPredReg == PredReg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool isMatchingIncrement(MachineInstr *MI, unsigned Base,
|
static inline bool isMatchingIncrement(MachineInstr *MI, unsigned Base,
|
||||||
unsigned Bytes, ARMCC::CondCodes Pred,
|
unsigned Bytes, ARMCC::CondCodes Pred,
|
||||||
unsigned PredReg) {
|
unsigned PredReg, bool isThumb2) {
|
||||||
unsigned MyPredReg = 0;
|
unsigned MyPredReg = 0;
|
||||||
return (MI && MI->getOpcode() == ARM::ADDri &&
|
if (!MI)
|
||||||
MI->getOperand(0).getReg() == Base &&
|
return false;
|
||||||
|
if (isThumb2) {
|
||||||
|
if (MI->getOpcode() != ARM::t2ADDri)
|
||||||
|
return false;
|
||||||
|
// Make sure the offset fits in 8 bits.
|
||||||
|
if (Bytes <= 0 || Bytes >= 0x100)
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
if (MI->getOpcode() != ARM::ADDri)
|
||||||
|
return false;
|
||||||
|
// Make sure the offset fits in 12 bits.
|
||||||
|
if (Bytes <= 0 || Bytes >= 0x1000)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (MI->getOperand(0).getReg() == Base &&
|
||||||
MI->getOperand(1).getReg() == Base &&
|
MI->getOperand(1).getReg() == Base &&
|
||||||
ARM_AM::getAM2Offset(MI->getOperand(2).getImm()) == Bytes &&
|
MI->getOperand(2).getImm() == Bytes &&
|
||||||
getInstrPredicate(MI, MyPredReg) == Pred &&
|
getInstrPredicate(MI, MyPredReg) == Pred &&
|
||||||
MyPredReg == PredReg);
|
MyPredReg == PredReg);
|
||||||
}
|
}
|
||||||
@ -308,6 +367,10 @@ static inline unsigned getLSMultipleTransferSize(MachineInstr *MI) {
|
|||||||
default: return 0;
|
default: return 0;
|
||||||
case ARM::LDR:
|
case ARM::LDR:
|
||||||
case ARM::STR:
|
case ARM::STR:
|
||||||
|
case ARM::t2LDRi8:
|
||||||
|
case ARM::t2LDRi12:
|
||||||
|
case ARM::t2STRi8:
|
||||||
|
case ARM::t2STRi12:
|
||||||
case ARM::FLDS:
|
case ARM::FLDS:
|
||||||
case ARM::FSTS:
|
case ARM::FSTS:
|
||||||
return 4;
|
return 4;
|
||||||
@ -325,7 +388,7 @@ static inline unsigned getLSMultipleTransferSize(MachineInstr *MI) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// mergeBaseUpdateLSMultiple - Fold proceeding/trailing inc/dec of base
|
/// MergeBaseUpdateLSMultiple - Fold proceeding/trailing inc/dec of base
|
||||||
/// register into the LDM/STM/FLDM{D|S}/FSTM{D|S} op when possible:
|
/// register into the LDM/STM/FLDM{D|S}/FSTM{D|S} op when possible:
|
||||||
///
|
///
|
||||||
/// stmia rn, <ra, rb, rc>
|
/// stmia rn, <ra, rb, rc>
|
||||||
@ -337,17 +400,18 @@ static inline unsigned getLSMultipleTransferSize(MachineInstr *MI) {
|
|||||||
/// ldmia rn, <ra, rb, rc>
|
/// ldmia rn, <ra, rb, rc>
|
||||||
/// =>
|
/// =>
|
||||||
/// ldmdb rn!, <ra, rb, rc>
|
/// ldmdb rn!, <ra, rb, rc>
|
||||||
static bool mergeBaseUpdateLSMultiple(MachineBasicBlock &MBB,
|
bool ARMLoadStoreOpt::MergeBaseUpdateLSMultiple(MachineBasicBlock &MBB,
|
||||||
MachineBasicBlock::iterator MBBI,
|
MachineBasicBlock::iterator MBBI,
|
||||||
bool &Advance,
|
bool &Advance,
|
||||||
MachineBasicBlock::iterator &I) {
|
MachineBasicBlock::iterator &I) {
|
||||||
MachineInstr *MI = MBBI;
|
MachineInstr *MI = MBBI;
|
||||||
unsigned Base = MI->getOperand(0).getReg();
|
unsigned Base = MI->getOperand(0).getReg();
|
||||||
unsigned Bytes = getLSMultipleTransferSize(MI);
|
unsigned Bytes = getLSMultipleTransferSize(MI);
|
||||||
unsigned PredReg = 0;
|
unsigned PredReg = 0;
|
||||||
ARMCC::CondCodes Pred = getInstrPredicate(MI, PredReg);
|
ARMCC::CondCodes Pred = getInstrPredicate(MI, PredReg);
|
||||||
int Opcode = MI->getOpcode();
|
int Opcode = MI->getOpcode();
|
||||||
bool isAM4 = Opcode == ARM::LDM || Opcode == ARM::STM;
|
bool isAM4 = Opcode == ARM::LDM || Opcode == ARM::t2LDM ||
|
||||||
|
Opcode == ARM::STM || Opcode == ARM::t2STM;
|
||||||
|
|
||||||
if (isAM4) {
|
if (isAM4) {
|
||||||
if (ARM_AM::getAM4WBFlag(MI->getOperand(1).getImm()))
|
if (ARM_AM::getAM4WBFlag(MI->getOperand(1).getImm()))
|
||||||
@ -364,12 +428,13 @@ static bool mergeBaseUpdateLSMultiple(MachineBasicBlock &MBB,
|
|||||||
if (MBBI != MBB.begin()) {
|
if (MBBI != MBB.begin()) {
|
||||||
MachineBasicBlock::iterator PrevMBBI = prior(MBBI);
|
MachineBasicBlock::iterator PrevMBBI = prior(MBBI);
|
||||||
if (Mode == ARM_AM::ia &&
|
if (Mode == ARM_AM::ia &&
|
||||||
isMatchingDecrement(PrevMBBI, Base, Bytes, Pred, PredReg)) {
|
isMatchingDecrement(PrevMBBI, Base, Bytes, Pred, PredReg, isThumb2)) {
|
||||||
MI->getOperand(1).setImm(ARM_AM::getAM4ModeImm(ARM_AM::db, true));
|
MI->getOperand(1).setImm(ARM_AM::getAM4ModeImm(ARM_AM::db, true));
|
||||||
MBB.erase(PrevMBBI);
|
MBB.erase(PrevMBBI);
|
||||||
return true;
|
return true;
|
||||||
} else if (Mode == ARM_AM::ib &&
|
} else if (Mode == ARM_AM::ib &&
|
||||||
isMatchingDecrement(PrevMBBI, Base, Bytes, Pred, PredReg)) {
|
isMatchingDecrement(PrevMBBI, Base, Bytes, Pred, PredReg,
|
||||||
|
isThumb2)) {
|
||||||
MI->getOperand(1).setImm(ARM_AM::getAM4ModeImm(ARM_AM::da, true));
|
MI->getOperand(1).setImm(ARM_AM::getAM4ModeImm(ARM_AM::da, true));
|
||||||
MBB.erase(PrevMBBI);
|
MBB.erase(PrevMBBI);
|
||||||
return true;
|
return true;
|
||||||
@ -379,7 +444,7 @@ static bool mergeBaseUpdateLSMultiple(MachineBasicBlock &MBB,
|
|||||||
if (MBBI != MBB.end()) {
|
if (MBBI != MBB.end()) {
|
||||||
MachineBasicBlock::iterator NextMBBI = next(MBBI);
|
MachineBasicBlock::iterator NextMBBI = next(MBBI);
|
||||||
if ((Mode == ARM_AM::ia || Mode == ARM_AM::ib) &&
|
if ((Mode == ARM_AM::ia || Mode == ARM_AM::ib) &&
|
||||||
isMatchingIncrement(NextMBBI, Base, Bytes, Pred, PredReg)) {
|
isMatchingIncrement(NextMBBI, Base, Bytes, Pred, PredReg, isThumb2)) {
|
||||||
MI->getOperand(1).setImm(ARM_AM::getAM4ModeImm(Mode, true));
|
MI->getOperand(1).setImm(ARM_AM::getAM4ModeImm(Mode, true));
|
||||||
if (NextMBBI == I) {
|
if (NextMBBI == I) {
|
||||||
Advance = true;
|
Advance = true;
|
||||||
@ -388,7 +453,8 @@ static bool mergeBaseUpdateLSMultiple(MachineBasicBlock &MBB,
|
|||||||
MBB.erase(NextMBBI);
|
MBB.erase(NextMBBI);
|
||||||
return true;
|
return true;
|
||||||
} else if ((Mode == ARM_AM::da || Mode == ARM_AM::db) &&
|
} else if ((Mode == ARM_AM::da || Mode == ARM_AM::db) &&
|
||||||
isMatchingDecrement(NextMBBI, Base, Bytes, Pred, PredReg)) {
|
isMatchingDecrement(NextMBBI, Base, Bytes, Pred, PredReg,
|
||||||
|
isThumb2)) {
|
||||||
MI->getOperand(1).setImm(ARM_AM::getAM4ModeImm(Mode, true));
|
MI->getOperand(1).setImm(ARM_AM::getAM4ModeImm(Mode, true));
|
||||||
if (NextMBBI == I) {
|
if (NextMBBI == I) {
|
||||||
Advance = true;
|
Advance = true;
|
||||||
@ -408,7 +474,7 @@ static bool mergeBaseUpdateLSMultiple(MachineBasicBlock &MBB,
|
|||||||
if (MBBI != MBB.begin()) {
|
if (MBBI != MBB.begin()) {
|
||||||
MachineBasicBlock::iterator PrevMBBI = prior(MBBI);
|
MachineBasicBlock::iterator PrevMBBI = prior(MBBI);
|
||||||
if (Mode == ARM_AM::ia &&
|
if (Mode == ARM_AM::ia &&
|
||||||
isMatchingDecrement(PrevMBBI, Base, Bytes, Pred, PredReg)) {
|
isMatchingDecrement(PrevMBBI, Base, Bytes, Pred, PredReg, isThumb2)) {
|
||||||
MI->getOperand(1).setImm(ARM_AM::getAM5Opc(ARM_AM::db, true, Offset));
|
MI->getOperand(1).setImm(ARM_AM::getAM5Opc(ARM_AM::db, true, Offset));
|
||||||
MBB.erase(PrevMBBI);
|
MBB.erase(PrevMBBI);
|
||||||
return true;
|
return true;
|
||||||
@ -418,7 +484,7 @@ static bool mergeBaseUpdateLSMultiple(MachineBasicBlock &MBB,
|
|||||||
if (MBBI != MBB.end()) {
|
if (MBBI != MBB.end()) {
|
||||||
MachineBasicBlock::iterator NextMBBI = next(MBBI);
|
MachineBasicBlock::iterator NextMBBI = next(MBBI);
|
||||||
if (Mode == ARM_AM::ia &&
|
if (Mode == ARM_AM::ia &&
|
||||||
isMatchingIncrement(NextMBBI, Base, Bytes, Pred, PredReg)) {
|
isMatchingIncrement(NextMBBI, Base, Bytes, Pred, PredReg, isThumb2)) {
|
||||||
MI->getOperand(1).setImm(ARM_AM::getAM5Opc(ARM_AM::ia, true, Offset));
|
MI->getOperand(1).setImm(ARM_AM::getAM5Opc(ARM_AM::ia, true, Offset));
|
||||||
if (NextMBBI == I) {
|
if (NextMBBI == I) {
|
||||||
Advance = true;
|
Advance = true;
|
||||||
@ -441,6 +507,12 @@ static unsigned getPreIndexedLoadStoreOpcode(unsigned Opc) {
|
|||||||
case ARM::FLDD: return ARM::FLDMD;
|
case ARM::FLDD: return ARM::FLDMD;
|
||||||
case ARM::FSTS: return ARM::FSTMS;
|
case ARM::FSTS: return ARM::FSTMS;
|
||||||
case ARM::FSTD: return ARM::FSTMD;
|
case ARM::FSTD: return ARM::FSTMD;
|
||||||
|
case ARM::t2LDRi8:
|
||||||
|
case ARM::t2LDRi12:
|
||||||
|
return ARM::t2LDR_PRE;
|
||||||
|
case ARM::t2STRi8:
|
||||||
|
case ARM::t2STRi12:
|
||||||
|
return ARM::t2STR_PRE;
|
||||||
default: LLVM_UNREACHABLE("Unhandled opcode!");
|
default: LLVM_UNREACHABLE("Unhandled opcode!");
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -454,18 +526,24 @@ static unsigned getPostIndexedLoadStoreOpcode(unsigned Opc) {
|
|||||||
case ARM::FLDD: return ARM::FLDMD;
|
case ARM::FLDD: return ARM::FLDMD;
|
||||||
case ARM::FSTS: return ARM::FSTMS;
|
case ARM::FSTS: return ARM::FSTMS;
|
||||||
case ARM::FSTD: return ARM::FSTMD;
|
case ARM::FSTD: return ARM::FSTMD;
|
||||||
|
case ARM::t2LDRi8:
|
||||||
|
case ARM::t2LDRi12:
|
||||||
|
return ARM::t2LDR_POST;
|
||||||
|
case ARM::t2STRi8:
|
||||||
|
case ARM::t2STRi12:
|
||||||
|
return ARM::t2STR_POST;
|
||||||
default: LLVM_UNREACHABLE("Unhandled opcode!");
|
default: LLVM_UNREACHABLE("Unhandled opcode!");
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// mergeBaseUpdateLoadStore - Fold proceeding/trailing inc/dec of base
|
/// MergeBaseUpdateLoadStore - Fold proceeding/trailing inc/dec of base
|
||||||
/// register into the LDR/STR/FLD{D|S}/FST{D|S} op when possible:
|
/// register into the LDR/STR/FLD{D|S}/FST{D|S} op when possible:
|
||||||
static bool mergeBaseUpdateLoadStore(MachineBasicBlock &MBB,
|
bool ARMLoadStoreOpt::MergeBaseUpdateLoadStore(MachineBasicBlock &MBB,
|
||||||
MachineBasicBlock::iterator MBBI,
|
MachineBasicBlock::iterator MBBI,
|
||||||
const TargetInstrInfo *TII,
|
const TargetInstrInfo *TII,
|
||||||
bool &Advance,
|
bool &Advance,
|
||||||
MachineBasicBlock::iterator &I) {
|
MachineBasicBlock::iterator &I) {
|
||||||
MachineInstr *MI = MBBI;
|
MachineInstr *MI = MBBI;
|
||||||
unsigned Base = MI->getOperand(1).getReg();
|
unsigned Base = MI->getOperand(1).getReg();
|
||||||
bool BaseKill = MI->getOperand(1).isKill();
|
bool BaseKill = MI->getOperand(1).isKill();
|
||||||
@ -473,11 +551,15 @@ static bool mergeBaseUpdateLoadStore(MachineBasicBlock &MBB,
|
|||||||
int Opcode = MI->getOpcode();
|
int Opcode = MI->getOpcode();
|
||||||
DebugLoc dl = MI->getDebugLoc();
|
DebugLoc dl = MI->getDebugLoc();
|
||||||
bool isAM2 = Opcode == ARM::LDR || Opcode == ARM::STR;
|
bool isAM2 = Opcode == ARM::LDR || Opcode == ARM::STR;
|
||||||
if ((isAM2 && ARM_AM::getAM2Offset(MI->getOperand(3).getImm()) != 0) ||
|
if (isAM2 && ARM_AM::getAM2Offset(MI->getOperand(3).getImm()) != 0)
|
||||||
(!isAM2 && ARM_AM::getAM5Offset(MI->getOperand(2).getImm()) != 0))
|
return false;
|
||||||
|
else if (!isAM2 && !isThumb2 &&
|
||||||
|
ARM_AM::getAM5Offset(MI->getOperand(2).getImm()) != 0)
|
||||||
|
return false;
|
||||||
|
else if (isThumb2 && MI->getOperand(2).getImm() != 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
bool isLd = Opcode == ARM::LDR || Opcode == ARM::FLDS || Opcode == ARM::FLDD;
|
bool isLd = isi32Load(Opcode) || Opcode == ARM::FLDS || Opcode == ARM::FLDD;
|
||||||
// Can't do the merge if the destination register is the same as the would-be
|
// Can't do the merge if the destination register is the same as the would-be
|
||||||
// writeback register.
|
// writeback register.
|
||||||
if (isLd && MI->getOperand(0).getReg() == Base)
|
if (isLd && MI->getOperand(0).getReg() == Base)
|
||||||
@ -490,12 +572,12 @@ static bool mergeBaseUpdateLoadStore(MachineBasicBlock &MBB,
|
|||||||
unsigned NewOpc = 0;
|
unsigned NewOpc = 0;
|
||||||
if (MBBI != MBB.begin()) {
|
if (MBBI != MBB.begin()) {
|
||||||
MachineBasicBlock::iterator PrevMBBI = prior(MBBI);
|
MachineBasicBlock::iterator PrevMBBI = prior(MBBI);
|
||||||
if (isMatchingDecrement(PrevMBBI, Base, Bytes, Pred, PredReg)) {
|
if (isMatchingDecrement(PrevMBBI, Base, Bytes, Pred, PredReg, isThumb2)) {
|
||||||
DoMerge = true;
|
DoMerge = true;
|
||||||
AddSub = ARM_AM::sub;
|
AddSub = ARM_AM::sub;
|
||||||
NewOpc = getPreIndexedLoadStoreOpcode(Opcode);
|
NewOpc = getPreIndexedLoadStoreOpcode(Opcode);
|
||||||
} else if (isAM2 && isMatchingIncrement(PrevMBBI, Base, Bytes,
|
} else if (isAM2 && isMatchingIncrement(PrevMBBI, Base, Bytes,
|
||||||
Pred, PredReg)) {
|
Pred, PredReg, isThumb2)) {
|
||||||
DoMerge = true;
|
DoMerge = true;
|
||||||
NewOpc = getPreIndexedLoadStoreOpcode(Opcode);
|
NewOpc = getPreIndexedLoadStoreOpcode(Opcode);
|
||||||
}
|
}
|
||||||
@ -505,11 +587,13 @@ static bool mergeBaseUpdateLoadStore(MachineBasicBlock &MBB,
|
|||||||
|
|
||||||
if (!DoMerge && MBBI != MBB.end()) {
|
if (!DoMerge && MBBI != MBB.end()) {
|
||||||
MachineBasicBlock::iterator NextMBBI = next(MBBI);
|
MachineBasicBlock::iterator NextMBBI = next(MBBI);
|
||||||
if (isAM2 && isMatchingDecrement(NextMBBI, Base, Bytes, Pred, PredReg)) {
|
if (isAM2 && isMatchingDecrement(NextMBBI, Base, Bytes, Pred, PredReg,
|
||||||
|
isThumb2)) {
|
||||||
DoMerge = true;
|
DoMerge = true;
|
||||||
AddSub = ARM_AM::sub;
|
AddSub = ARM_AM::sub;
|
||||||
NewOpc = getPostIndexedLoadStoreOpcode(Opcode);
|
NewOpc = getPostIndexedLoadStoreOpcode(Opcode);
|
||||||
} else if (isMatchingIncrement(NextMBBI, Base, Bytes, Pred, PredReg)) {
|
} else if (isMatchingIncrement(NextMBBI, Base, Bytes, Pred, PredReg,
|
||||||
|
isThumb2)) {
|
||||||
DoMerge = true;
|
DoMerge = true;
|
||||||
NewOpc = getPostIndexedLoadStoreOpcode(Opcode);
|
NewOpc = getPostIndexedLoadStoreOpcode(Opcode);
|
||||||
}
|
}
|
||||||
@ -526,16 +610,19 @@ static bool mergeBaseUpdateLoadStore(MachineBasicBlock &MBB,
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
bool isDPR = NewOpc == ARM::FLDMD || NewOpc == ARM::FSTMD;
|
bool isDPR = NewOpc == ARM::FLDMD || NewOpc == ARM::FSTMD;
|
||||||
unsigned Offset = isAM2 ? ARM_AM::getAM2Opc(AddSub, Bytes, ARM_AM::no_shift)
|
unsigned Offset = isAM2
|
||||||
: ARM_AM::getAM5Opc((AddSub == ARM_AM::sub) ? ARM_AM::db : ARM_AM::ia,
|
? ARM_AM::getAM2Opc(AddSub, Bytes, ARM_AM::no_shift)
|
||||||
true, isDPR ? 2 : 1);
|
: (isThumb2
|
||||||
|
? Bytes
|
||||||
|
: ARM_AM::getAM5Opc((AddSub == ARM_AM::sub) ? ARM_AM::db : ARM_AM::ia,
|
||||||
|
true, isDPR ? 2 : 1));
|
||||||
if (isLd) {
|
if (isLd) {
|
||||||
if (isAM2)
|
if (isAM2 || isThumb2)
|
||||||
// LDR_PRE, LDR_POST;
|
// LDR_PRE, LDR_POST, t2LDR_PRE, t2LDR_POST
|
||||||
BuildMI(MBB, MBBI, dl, TII->get(NewOpc), MI->getOperand(0).getReg())
|
BuildMI(MBB, MBBI, dl, TII->get(NewOpc), MI->getOperand(0).getReg())
|
||||||
.addReg(Base, RegState::Define)
|
.addReg(Base, RegState::Define)
|
||||||
.addReg(Base).addReg(0).addImm(Offset).addImm(Pred).addReg(PredReg);
|
.addReg(Base).addReg(0).addImm(Offset).addImm(Pred).addReg(PredReg);
|
||||||
else
|
else if (!isThumb2)
|
||||||
// FLDMS, FLDMD
|
// FLDMS, FLDMD
|
||||||
BuildMI(MBB, MBBI, dl, TII->get(NewOpc))
|
BuildMI(MBB, MBBI, dl, TII->get(NewOpc))
|
||||||
.addReg(Base, getKillRegState(BaseKill))
|
.addReg(Base, getKillRegState(BaseKill))
|
||||||
@ -543,8 +630,8 @@ static bool mergeBaseUpdateLoadStore(MachineBasicBlock &MBB,
|
|||||||
.addReg(MI->getOperand(0).getReg(), RegState::Define);
|
.addReg(MI->getOperand(0).getReg(), RegState::Define);
|
||||||
} else {
|
} else {
|
||||||
MachineOperand &MO = MI->getOperand(0);
|
MachineOperand &MO = MI->getOperand(0);
|
||||||
if (isAM2)
|
if (isAM2 || isThumb2)
|
||||||
// STR_PRE, STR_POST;
|
// STR_PRE, STR_POST, t2STR_PRE, t2STR_POST
|
||||||
BuildMI(MBB, MBBI, dl, TII->get(NewOpc), Base)
|
BuildMI(MBB, MBBI, dl, TII->get(NewOpc), Base)
|
||||||
.addReg(MO.getReg(), getKillRegState(MO.isKill()))
|
.addReg(MO.getReg(), getKillRegState(MO.isKill()))
|
||||||
.addReg(Base).addReg(0).addImm(Offset).addImm(Pred).addReg(PredReg);
|
.addReg(Base).addReg(0).addImm(Offset).addImm(Pred).addReg(PredReg);
|
||||||
@ -561,7 +648,7 @@ static bool mergeBaseUpdateLoadStore(MachineBasicBlock &MBB,
|
|||||||
|
|
||||||
/// isMemoryOp - Returns true if instruction is a memory operations (that this
|
/// isMemoryOp - Returns true if instruction is a memory operations (that this
|
||||||
/// pass is capable of operating on).
|
/// pass is capable of operating on).
|
||||||
static bool isMemoryOp(MachineInstr *MI) {
|
static bool isMemoryOp(const MachineInstr *MI) {
|
||||||
int Opcode = MI->getOpcode();
|
int Opcode = MI->getOpcode();
|
||||||
switch (Opcode) {
|
switch (Opcode) {
|
||||||
default: break;
|
default: break;
|
||||||
@ -574,6 +661,11 @@ static bool isMemoryOp(MachineInstr *MI) {
|
|||||||
case ARM::FLDD:
|
case ARM::FLDD:
|
||||||
case ARM::FSTD:
|
case ARM::FSTD:
|
||||||
return MI->getOperand(1).isReg();
|
return MI->getOperand(1).isReg();
|
||||||
|
case ARM::t2LDRi8:
|
||||||
|
case ARM::t2LDRi12:
|
||||||
|
case ARM::t2STRi8:
|
||||||
|
case ARM::t2STRi12:
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -595,11 +687,19 @@ void ARMLoadStoreOpt::AdvanceRS(MachineBasicBlock &MBB, MemOpQueue &MemOps) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int getMemoryOpOffset(const MachineInstr *MI) {
|
static int getMemoryOpOffset(const MachineInstr *MI) {
|
||||||
|
assert(isMemoryOp(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;
|
||||||
bool isAM3 = Opcode == ARM::LDRD || Opcode == ARM::STRD;
|
bool isAM3 = Opcode == ARM::LDRD || Opcode == ARM::STRD;
|
||||||
unsigned NumOperands = MI->getDesc().getNumOperands();
|
unsigned NumOperands = MI->getDesc().getNumOperands();
|
||||||
unsigned OffField = MI->getOperand(NumOperands-3).getImm();
|
unsigned OffField = MI->getOperand(NumOperands-3).getImm();
|
||||||
|
|
||||||
|
if (Opcode == ARM::t2LDRi12 || Opcode == ARM::t2LDRi8 ||
|
||||||
|
Opcode == ARM::t2STRi12 || Opcode == ARM::t2STRi8 ||
|
||||||
|
Opcode == ARM::t2LDRDi8 || Opcode == ARM::t2STRDi8)
|
||||||
|
return OffField;
|
||||||
|
|
||||||
int Offset = isAM2
|
int Offset = isAM2
|
||||||
? ARM_AM::getAM2Offset(OffField)
|
? ARM_AM::getAM2Offset(OffField)
|
||||||
: (isAM3 ? ARM_AM::getAM3Offset(OffField)
|
: (isAM3 ? ARM_AM::getAM3Offset(OffField)
|
||||||
@ -772,7 +872,7 @@ bool ARMLoadStoreOpt::LoadStoreMultipleOpti(MachineBasicBlock &MBB) {
|
|||||||
// looks like the later ldr(s) use the same base register. Try to
|
// looks like the later ldr(s) use the same base register. Try to
|
||||||
// merge the ldr's so far, including this one. But don't try to
|
// merge the ldr's so far, including this one. But don't try to
|
||||||
// combine the following ldr(s).
|
// combine the following ldr(s).
|
||||||
Clobber = (Opcode == ARM::LDR && Base == MBBI->getOperand(0).getReg());
|
Clobber = (isi32Load(Opcode) && Base == MBBI->getOperand(0).getReg());
|
||||||
if (CurrBase == 0 && !Clobber) {
|
if (CurrBase == 0 && !Clobber) {
|
||||||
// Start of a new chain.
|
// Start of a new chain.
|
||||||
CurrBase = Base;
|
CurrBase = Base;
|
||||||
@ -842,7 +942,7 @@ bool ARMLoadStoreOpt::LoadStoreMultipleOpti(MachineBasicBlock &MBB) {
|
|||||||
// 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 = Merges.size(); i < e; ++i)
|
for (unsigned i = 0, e = Merges.size(); i < e; ++i)
|
||||||
if (mergeBaseUpdateLSMultiple(MBB, Merges[i], Advance, MBBI))
|
if (MergeBaseUpdateLSMultiple(MBB, Merges[i], Advance, MBBI))
|
||||||
++NumMerges;
|
++NumMerges;
|
||||||
NumMerges += Merges.size();
|
NumMerges += Merges.size();
|
||||||
|
|
||||||
@ -850,7 +950,7 @@ bool ARMLoadStoreOpt::LoadStoreMultipleOpti(MachineBasicBlock &MBB) {
|
|||||||
// that were not merged to form LDM/STM ops.
|
// that were not merged to form LDM/STM ops.
|
||||||
for (unsigned i = 0; i != NumMemOps; ++i)
|
for (unsigned i = 0; i != NumMemOps; ++i)
|
||||||
if (!MemOps[i].Merged)
|
if (!MemOps[i].Merged)
|
||||||
if (mergeBaseUpdateLoadStore(MBB, MemOps[i].MBBI, TII,Advance,MBBI))
|
if (MergeBaseUpdateLoadStore(MBB, MemOps[i].MBBI, TII,Advance,MBBI))
|
||||||
++NumMerges;
|
++NumMerges;
|
||||||
|
|
||||||
// RS may be pointing to an instruction that's deleted.
|
// RS may be pointing to an instruction that's deleted.
|
||||||
@ -858,7 +958,7 @@ bool ARMLoadStoreOpt::LoadStoreMultipleOpti(MachineBasicBlock &MBB) {
|
|||||||
} else if (NumMemOps == 1) {
|
} else if (NumMemOps == 1) {
|
||||||
// Try folding preceeding/trailing base inc/dec into the single
|
// Try folding preceeding/trailing base inc/dec into the single
|
||||||
// load/store.
|
// load/store.
|
||||||
if (mergeBaseUpdateLoadStore(MBB, MemOps[0].MBBI, TII, Advance, MBBI)) {
|
if (MergeBaseUpdateLoadStore(MBB, MemOps[0].MBBI, TII, Advance, MBBI)) {
|
||||||
++NumMerges;
|
++NumMerges;
|
||||||
RS->forward(prior(MBBI));
|
RS->forward(prior(MBBI));
|
||||||
}
|
}
|
||||||
@ -907,12 +1007,14 @@ bool ARMLoadStoreOpt::MergeReturnIntoLDM(MachineBasicBlock &MBB) {
|
|||||||
if (MBB.empty()) return false;
|
if (MBB.empty()) return false;
|
||||||
|
|
||||||
MachineBasicBlock::iterator MBBI = prior(MBB.end());
|
MachineBasicBlock::iterator MBBI = prior(MBB.end());
|
||||||
if (MBBI->getOpcode() == ARM::BX_RET && MBBI != MBB.begin()) {
|
if (MBBI != MBB.begin() &&
|
||||||
|
(MBBI->getOpcode() == ARM::BX_RET || MBBI->getOpcode() == ARM::t2BX_RET)){
|
||||||
MachineInstr *PrevMI = prior(MBBI);
|
MachineInstr *PrevMI = prior(MBBI);
|
||||||
if (PrevMI->getOpcode() == ARM::LDM) {
|
if (PrevMI->getOpcode() == ARM::LDM || PrevMI->getOpcode() == ARM::t2LDM) {
|
||||||
MachineOperand &MO = PrevMI->getOperand(PrevMI->getNumOperands()-1);
|
MachineOperand &MO = PrevMI->getOperand(PrevMI->getNumOperands()-1);
|
||||||
if (MO.getReg() == ARM::LR) {
|
if (MO.getReg() == ARM::LR) {
|
||||||
PrevMI->setDesc(TII->get(ARM::LDM_RET));
|
unsigned NewOpc = isThumb2 ? ARM::t2LDM_RET : ARM::LDM_RET;
|
||||||
|
PrevMI->setDesc(TII->get(NewOpc));
|
||||||
MO.setReg(ARM::PC);
|
MO.setReg(ARM::PC);
|
||||||
MBB.erase(MBBI);
|
MBB.erase(MBBI);
|
||||||
return true;
|
return true;
|
||||||
@ -928,6 +1030,7 @@ bool ARMLoadStoreOpt::runOnMachineFunction(MachineFunction &Fn) {
|
|||||||
TII = TM.getInstrInfo();
|
TII = TM.getInstrInfo();
|
||||||
TRI = TM.getRegisterInfo();
|
TRI = TM.getRegisterInfo();
|
||||||
RS = new RegScavenger();
|
RS = new RegScavenger();
|
||||||
|
isThumb2 = AFI->isThumb2Function();
|
||||||
|
|
||||||
bool Modified = false;
|
bool Modified = false;
|
||||||
for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E;
|
for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E;
|
||||||
|
Loading…
Reference in New Issue
Block a user