1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-19 19:12:56 +02:00

Refactor ARM STR/STRB instruction patterns into STR{B}i12 and STR{B}rs, like

the LDR instructions have. This makes the literal/register forms of the
instructions explicit and allows us to assign scheduling itineraries
appropriately. rdar://8477752

llvm-svn: 117505
This commit is contained in:
Jim Grosbach 2010-10-27 23:12:14 +00:00
parent 27049dbce3
commit 86ecfda983
9 changed files with 94 additions and 101 deletions

View File

@ -870,8 +870,8 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) {
switch (MI->getOpcode()) {
default:
llvm_unreachable("Unexpected opcode!");
case ARM::PICSTR: Opcode = ARM::STR; break;
case ARM::PICSTRB: Opcode = ARM::STRB; break;
case ARM::PICSTR: Opcode = ARM::STRrs; break;
case ARM::PICSTRB: Opcode = ARM::STRBrs; break;
case ARM::PICSTRH: Opcode = ARM::STRH; break;
case ARM::PICLDR: Opcode = ARM::LDRrs; break;
case ARM::PICLDRB: Opcode = ARM::LDRBrs; break;
@ -1161,10 +1161,9 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) {
}
{
MCInst TmpInst;
TmpInst.setOpcode(ARM::STR);
TmpInst.setOpcode(ARM::STRi12);
TmpInst.addOperand(MCOperand::CreateReg(ValReg));
TmpInst.addOperand(MCOperand::CreateReg(SrcReg));
TmpInst.addOperand(MCOperand::CreateReg(0));
TmpInst.addOperand(MCOperand::CreateImm(4));
// Predicate.
TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));

View File

@ -676,9 +676,9 @@ storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
switch (RC->getID()) {
case ARM::GPRRegClassID:
AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::STR))
AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::STRi12))
.addReg(SrcReg, getKillRegState(isKill))
.addFrameIndex(FI).addReg(0).addImm(0).addMemOperand(MMO));
.addFrameIndex(FI).addImm(0).addMemOperand(MMO));
break;
case ARM::SPRRegClassID:
AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VSTRS))
@ -755,7 +755,7 @@ ARMBaseInstrInfo::isStoreToStackSlot(const MachineInstr *MI,
int &FrameIndex) const {
switch (MI->getOpcode()) {
default: break;
case ARM::STR:
case ARM::STRrs:
case ARM::t2STRs: // FIXME: don't use t2STRs to access frame.
if (MI->getOperand(1).isFI() &&
MI->getOperand(2).isReg() &&
@ -766,6 +766,7 @@ ARMBaseInstrInfo::isStoreToStackSlot(const MachineInstr *MI,
return MI->getOperand(0).getReg();
}
break;
case ARM::STRi12:
case ARM::t2STRi12:
case ARM::tSpill:
case ARM::VSTRD:

View File

@ -1377,7 +1377,7 @@ needsFrameBaseReg(MachineInstr *MI, int64_t Offset) const {
unsigned Opc = MI->getOpcode();
switch (Opc) {
case ARM::LDRi12: case ARM::LDRH: case ARM::LDRBi12:
case ARM::STR: case ARM::STRH: case ARM::STRB:
case ARM::STRi12: case ARM::STRH: case ARM::STRBi12:
case ARM::t2LDRi12: case ARM::t2LDRi8:
case ARM::t2STRi12: case ARM::t2STRi8:
case ARM::VLDRS: case ARM::VLDRD:
@ -1711,7 +1711,7 @@ emitPrologue(MachineFunction &MF) const {
// Build the new SUBri to adjust SP for integer callee-save spill area.
emitSPUpdate(isARM, MBB, MBBI, dl, TII, -GPRCSSize);
movePastCSLoadStoreOps(MBB, MBBI, ARM::STR, ARM::t2STRi12, 1, STI);
movePastCSLoadStoreOps(MBB, MBBI, ARM::STRi12, ARM::t2STRi12, 1, STI);
// Set FP to point to the stack slot that contains the previous FP.
bool HasFP = hasFP(MF);

View File

@ -966,8 +966,9 @@ void ARMCodeEmitter::emitLoadStoreInstruction(const MachineInstr &MI,
// Part of binary is determined by TableGn.
unsigned Binary = getBinaryCodeForInstr(MI);
// If this is an LDRi12 or LDRcp, nothing more needs be done.
if (MI.getOpcode() == ARM::LDRi12 || MI.getOpcode() == ARM::LDRcp) {
// If this is an LDRi12, STRi12 or LDRcp, nothing more needs be done.
if (MI.getOpcode() == ARM::LDRi12 || MI.getOpcode() == ARM::LDRcp ||
MI.getOpcode() == ARM::STRi12) {
emitWordLE(Binary);
return;
}

View File

@ -805,17 +805,19 @@ bool ARMFastISel::ARMEmitStore(EVT VT, unsigned SrcReg,
unsigned Base, int Offset) {
unsigned StrOpc;
bool isFloat = false;
bool needReg0Op = false;
switch (VT.getSimpleVT().SimpleTy) {
default: return false;
case MVT::i1:
case MVT::i8:
StrOpc = isThumb ? ARM::t2STRBi12 : ARM::STRB;
StrOpc = isThumb ? ARM::t2STRBi12 : ARM::STRBi12;
break;
case MVT::i16:
StrOpc = isThumb ? ARM::t2STRHi12 : ARM::STRH;
needReg0Op = true;
break;
case MVT::i32:
StrOpc = isThumb ? ARM::t2STRi12 : ARM::STR;
StrOpc = isThumb ? ARM::t2STRi12 : ARM::STRi12;
break;
case MVT::f32:
if (!Subtarget->hasVFP2()) return false;
@ -836,9 +838,10 @@ bool ARMFastISel::ARMEmitStore(EVT VT, unsigned SrcReg,
if (isFloat)
Offset /= 4;
// The thumb addressing mode has operands swapped from the arm addressing
// mode, the floating point one only has two operands.
if (isFloat || isThumb)
// FIXME: The 'needReg0Op' bit goes away once STRH is converted to
// not use the mega-addrmode stuff.
if (!needReg0Op)
AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL,
TII.get(StrOpc))
.addReg(SrcReg).addReg(Base).addImm(Offset));

View File

@ -401,9 +401,10 @@ class AI2<dag oops, dag iops, Format f, InstrItinClass itin,
// loads
// LDR/LDRB
class AIldr1<bits<3> op, bit opc22, dag oops, dag iops, AddrMode am, Format f,
InstrItinClass itin, string opc, string asm, list<dag> pattern>
// LDR/LDRB/STR/STRB
class AIldst1<bits<3> op, bit opc22, bit isLd, dag oops, dag iops, AddrMode am,
Format f, InstrItinClass itin, string opc, string asm,
list<dag> pattern>
: I<oops, iops, am, Size4Bytes, IndexModeNone, f, itin, opc, asm,
"", pattern> {
let Inst{27-25} = op;
@ -411,7 +412,7 @@ class AIldr1<bits<3> op, bit opc22, dag oops, dag iops, AddrMode am, Format f,
// 23 == U
let Inst{22} = opc22;
let Inst{21} = 0; // 21 == W
let Inst{20} = 1;
let Inst{20} = isLd;
}
// LDRH/LDRSB/LDRSH/LDRD
class AIldr2<bits<4> op, bit opc22, bit opc20, dag oops, dag iops, AddrMode am,

View File

@ -48,13 +48,13 @@ unsigned ARMInstrInfo::getUnindexedOpcode(unsigned Opc) const {
return ARM::LDRSB;
case ARM::STR_PRE:
case ARM::STR_POST:
return ARM::STR;
return ARM::STRi12;
case ARM::STRH_PRE:
case ARM::STRH_POST:
return ARM::STRH;
case ARM::STRB_PRE:
case ARM::STRB_POST:
return ARM::STRB;
return ARM::STRBi12;
}
return 0;

View File

@ -813,7 +813,7 @@ multiclass AI_ldr1<bit opc22, string opc, InstrItinClass iii,
// Note: We use the complex addrmode_imm12 rather than just an input
// GPR and a constrained immediate so that we can use this to match
// frame index references and avoid matching constant pool references.
def i12 : AIldr1<0b010, opc22, (outs GPR:$Rt), (ins addrmode_imm12:$addr),
def i12 : AIldst1<0b010, opc22, 1, (outs GPR:$Rt), (ins addrmode_imm12:$addr),
AddrMode_i12, LdFrm, iii, opc, "\t$Rt, $addr",
[(set GPR:$Rt, (opnode addrmode_imm12:$addr))]> {
bits<4> Rt;
@ -823,7 +823,7 @@ multiclass AI_ldr1<bit opc22, string opc, InstrItinClass iii,
let Inst{15-12} = Rt;
let Inst{11-0} = addr{11-0}; // imm12
}
def rs : AIldr1<0b011, opc22, (outs GPR:$Rt), (ins ldst_so_reg:$shift),
def rs : AIldst1<0b011, opc22, 1, (outs GPR:$Rt), (ins ldst_so_reg:$shift),
AddrModeNone, LdFrm, iir, opc, "\t$Rt, $shift",
[(set GPR:$Rt, (opnode ldst_so_reg:$shift))]> {
bits<4> Rt;
@ -835,6 +835,32 @@ multiclass AI_ldr1<bit opc22, string opc, InstrItinClass iii,
}
}
multiclass AI_str1<bit opc22, string opc, InstrItinClass iii,
InstrItinClass iir, PatFrag opnode> {
// Note: We use the complex addrmode_imm12 rather than just an input
// GPR and a constrained immediate so that we can use this to match
// frame index references and avoid matching constant pool references.
def i12 : AIldst1<0b010, opc22, 0, (outs),
(ins GPR:$Rt, addrmode_imm12:$addr),
AddrMode_i12, StFrm, iii, opc, "\t$Rt, $addr",
[(opnode GPR:$Rt, addrmode_imm12:$addr)]> {
bits<4> Rt;
bits<17> addr;
let Inst{23} = addr{12}; // U (add = ('U' == 1))
let Inst{19-16} = addr{16-13}; // Rn
let Inst{15-12} = Rt;
let Inst{11-0} = addr{11-0}; // imm12
}
def rs : AIldst1<0b011, opc22, 0, (outs), (ins GPR:$Rt, ldst_so_reg:$shift),
AddrModeNone, StFrm, iir, opc, "\t$Rt, $shift",
[(opnode GPR:$Rt, ldst_so_reg:$shift)]> {
bits<4> Rt;
bits<17> shift;
let Inst{23} = shift{12}; // U (add = ('U' == 1))
let Inst{19-16} = shift{16-13}; // Rn
let Inst{11-0} = shift{11-0};
}
}
//===----------------------------------------------------------------------===//
// Instructions
//===----------------------------------------------------------------------===//
@ -1409,11 +1435,15 @@ defm LDR : AI_ldr1<0, "ldr", IIC_iLoad_i, IIC_iLoad_r,
UnOpFrag<(load node:$Src)>>;
defm LDRB : AI_ldr1<1, "ldrb", IIC_iLoad_bh_i, IIC_iLoad_bh_r,
UnOpFrag<(zextloadi8 node:$Src)>>;
defm STR : AI_str1<0, "str", IIC_iStore_i, IIC_iStore_r,
BinOpFrag<(store node:$LHS, node:$RHS)>>;
defm STRB : AI_str1<1, "strb", IIC_iStore_bh_i, IIC_iStore_bh_r,
BinOpFrag<(truncstorei8 node:$LHS, node:$RHS)>>;
// Special LDR for loads from non-pc-relative constpools.
let canFoldAsLoad = 1, mayLoad = 1, neverHasSideEffects = 1,
isReMaterializable = 1 in
def LDRcp : AIldr1<0b010, 0, (outs GPR:$Rt), (ins addrmode_imm12:$addr),
def LDRcp : AIldst1<0b010, 0, 1, (outs GPR:$Rt), (ins addrmode_imm12:$addr),
AddrMode_i12, LdFrm, IIC_iLoad_r, "ldr", "\t$Rt, $addr", []> {
bits<4> Rt;
bits<17> addr;
@ -1531,19 +1561,12 @@ def LDRSHT : AI3ldshpo<(outs GPR:$dst, GPR:$base_wb),
}
// Store
def STR : AI2stw<(outs), (ins GPR:$src, addrmode2:$addr), StFrm, IIC_iStore_r,
"str", "\t$src, $addr",
[(store GPR:$src, addrmode2:$addr)]>;
// Stores with truncate
def STRH : AI3sth<(outs), (ins GPR:$src, addrmode3:$addr), StMiscFrm,
IIC_iStore_bh_r, "strh", "\t$src, $addr",
[(truncstorei16 GPR:$src, addrmode3:$addr)]>;
def STRB : AI2stb<(outs), (ins GPR:$src, addrmode2:$addr), StFrm,
IIC_iStore_bh_r, "strb", "\t$src, $addr",
[(truncstorei8 GPR:$src, addrmode2:$addr)]>;
// Store doubleword
let mayStore = 1, neverHasSideEffects = 1, hasExtraSrcRegAllocReq = 1 in
def STRD : AI3std<(outs), (ins GPR:$src1, GPR:$src2, addrmode3:$addr),

View File

@ -133,7 +133,7 @@ static int getLoadStoreMultipleOpcode(int Opcode) {
case ARM::LDRi12:
++NumLDMGened;
return ARM::LDM;
case ARM::STR:
case ARM::STRi12:
++NumSTMGened;
return ARM::STM;
case ARM::t2LDRi8:
@ -174,7 +174,7 @@ static bool isT2i32Store(unsigned Opc) {
}
static bool isi32Store(unsigned Opc) {
return Opc == ARM::STR || isT2i32Store(Opc);
return Opc == ARM::STRi12 || isT2i32Store(Opc);
}
/// MergeOps - Create and insert a LDM or STM with Base as base register and
@ -441,7 +441,7 @@ static inline unsigned getLSMultipleTransferSize(MachineInstr *MI) {
switch (MI->getOpcode()) {
default: return 0;
case ARM::LDRi12:
case ARM::STR:
case ARM::STRi12:
case ARM::t2LDRi8:
case ARM::t2LDRi12:
case ARM::t2STRi8:
@ -579,7 +579,7 @@ bool ARMLoadStoreOpt::MergeBaseUpdateLSMultiple(MachineBasicBlock &MBB,
static unsigned getPreIndexedLoadStoreOpcode(unsigned Opc) {
switch (Opc) {
case ARM::LDRi12: return ARM::LDR_PRE;
case ARM::STR: return ARM::STR_PRE;
case ARM::STRi12: return ARM::STR_PRE;
case ARM::VLDRS: return ARM::VLDMS_UPD;
case ARM::VLDRD: return ARM::VLDMD_UPD;
case ARM::VSTRS: return ARM::VSTMS_UPD;
@ -598,7 +598,7 @@ static unsigned getPreIndexedLoadStoreOpcode(unsigned Opc) {
static unsigned getPostIndexedLoadStoreOpcode(unsigned Opc) {
switch (Opc) {
case ARM::LDRi12: return ARM::LDR_POST;
case ARM::STR: return ARM::STR_POST;
case ARM::STRi12: return ARM::STR_POST;
case ARM::VLDRS: return ARM::VLDMS_UPD;
case ARM::VLDRD: return ARM::VLDMD_UPD;
case ARM::VSTRS: return ARM::VSTMS_UPD;
@ -629,16 +629,10 @@ bool ARMLoadStoreOpt::MergeBaseUpdateLoadStore(MachineBasicBlock &MBB,
DebugLoc dl = MI->getDebugLoc();
bool isAM5 = (Opcode == ARM::VLDRD || Opcode == ARM::VLDRS ||
Opcode == ARM::VSTRD || Opcode == ARM::VSTRS);
bool isAM2 = (Opcode == ARM::LDRi12 || Opcode == ARM::STR);
// FIXME: This special handling of LDRi12 is hackery until all of the ARM
// LDR/STR insns are moved away from the addrmode2 mega-instruction to
// the split (LDRi12/LDRrs) style instructions.
if (Opcode == ARM::LDRi12 || isT2i32Load(Opcode) || isT2i32Store(Opcode))
bool isAM2 = (Opcode == ARM::LDRi12 || Opcode == ARM::STRi12);
if (isi32Load(Opcode) || isi32Store(Opcode))
if (MI->getOperand(2).getImm() != 0)
return false;
if (isAM2 && Opcode != ARM::LDRi12
&& ARM_AM::getAM2Offset(MI->getOperand(3).getImm()) != 0)
return false;
if (isAM5 && ARM_AM::getAM5Offset(MI->getOperand(2).getImm()) != 0)
return false;
@ -786,8 +780,6 @@ static bool isMemoryOp(const MachineInstr *MI) {
int Opcode = MI->getOpcode();
switch (Opcode) {
default: break;
case ARM::STR:
return MI->getOperand(1).isReg() && MI->getOperand(2).getReg() == 0;
case ARM::VLDRS:
case ARM::VSTRS:
return MI->getOperand(1).isReg();
@ -795,6 +787,7 @@ static bool isMemoryOp(const MachineInstr *MI) {
case ARM::VSTRD:
return MI->getOperand(1).isReg();
case ARM::LDRi12:
case ARM::STRi12:
case ARM::t2LDRi8:
case ARM::t2LDRi12:
case ARM::t2STRi8:
@ -822,7 +815,6 @@ void ARMLoadStoreOpt::AdvanceRS(MachineBasicBlock &MBB, MemOpQueue &MemOps) {
static int getMemoryOpOffset(const MachineInstr *MI) {
int Opcode = MI->getOpcode();
bool isAM2 = Opcode == ARM::STR;
bool isAM3 = Opcode == ARM::LDRD || Opcode == ARM::STRD;
unsigned NumOperands = MI->getDesc().getNumOperands();
unsigned OffField = MI->getOperand(NumOperands-3).getImm();
@ -830,17 +822,12 @@ static int getMemoryOpOffset(const MachineInstr *MI) {
if (Opcode == ARM::t2LDRi12 || Opcode == ARM::t2LDRi8 ||
Opcode == ARM::t2STRi12 || Opcode == ARM::t2STRi8 ||
Opcode == ARM::t2LDRDi8 || Opcode == ARM::t2STRDi8 ||
Opcode == ARM::LDRi12)
Opcode == ARM::LDRi12 || Opcode == ARM::STRi12)
return OffField;
int Offset = isAM2
? ARM_AM::getAM2Offset(OffField)
: (isAM3 ? ARM_AM::getAM3Offset(OffField)
: ARM_AM::getAM5Offset(OffField) * 4);
if (isAM2) {
if (ARM_AM::getAM2Op(OffField) == ARM_AM::sub)
Offset = -Offset;
} else if (isAM3) {
int Offset = isAM3 ? ARM_AM::getAM3Offset(OffField)
: ARM_AM::getAM5Offset(OffField) * 4;
if (isAM3) {
if (ARM_AM::getAM3Op(OffField) == ARM_AM::sub)
Offset = -Offset;
} else {
@ -852,22 +839,13 @@ static int getMemoryOpOffset(const MachineInstr *MI) {
static void InsertLDR_STR(MachineBasicBlock &MBB,
MachineBasicBlock::iterator &MBBI,
int OffImm, bool isDef,
int Offset, bool isDef,
DebugLoc dl, unsigned NewOpc,
unsigned Reg, bool RegDeadKill, bool RegUndef,
unsigned BaseReg, bool BaseKill, bool BaseUndef,
unsigned OffReg, bool OffKill, bool OffUndef,
bool OffKill, bool OffUndef,
ARMCC::CondCodes Pred, unsigned PredReg,
const TargetInstrInfo *TII, bool isT2) {
int Offset = OffImm;
// FIXME: This fancy offset encoding stuff goes away when we're done
// removing addrmode2.
if (!isT2 && !isDef) {
if (OffImm < 0)
Offset = ARM_AM::getAM2Opc(ARM_AM::sub, -OffImm, ARM_AM::no_shift);
else
Offset = ARM_AM::getAM2Opc(ARM_AM::add, OffImm, ARM_AM::no_shift);
}
if (isDef) {
MachineInstrBuilder MIB = BuildMI(MBB, MBBI, MBBI->getDebugLoc(),
TII->get(NewOpc))
@ -879,8 +857,6 @@ static void InsertLDR_STR(MachineBasicBlock &MBB,
TII->get(NewOpc))
.addReg(Reg, getKillRegState(RegDeadKill) | getUndefRegState(RegUndef))
.addReg(BaseReg, getKillRegState(BaseKill)|getUndefRegState(BaseUndef));
if (!isT2)
MIB.addReg(OffReg, getKillRegState(OffKill)|getUndefRegState(OffUndef));
MIB.addImm(Offset).addImm(Pred).addReg(PredReg);
}
}
@ -911,14 +887,13 @@ bool ARMLoadStoreOpt::FixInvalidRegPairOp(MachineBasicBlock &MBB,
unsigned BaseReg = BaseOp.getReg();
bool BaseKill = BaseOp.isKill();
bool BaseUndef = BaseOp.isUndef();
unsigned OffReg = isT2 ? 0 : MI->getOperand(3).getReg();
bool OffKill = isT2 ? false : MI->getOperand(3).isKill();
bool OffUndef = isT2 ? false : MI->getOperand(3).isUndef();
int OffImm = getMemoryOpOffset(MI);
unsigned PredReg = 0;
ARMCC::CondCodes Pred = llvm::getInstrPredicate(MI, PredReg);
if (OddRegNum > EvenRegNum && OffReg == 0 && OffImm == 0) {
if (OddRegNum > EvenRegNum && OffImm == 0) {
// Ascending register numbers and no offset. It's safe to change it to a
// ldm or stm.
unsigned NewOpc = (isLd)
@ -946,28 +921,24 @@ bool ARMLoadStoreOpt::FixInvalidRegPairOp(MachineBasicBlock &MBB,
NewBBI = llvm::prior(MBBI);
} else {
// Split into two instructions.
assert((!isT2 || !OffReg) &&
"Thumb2 ldrd / strd does not encode offset register!");
unsigned NewOpc = (isLd)
? (isT2 ? (OffImm < 0 ? ARM::t2LDRi8 : ARM::t2LDRi12) : ARM::LDRi12)
: (isT2 ? (OffImm < 0 ? ARM::t2STRi8 : ARM::t2STRi12) : ARM::STR);
: (isT2 ? (OffImm < 0 ? ARM::t2STRi8 : ARM::t2STRi12) : ARM::STRi12);
DebugLoc dl = MBBI->getDebugLoc();
// If this is a load and base register is killed, it may have been
// re-defed by the load, make sure the first load does not clobber it.
if (isLd &&
(BaseKill || OffKill) &&
(TRI->regsOverlap(EvenReg, BaseReg) ||
(OffReg && TRI->regsOverlap(EvenReg, OffReg)))) {
assert(!TRI->regsOverlap(OddReg, BaseReg) &&
(!OffReg || !TRI->regsOverlap(OddReg, OffReg)));
(TRI->regsOverlap(EvenReg, BaseReg))) {
assert(!TRI->regsOverlap(OddReg, BaseReg));
InsertLDR_STR(MBB, MBBI, OffImm+4, isLd, dl, NewOpc,
OddReg, OddDeadKill, false,
BaseReg, false, BaseUndef, OffReg, false, OffUndef,
BaseReg, false, BaseUndef, false, OffUndef,
Pred, PredReg, TII, isT2);
NewBBI = llvm::prior(MBBI);
InsertLDR_STR(MBB, MBBI, OffImm, isLd, dl, NewOpc,
EvenReg, EvenDeadKill, false,
BaseReg, BaseKill, BaseUndef, OffReg, OffKill, OffUndef,
BaseReg, BaseKill, BaseUndef, OffKill, OffUndef,
Pred, PredReg, TII, isT2);
} else {
if (OddReg == EvenReg && EvenDeadKill) {
@ -979,12 +950,12 @@ bool ARMLoadStoreOpt::FixInvalidRegPairOp(MachineBasicBlock &MBB,
}
InsertLDR_STR(MBB, MBBI, OffImm, isLd, dl, NewOpc,
EvenReg, EvenDeadKill, EvenUndef,
BaseReg, false, BaseUndef, OffReg, false, OffUndef,
BaseReg, false, BaseUndef, false, OffUndef,
Pred, PredReg, TII, isT2);
NewBBI = llvm::prior(MBBI);
InsertLDR_STR(MBB, MBBI, OffImm+4, isLd, dl, NewOpc,
OddReg, OddDeadKill, OddUndef,
BaseReg, BaseKill, BaseUndef, OffReg, OffKill, OffUndef,
BaseReg, BaseKill, BaseUndef, OffKill, OffUndef,
Pred, PredReg, TII, isT2);
}
if (isLd)
@ -1256,7 +1227,7 @@ namespace {
bool CanFormLdStDWord(MachineInstr *Op0, MachineInstr *Op1, DebugLoc &dl,
unsigned &NewOpc, unsigned &EvenReg,
unsigned &OddReg, unsigned &BaseReg,
unsigned &OffReg, int &Offset,
int &Offset,
unsigned &PredReg, ARMCC::CondCodes &Pred,
bool &isT2);
bool RescheduleOps(MachineBasicBlock *MBB,
@ -1336,8 +1307,7 @@ ARMPreAllocLoadStoreOpt::CanFormLdStDWord(MachineInstr *Op0, MachineInstr *Op1,
DebugLoc &dl,
unsigned &NewOpc, unsigned &EvenReg,
unsigned &OddReg, unsigned &BaseReg,
unsigned &OffReg, int &Offset,
unsigned &PredReg,
int &Offset, unsigned &PredReg,
ARMCC::CondCodes &Pred,
bool &isT2) {
// Make sure we're allowed to generate LDRD/STRD.
@ -1349,7 +1319,7 @@ ARMPreAllocLoadStoreOpt::CanFormLdStDWord(MachineInstr *Op0, MachineInstr *Op1,
unsigned Opcode = Op0->getOpcode();
if (Opcode == ARM::LDRi12)
NewOpc = ARM::LDRD;
else if (Opcode == ARM::STR)
else if (Opcode == ARM::STRi12)
NewOpc = ARM::STRD;
else if (Opcode == ARM::t2LDRi8 || Opcode == ARM::t2LDRi12) {
NewOpc = ARM::t2LDRDi8;
@ -1362,11 +1332,6 @@ ARMPreAllocLoadStoreOpt::CanFormLdStDWord(MachineInstr *Op0, MachineInstr *Op1,
} else
return false;
// Make sure the offset registers match.
if (!isT2 && Opcode != ARM::LDRi12 &&
(Op0->getOperand(2).getReg() != Op1->getOperand(2).getReg()))
return false;
// Make sure the base address satisfies i64 ld / st alignment requirement.
if (!Op0->hasOneMemOperand() ||
!(*Op0->memoperands_begin())->getValue() ||
@ -1376,7 +1341,7 @@ ARMPreAllocLoadStoreOpt::CanFormLdStDWord(MachineInstr *Op0, MachineInstr *Op1,
unsigned Align = (*Op0->memoperands_begin())->getAlignment();
const Function *Func = MF->getFunction();
unsigned ReqAlign = STI->hasV6Ops()
? TD->getABITypeAlignment(Type::getInt64Ty(Func->getContext()))
? TD->getABITypeAlignment(Type::getInt64Ty(Func->getContext()))
: 8; // Pre-v6 need 8-byte align
if (Align < ReqAlign)
return false;
@ -1410,8 +1375,6 @@ ARMPreAllocLoadStoreOpt::CanFormLdStDWord(MachineInstr *Op0, MachineInstr *Op1,
if (EvenReg == OddReg)
return false;
BaseReg = Op0->getOperand(1).getReg();
if (!isT2 && Opcode != ARM::LDRi12)
OffReg = Op0->getOperand(2).getReg();
Pred = llvm::getInstrPredicate(Op0, PredReg);
dl = Op0->getDebugLoc();
return true;
@ -1499,14 +1462,14 @@ bool ARMPreAllocLoadStoreOpt::RescheduleOps(MachineBasicBlock *MBB,
MachineInstr *Op0 = Ops.back();
MachineInstr *Op1 = Ops[Ops.size()-2];
unsigned EvenReg = 0, OddReg = 0;
unsigned BaseReg = 0, OffReg = 0, PredReg = 0;
unsigned BaseReg = 0, PredReg = 0;
ARMCC::CondCodes Pred = ARMCC::AL;
bool isT2 = false;
unsigned NewOpc = 0;
int Offset = 0;
DebugLoc dl;
if (NumMove == 2 && CanFormLdStDWord(Op0, Op1, dl, NewOpc,
EvenReg, OddReg, BaseReg, OffReg,
EvenReg, OddReg, BaseReg,
Offset, PredReg, Pred, isT2)) {
Ops.pop_back();
Ops.pop_back();
@ -1518,10 +1481,9 @@ bool ARMPreAllocLoadStoreOpt::RescheduleOps(MachineBasicBlock *MBB,
.addReg(EvenReg, RegState::Define)
.addReg(OddReg, RegState::Define)
.addReg(BaseReg);
// For now, we're converting from LDRi12 to an insn that still
// FIXME: We're converting from LDRi12 to an insn that still
// uses addrmode2, so we need an explicit offset reg. It should
// always by reg0 since we're transforming LDRi12s. The old
// was just being paranoid in allowing for anything else.
// always by reg0 since we're transforming LDRi12s.
if (!isT2)
MIB.addReg(0);
MIB.addImm(Offset).addImm(Pred).addReg(PredReg);
@ -1532,8 +1494,11 @@ bool ARMPreAllocLoadStoreOpt::RescheduleOps(MachineBasicBlock *MBB,
.addReg(EvenReg)
.addReg(OddReg)
.addReg(BaseReg);
// FIXME: We're converting from LDRi12 to an insn that still
// uses addrmode2, so we need an explicit offset reg. It should
// always by reg0 since we're transforming STRi12s.
if (!isT2)
MIB.addReg(OffReg);
MIB.addReg(0);
MIB.addImm(Offset).addImm(Pred).addReg(PredReg);
++NumSTRDFormed;
}