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:
Evan Cheng 2009-07-09 23:11:34 +00:00
parent c50a1cbf5f
commit 45032f2801

View File

@ -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;