diff --git a/lib/Target/ARM/ARMFrameLowering.cpp b/lib/Target/ARM/ARMFrameLowering.cpp index 13fe7d624fe..8814f874453 100644 --- a/lib/Target/ARM/ARMFrameLowering.cpp +++ b/lib/Target/ARM/ARMFrameLowering.cpp @@ -588,14 +588,8 @@ void ARMFrameLowering::emitPushInst(MachineBasicBlock &MBB, MachineInstrBuilder MIB = BuildMI(MBB, MI, DL, TII.get(StrOpc), ARM::SP) .addReg(Regs[0].first, getKillRegState(Regs[0].second)) - .addReg(ARM::SP).setMIFlags(MIFlags); - // ARM mode needs an extra reg0 here due to addrmode2. Will go away once - // that refactoring is complete (eventually). - if (StrOpc == ARM::STR_PRE_REG || StrOpc == ARM::STR_PRE_IMM) { - MIB.addReg(0); - MIB.addImm(ARM_AM::getAM2Opc(ARM_AM::sub, 4, ARM_AM::no_shift)); - } else - MIB.addImm(-4); + .addReg(ARM::SP).setMIFlags(MIFlags) + .addImm(-4); AddDefaultPred(MIB); } Regs.clear(); diff --git a/lib/Target/ARM/ARMISelDAGToDAG.cpp b/lib/Target/ARM/ARMISelDAGToDAG.cpp index 74d877a27fc..ceceddb248a 100644 --- a/lib/Target/ARM/ARMISelDAGToDAG.cpp +++ b/lib/Target/ARM/ARMISelDAGToDAG.cpp @@ -133,6 +133,7 @@ public: SDValue &Offset, SDValue &Opc); bool SelectAddrMode2OffsetImm(SDNode *Op, SDValue N, SDValue &Offset, SDValue &Opc); + bool SelectAddrOffsetNone(SDValue N, SDValue &Base); bool SelectAddrMode3(SDValue N, SDValue &Base, SDValue &Offset, SDValue &Opc); bool SelectAddrMode3Offset(SDNode *Op, SDValue N, @@ -772,8 +773,10 @@ bool ARMDAGToDAGISel::SelectAddrMode2OffsetImm(SDNode *Op, SDValue N, return false; } - - +bool ARMDAGToDAGISel::SelectAddrOffsetNone(SDValue N, SDValue &Base) { + Base = N; + return true; +} bool ARMDAGToDAGISel::SelectAddrMode3(SDValue N, SDValue &Base, SDValue &Offset, diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index 60de3e9b1dd..b72467f16ac 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -5289,6 +5289,37 @@ ARMTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, MI->dump(); llvm_unreachable("Unexpected instr type to insert"); } + case ARM::STRi_preidx: + case ARM::STRBi_preidx: { + unsigned NewOpc = MI->getOpcode() == ARM::STRr_preidx ? + ARM::STR_PRE_IMM : ARM::STRB_PRE_IMM; + // Decode the offset. + unsigned Offset = MI->getOperand(4).getImm(); + bool isSub = ARM_AM::getAM2Op(Offset) == ARM_AM::sub; + Offset = ARM_AM::getAM2Offset(Offset); + if (isSub) + Offset = -Offset; + + MachineInstrBuilder MIB = BuildMI(*BB, MI, dl, TII->get(NewOpc)) + .addOperand(MI->getOperand(0)) // Rn_wb + .addOperand(MI->getOperand(1)) // Rt + .addOperand(MI->getOperand(2)) // Rn + .addImm(Offset) // offset (skip GPR==zero_reg) + .addOperand(MI->getOperand(5)) // pred + .addOperand(MI->getOperand(6)); + MI->eraseFromParent(); + return BB; + } + case ARM::STRr_preidx: + case ARM::STRBr_preidx: { + unsigned NewOpc = MI->getOpcode() == ARM::STRr_preidx ? + ARM::STR_PRE_REG : ARM::STRB_PRE_REG; + MachineInstrBuilder MIB = BuildMI(*BB, MI, dl, TII->get(NewOpc)); + for (unsigned i = 0; i < MI->getNumOperands(); ++i) + MIB.addOperand(MI->getOperand(i)); + MI->eraseFromParent(); + return BB; + } case ARM::ATOMIC_LOAD_ADD_I8: return EmitAtomicBinary(MI, BB, 1, isThumb2 ? ARM::t2ADDrr : ARM::ADDrr); case ARM::ATOMIC_LOAD_ADD_I16: diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index 99584d4445f..8f81bd236ab 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -769,7 +769,8 @@ def addrmodepc : Operand, // addr_offset_none := reg // def MemNoOffsetAsmOperand : AsmOperandClass { let Name = "MemNoOffset"; } -def addr_offset_none : Operand { +def addr_offset_none : Operand, + ComplexPattern { let PrintMethod = "printAddrMode7Operand"; let ParserMatchClass = MemNoOffsetAsmOperand; let MIOperandInfo = (ops GPR:$base); @@ -1926,7 +1927,6 @@ multiclass AI2_ldridx { let Inst{23} = offset{12}; let Inst{19-16} = addr; let Inst{11-0} = offset{11-0}; - let DecoderMethod = "DecodeAddrMode2IdxInstruction"; } def _POST_IMM : AI2ldstidx<1, isByte, 0, (outs GPR:$Rt, GPR:$Rn_wb), @@ -1942,7 +1942,6 @@ multiclass AI2_ldridx { let Inst{23} = offset{12}; let Inst{19-16} = addr; let Inst{11-0} = offset{11-0}; - let DecoderMethod = "DecodeAddrMode2IdxInstruction"; } } @@ -2092,69 +2091,111 @@ def STRD : AI3str<0b1111, (outs), (ins GPR:$Rt, GPR:$src2, addrmode3:$addr), } // Indexed stores -def STR_PRE_REG : AI2stridx_reg<0, 1, (outs GPR:$Rn_wb), - (ins GPR:$Rt, GPR:$Rn, am2offset_reg:$offset), - IndexModePre, StFrm, IIC_iStore_ru, - "str", "\t$Rt, [$Rn, $offset]!", - "$Rn = $Rn_wb,@earlyclobber $Rn_wb", - [(set GPR:$Rn_wb, - (pre_store GPR:$Rt, GPR:$Rn, am2offset_reg:$offset))]>; -def STR_PRE_IMM : AI2stridx_imm<0, 1, (outs GPR:$Rn_wb), - (ins GPR:$Rt, GPR:$Rn, am2offset_imm:$offset), - IndexModePre, StFrm, IIC_iStore_ru, - "str", "\t$Rt, [$Rn, $offset]!", - "$Rn = $Rn_wb,@earlyclobber $Rn_wb", - [(set GPR:$Rn_wb, - (pre_store GPR:$Rt, GPR:$Rn, am2offset_imm:$offset))]>; +multiclass AI2_stridx { + def _PRE_IMM : AI2ldstidx<0, isByte, 1, (outs GPR:$Rn_wb), + (ins GPR:$Rt, addrmode_imm12:$addr), IndexModePre, + StFrm, itin, + opc, "\t$Rt, $addr!", "$addr.base = $Rn_wb", []> { + bits<17> addr; + let Inst{25} = 0; + let Inst{23} = addr{12}; // U (add = ('U' == 1)) + let Inst{19-16} = addr{16-13}; // Rn + let Inst{11-0} = addr{11-0}; // imm12 + let AsmMatchConverter = "cvtStWriteBackRegAddrMode2"; + } + def _PRE_REG : AI2ldstidx<0, isByte, 1, (outs GPR:$Rn_wb), + (ins GPR:$Rt, addrmode2:$addr), IndexModePre, StFrm, itin, + opc, "\t$Rt, $addr!", "$addr.base = $Rn_wb", []> { + bits<17> addr; + let Inst{25} = 1; + let Inst{23} = addr{12}; // U (add = ('U' == 1)) + let Inst{19-16} = addr{16-13}; // Rn + let Inst{11-0} = addr{11-0}; + let Inst{4} = 0; // Inst{4} = 0 + let AsmMatchConverter = "cvtStWriteBackRegAddrMode2"; + } + def _POST_REG : AI2ldstidx<0, isByte, 0, (outs GPR:$Rn_wb), + (ins GPR:$Rt, addr_offset_none:$addr, am2offset_reg:$offset), + IndexModePost, StFrm, itin, + opc, "\t$Rt, $addr, $offset", + "$addr.base = $Rn_wb", []> { + // {12} isAdd + // {11-0} imm12/Rm + bits<14> offset; + bits<4> addr; + let Inst{25} = 1; + let Inst{23} = offset{12}; + let Inst{19-16} = addr; + let Inst{11-0} = offset{11-0}; + } + def _POST_IMM : AI2ldstidx<0, isByte, 0, (outs GPR:$Rn_wb), + (ins GPR:$Rt, addr_offset_none:$addr, am2offset_imm:$offset), + IndexModePost, StFrm, itin, + opc, "\t$Rt, $addr, $offset", + "$addr.base = $Rn_wb", []> { + // {12} isAdd + // {11-0} imm12/Rm + bits<14> offset; + bits<4> addr; + let Inst{25} = 0; + let Inst{23} = offset{12}; + let Inst{19-16} = addr; + let Inst{11-0} = offset{11-0}; + } +} -def STR_POST_REG : AI2stridx_reg<0, 0, (outs GPR:$Rn_wb), - (ins GPR:$Rt, GPR:$Rn, am2offset_reg:$offset), - IndexModePost, StFrm, IIC_iStore_ru, - "str", "\t$Rt, [$Rn], $offset", - "$Rn = $Rn_wb,@earlyclobber $Rn_wb", - [(set GPR:$Rn_wb, - (post_store GPR:$Rt, GPR:$Rn, am2offset_reg:$offset))]>; -def STR_POST_IMM : AI2stridx_imm<0, 0, (outs GPR:$Rn_wb), - (ins GPR:$Rt, GPR:$Rn, am2offset_imm:$offset), - IndexModePost, StFrm, IIC_iStore_ru, - "str", "\t$Rt, [$Rn], $offset", - "$Rn = $Rn_wb,@earlyclobber $Rn_wb", - [(set GPR:$Rn_wb, - (post_store GPR:$Rt, GPR:$Rn, am2offset_imm:$offset))]>; +let mayStore = 1, neverHasSideEffects = 1 in { +defm STR : AI2_stridx<0, "str", IIC_iStore_ru>; +defm STRB : AI2_stridx<1, "strb", IIC_iStore_bh_ru>; +} +def : ARMPat<(post_store GPR:$Rt, addr_offset_none:$addr, + am2offset_reg:$offset), + (STR_POST_REG GPR:$Rt, addr_offset_none:$addr, + am2offset_reg:$offset)>; +def : ARMPat<(post_store GPR:$Rt, addr_offset_none:$addr, + am2offset_imm:$offset), + (STR_POST_IMM GPR:$Rt, addr_offset_none:$addr, + am2offset_imm:$offset)>; +def : ARMPat<(post_truncsti8 GPR:$Rt, addr_offset_none:$addr, + am2offset_reg:$offset), + (STRB_POST_REG GPR:$Rt, addr_offset_none:$addr, + am2offset_reg:$offset)>; +def : ARMPat<(post_truncsti8 GPR:$Rt, addr_offset_none:$addr, + am2offset_imm:$offset), + (STRB_POST_IMM GPR:$Rt, addr_offset_none:$addr, + am2offset_imm:$offset)>; -def STRB_PRE_REG : AI2stridx_reg<1, 1, (outs GPR:$Rn_wb), - (ins GPR:$Rt, GPR:$Rn, am2offset_reg:$offset), - IndexModePre, StFrm, IIC_iStore_bh_ru, - "strb", "\t$Rt, [$Rn, $offset]!", - "$Rn = $Rn_wb,@earlyclobber $Rn_wb", - [(set GPR:$Rn_wb, (pre_truncsti8 GPR:$Rt, - GPR:$Rn, am2offset_reg:$offset))]>; -def STRB_PRE_IMM : AI2stridx_imm<1, 1, (outs GPR:$Rn_wb), - (ins GPR:$Rt, GPR:$Rn, am2offset_imm:$offset), - IndexModePre, StFrm, IIC_iStore_bh_ru, - "strb", "\t$Rt, [$Rn, $offset]!", - "$Rn = $Rn_wb,@earlyclobber $Rn_wb", - [(set GPR:$Rn_wb, (pre_truncsti8 GPR:$Rt, - GPR:$Rn, am2offset_imm:$offset))]>; - -def STRB_POST_REG: AI2stridx_reg<1, 0, (outs GPR:$Rn_wb), - (ins GPR:$Rt, GPR:$Rn, am2offset_reg:$offset), - IndexModePost, StFrm, IIC_iStore_bh_ru, - "strb", "\t$Rt, [$Rn], $offset", - "$Rn = $Rn_wb,@earlyclobber $Rn_wb", - [(set GPR:$Rn_wb, (post_truncsti8 GPR:$Rt, - GPR:$Rn, am2offset_reg:$offset))]>; -def STRB_POST_IMM: AI2stridx_imm<1, 0, (outs GPR:$Rn_wb), - (ins GPR:$Rt, GPR:$Rn, am2offset_imm:$offset), - IndexModePost, StFrm, IIC_iStore_bh_ru, - "strb", "\t$Rt, [$Rn], $offset", - "$Rn = $Rn_wb,@earlyclobber $Rn_wb", - [(set GPR:$Rn_wb, (post_truncsti8 GPR:$Rt, - GPR:$Rn, am2offset_imm:$offset))]>; - +// Pseudo-instructions for pattern matching the pre-indexed stores. We can't +// put the patterns on the instruction definitions directly as ISel wants +// the address base and offset to be separate operands, not a single +// complex operand like we represent the instructions themselves. The +// pseudos map between the two. +let usesCustomInserter = 1, + Constraints = "$Rn = $Rn_wb,@earlyclobber $Rn_wb" in { +def STRi_preidx: ARMPseudoInst<(outs GPR:$Rn_wb), + (ins GPR:$Rt, GPR:$Rn, am2offset_imm:$offset, pred:$p), + 4, IIC_iStore_ru, + [(set GPR:$Rn_wb, + (pre_store GPR:$Rt, GPR:$Rn, am2offset_imm:$offset))]>; +def STRr_preidx: ARMPseudoInst<(outs GPR:$Rn_wb), + (ins GPR:$Rt, GPR:$Rn, am2offset_reg:$offset, pred:$p), + 4, IIC_iStore_ru, + [(set GPR:$Rn_wb, + (pre_store GPR:$Rt, GPR:$Rn, am2offset_reg:$offset))]>; +def STRBi_preidx: ARMPseudoInst<(outs GPR:$Rn_wb), + (ins GPR:$Rt, GPR:$Rn, am2offset_imm:$offset, pred:$p), + 4, IIC_iStore_ru, + [(set GPR:$Rn_wb, + (pre_truncsti8 GPR:$Rt, GPR:$Rn, am2offset_imm:$offset))]>; +def STRBr_preidx: ARMPseudoInst<(outs GPR:$Rn_wb), + (ins GPR:$Rt, GPR:$Rn, am2offset_reg:$offset, pred:$p), + 4, IIC_iStore_ru, + [(set GPR:$Rn_wb, + (pre_truncsti8 GPR:$Rt, GPR:$Rn, am2offset_reg:$offset))]>; +} def STRH_PRE : AI3stridx<0b1011, 0, 1, (outs GPR:$Rn_wb), (ins GPR:$Rt, GPR:$Rn, am3offset:$offset), diff --git a/lib/Target/ARM/ARMLoadStoreOptimizer.cpp b/lib/Target/ARM/ARMLoadStoreOptimizer.cpp index ee0028c2ea6..d29ce3ab4e5 100644 --- a/lib/Target/ARM/ARMLoadStoreOptimizer.cpp +++ b/lib/Target/ARM/ARMLoadStoreOptimizer.cpp @@ -894,7 +894,10 @@ bool ARMLoadStoreOpt::MergeBaseUpdateLoadStore(MachineBasicBlock &MBB, return false; unsigned Offset = 0; - if (isAM2) + // FIXME: Loads still use a combined reg/imm offset operand. When + // AM2 refactoring is complete, this can go away and just always use + // the raw Offset value. + if (isAM2 && isLd) Offset = ARM_AM::getAM2Opc(AddSub, Bytes, ARM_AM::no_shift); else if (!isAM5) Offset = AddSub == ARM_AM::sub ? -Bytes : Bytes; @@ -924,7 +927,10 @@ bool ARMLoadStoreOpt::MergeBaseUpdateLoadStore(MachineBasicBlock &MBB, .addReg(Base).addImm(Offset).addImm(Pred).addReg(PredReg); } else { MachineOperand &MO = MI->getOperand(0); - if (isAM2) + // FIXME: post-indexed stores use am2offset_imm, which still encodes + // the vestigal zero-reg offset register. When that's fixed, this clause + // can be removed entirely. + if (isAM2 && NewOpc == ARM::STR_POST_IMM) // STR_PRE, STR_POST BuildMI(MBB, MBBI, dl, TII->get(NewOpc), Base) .addReg(MO.getReg(), getKillRegState(MO.isKill()))