mirror of
https://github.com/RPCSX/llvm.git
synced 2025-01-01 01:14:22 +00: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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@117505 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
0bccec368a
commit
7e3383c007
@ -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));
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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));
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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),
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user