From: Owen Anderson Date: Tue, 26 Jul 2011 20:54:26 +0000 (+0000) Subject: Split am2offset into register addend and immediate addend forms, necessary for allowi... X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=793e79601f0fd68ba082fa2016018f80b2379460;p=oota-llvm.git Split am2offset into register addend and immediate addend forms, necessary for allowing the fixed-length disassembler to distinguish between SBFX and STR_PRE. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@136141 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/ARM/ARMAsmPrinter.cpp b/lib/Target/ARM/ARMAsmPrinter.cpp index 3a10cc8e3cd..c9a5fca393b 100644 --- a/lib/Target/ARM/ARMAsmPrinter.cpp +++ b/lib/Target/ARM/ARMAsmPrinter.cpp @@ -994,7 +994,8 @@ void ARMAsmPrinter::EmitUnwindingInstruction(const MachineInstr *MI) { i != NumOps; ++i) RegList.push_back(MI->getOperand(i).getReg()); break; - case ARM::STR_PRE: + case ARM::STR_PRE_IMM: + case ARM::STR_PRE_REG: assert(MI->getOperand(2).getReg() == ARM::SP && "Only stack pointer as a source reg is supported"); RegList.push_back(SrcReg); diff --git a/lib/Target/ARM/ARMFrameLowering.cpp b/lib/Target/ARM/ARMFrameLowering.cpp index da61ccbceb9..13fe7d624fe 100644 --- a/lib/Target/ARM/ARMFrameLowering.cpp +++ b/lib/Target/ARM/ARMFrameLowering.cpp @@ -93,7 +93,8 @@ static bool isCSRestore(MachineInstr *MI, return false; return true; } - if ((MI->getOpcode() == ARM::LDR_POST || + if ((MI->getOpcode() == ARM::LDR_POST_IMM || + MI->getOpcode() == ARM::LDR_POST_REG || MI->getOpcode() == ARM::t2LDR_POST) && isCalleeSavedRegister(MI->getOperand(0).getReg(), CSRegs) && MI->getOperand(1).getReg() == ARM::SP) @@ -590,7 +591,7 @@ void ARMFrameLowering::emitPushInst(MachineBasicBlock &MBB, .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) { + 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 @@ -665,7 +666,7 @@ void ARMFrameLowering::emitPopInst(MachineBasicBlock &MBB, .addReg(ARM::SP); // ARM mode needs an extra reg0 here due to addrmode2. Will go away once // that refactoring is complete (eventually). - if (LdrOpc == ARM::LDR_POST) { + if (LdrOpc == ARM::LDR_POST_REG || LdrOpc == ARM::LDR_POST_IMM) { MIB.addReg(0); MIB.addImm(ARM_AM::getAM2Opc(ARM_AM::add, 4, ARM_AM::no_shift)); } else @@ -687,7 +688,7 @@ bool ARMFrameLowering::spillCalleeSavedRegisters(MachineBasicBlock &MBB, ARMFunctionInfo *AFI = MF.getInfo(); unsigned PushOpc = AFI->isThumbFunction() ? ARM::t2STMDB_UPD : ARM::STMDB_UPD; - unsigned PushOneOpc = AFI->isThumbFunction() ? ARM::t2STR_PRE : ARM::STR_PRE; + unsigned PushOneOpc = AFI->isThumbFunction() ? ARM::t2STR_PRE : ARM::STR_PRE_IMM; unsigned FltOpc = ARM::VSTMDDB_UPD; emitPushInst(MBB, MI, CSI, PushOpc, PushOneOpc, false, &isARMArea1Register, MachineInstr::FrameSetup); @@ -711,7 +712,7 @@ bool ARMFrameLowering::restoreCalleeSavedRegisters(MachineBasicBlock &MBB, bool isVarArg = AFI->getVarArgsRegSaveSize() > 0; unsigned PopOpc = AFI->isThumbFunction() ? ARM::t2LDMIA_UPD : ARM::LDMIA_UPD; - unsigned LdrOpc = AFI->isThumbFunction() ? ARM::t2LDR_POST : ARM::LDR_POST; + unsigned LdrOpc = AFI->isThumbFunction() ? ARM::t2LDR_POST : ARM::LDR_POST_IMM; unsigned FltOpc = ARM::VLDMDIA_UPD; emitPopInst(MBB, MI, CSI, FltOpc, 0, isVarArg, true, &isARMArea3Register); emitPopInst(MBB, MI, CSI, PopOpc, LdrOpc, isVarArg, false, diff --git a/lib/Target/ARM/ARMISelDAGToDAG.cpp b/lib/Target/ARM/ARMISelDAGToDAG.cpp index adc49c6a508..928e2efa72f 100644 --- a/lib/Target/ARM/ARMISelDAGToDAG.cpp +++ b/lib/Target/ARM/ARMISelDAGToDAG.cpp @@ -129,7 +129,9 @@ public: return true; } - bool SelectAddrMode2Offset(SDNode *Op, SDValue N, + bool SelectAddrMode2OffsetReg(SDNode *Op, SDValue N, + SDValue &Offset, SDValue &Opc); + bool SelectAddrMode2OffsetImm(SDNode *Op, SDValue N, SDValue &Offset, SDValue &Opc); bool SelectAddrMode3(SDValue N, SDValue &Base, SDValue &Offset, SDValue &Opc); @@ -714,7 +716,7 @@ AddrMode2Type ARMDAGToDAGISel::SelectAddrMode2Worker(SDValue N, return AM2_SHOP; } -bool ARMDAGToDAGISel::SelectAddrMode2Offset(SDNode *Op, SDValue N, +bool ARMDAGToDAGISel::SelectAddrMode2OffsetReg(SDNode *Op, SDValue N, SDValue &Offset, SDValue &Opc) { unsigned Opcode = Op->getOpcode(); ISD::MemIndexedMode AM = (Opcode == ISD::LOAD) @@ -723,13 +725,8 @@ bool ARMDAGToDAGISel::SelectAddrMode2Offset(SDNode *Op, SDValue N, ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC) ? ARM_AM::add : ARM_AM::sub; int Val; - if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val)) { // 12 bits. - Offset = CurDAG->getRegister(0, MVT::i32); - Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, Val, - ARM_AM::no_shift), - MVT::i32); - return true; - } + if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val)) + return false; Offset = N; ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode()); @@ -755,6 +752,28 @@ bool ARMDAGToDAGISel::SelectAddrMode2Offset(SDNode *Op, SDValue N, return true; } +bool ARMDAGToDAGISel::SelectAddrMode2OffsetImm(SDNode *Op, SDValue N, + SDValue &Offset, SDValue &Opc) { + unsigned Opcode = Op->getOpcode(); + ISD::MemIndexedMode AM = (Opcode == ISD::LOAD) + ? cast(Op)->getAddressingMode() + : cast(Op)->getAddressingMode(); + ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC) + ? ARM_AM::add : ARM_AM::sub; + int Val; + if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val)) { // 12 bits. + Offset = CurDAG->getRegister(0, MVT::i32); + Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, Val, + ARM_AM::no_shift), + MVT::i32); + return true; + } + + return false; +} + + + bool ARMDAGToDAGISel::SelectAddrMode3(SDValue N, SDValue &Base, SDValue &Offset, @@ -1298,9 +1317,14 @@ SDNode *ARMDAGToDAGISel::SelectARMIndexedLoad(SDNode *N) { unsigned Opcode = 0; bool Match = false; if (LoadedVT == MVT::i32 && - SelectAddrMode2Offset(N, LD->getOffset(), Offset, AMOpc)) { - Opcode = isPre ? ARM::LDR_PRE : ARM::LDR_POST; + SelectAddrMode2OffsetImm(N, LD->getOffset(), Offset, AMOpc)) { + Opcode = isPre ? ARM::LDR_PRE : ARM::LDR_POST_IMM; + Match = true; + } else if (LoadedVT == MVT::i32 && + SelectAddrMode2OffsetReg(N, LD->getOffset(), Offset, AMOpc)) { + Opcode = isPre ? ARM::LDR_PRE : ARM::LDR_POST_REG; Match = true; + } else if (LoadedVT == MVT::i16 && SelectAddrMode3Offset(N, LD->getOffset(), Offset, AMOpc)) { Match = true; @@ -1314,9 +1338,12 @@ SDNode *ARMDAGToDAGISel::SelectARMIndexedLoad(SDNode *N) { Opcode = isPre ? ARM::LDRSB_PRE : ARM::LDRSB_POST; } } else { - if (SelectAddrMode2Offset(N, LD->getOffset(), Offset, AMOpc)) { + if (SelectAddrMode2OffsetImm(N, LD->getOffset(), Offset, AMOpc)) { + Match = true; + Opcode = isPre ? ARM::LDRB_PRE : ARM::LDRB_POST_IMM; + } else if (SelectAddrMode2OffsetReg(N, LD->getOffset(), Offset, AMOpc)) { Match = true; - Opcode = isPre ? ARM::LDRB_PRE : ARM::LDRB_POST; + Opcode = isPre ? ARM::LDRB_PRE : ARM::LDRB_POST_REG; } } } diff --git a/lib/Target/ARM/ARMInstrFormats.td b/lib/Target/ARM/ARMInstrFormats.td index 23c306de772..769fecf6d87 100644 --- a/lib/Target/ARM/ARMInstrFormats.td +++ b/lib/Target/ARM/ARMInstrFormats.td @@ -507,22 +507,41 @@ class AI2ldstidx pattern> + : AI2ldstidx<0, isByte, isPre, oops, iops, im, f, itin, opc, asm, cstr, + pattern> { + // AM2 store w/ two operands: (GPR, am2offset) + // {12} isAdd + // {11-0} imm12/Rm + bits<14> offset; + bits<4> Rn; + let Inst{25} = 1; + let Inst{23} = offset{12}; + let Inst{19-16} = Rn; + let Inst{11-5} = offset{11-5}; + let Inst{4} = 0; + let Inst{3-0} = offset{3-0}; +} + +class AI2stridx_imm pattern> : AI2ldstidx<0, isByte, isPre, oops, iops, im, f, itin, opc, asm, cstr, pattern> { // AM2 store w/ two operands: (GPR, am2offset) - // {13} 1 == Rm, 0 == imm12 // {12} isAdd // {11-0} imm12/Rm bits<14> offset; bits<4> Rn; - let Inst{25} = offset{13}; + let Inst{25} = 0; let Inst{23} = offset{12}; let Inst{19-16} = Rn; let Inst{11-0} = offset{11-0}; } + + // FIXME: Merge with the above class when addrmode2 gets used for STR, STRB // but for now use this class for STRT and STRBT. class AI2stridxT, ImmLeaf= 0 && Imm < 32; }]> { let EncoderMethod = "getImmMinusOneOpValue"; + let DecoderMethod = "DecodeImmMinusOneOperand"; } // imm0_65535_expr - For movt/movw - 16-bit immediate that can also reference @@ -606,14 +607,23 @@ def addrmode2 : Operand, let MIOperandInfo = (ops GPR:$base, GPR:$offsreg, i32imm:$offsimm); } -def am2offset : Operand, - ComplexPattern, + ComplexPattern { let EncoderMethod = "getAddrMode2OffsetOpValue"; let PrintMethod = "printAddrMode2OffsetOperand"; let MIOperandInfo = (ops GPR, i32imm); } +def am2offset_imm : Operand, + ComplexPattern { + let EncoderMethod = "getAddrMode2OffsetOpValue"; + let PrintMethod = "printAddrMode2OffsetOperand"; + let MIOperandInfo = (ops GPR, i32imm); +} + + // addrmode3 := reg +/- reg // addrmode3 := reg +/- imm8 // @@ -1845,7 +1855,7 @@ multiclass AI2_ldridx { (ins addrmode2:$addr), IndexModePre, LdFrm, itin, opc, "\t$Rt, $addr!", "$addr.base = $Rn_wb", []> { // {17-14} Rn - // {13} 1 == Rm, 0 == imm12 + // {13} reg vs. imm // {12} isAdd // {11-0} imm12/Rm bits<18> addr; @@ -1855,19 +1865,35 @@ multiclass AI2_ldridx { let Inst{11-0} = addr{11-0}; let AsmMatchConverter = "cvtLdWriteBackRegAddrMode2"; } - def _POST : AI2ldstidx<1, isByte, 0, (outs GPR:$Rt, GPR:$Rn_wb), - (ins GPR:$Rn, am2offset:$offset), + + def _POST_REG : AI2ldstidx<1, isByte, 0, (outs GPR:$Rt, GPR:$Rn_wb), + (ins GPR:$Rn, am2offset_reg:$offset), + IndexModePost, LdFrm, itin, + opc, "\t$Rt, [$Rn], $offset", "$Rn = $Rn_wb", []> { + // {12} isAdd + // {11-0} imm12/Rm + bits<14> offset; + bits<4> Rn; + let Inst{25} = 1; + let Inst{23} = offset{12}; + let Inst{19-16} = Rn; + let Inst{11-0} = offset{11-0}; + let DecoderMethod = "DecodeAddrMode2IdxInstruction"; + } + + def _POST_IMM : AI2ldstidx<1, isByte, 0, (outs GPR:$Rt, GPR:$Rn_wb), + (ins GPR:$Rn, am2offset_imm:$offset), IndexModePost, LdFrm, itin, opc, "\t$Rt, [$Rn], $offset", "$Rn = $Rn_wb", []> { - // {13} 1 == Rm, 0 == imm12 // {12} isAdd // {11-0} imm12/Rm bits<14> offset; bits<4> Rn; - let Inst{25} = offset{13}; + let Inst{25} = 0; let Inst{23} = offset{12}; let Inst{19-16} = Rn; let Inst{11-0} = offset{11-0}; + let DecoderMethod = "DecodeAddrMode2IdxInstruction"; } } @@ -1998,36 +2024,69 @@ def STRD : AI3str<0b1111, (outs), (ins GPR:$Rt, GPR:$src2, addrmode3:$addr), "strd", "\t$Rt, $src2, $addr", []>, Requires<[IsARM, HasV5TE]>; // Indexed stores -def STR_PRE : AI2stridx<0, 1, (outs GPR:$Rn_wb), - (ins GPR:$Rt, GPR:$Rn, am2offset:$offset), +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:$offset))]>; + (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))]>; + + -def STR_POST : AI2stridx<0, 0, (outs GPR:$Rn_wb), - (ins GPR:$Rt, GPR:$Rn, am2offset:$offset), +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:$offset))]>; + (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))]>; -def STRB_PRE : AI2stridx<1, 1, (outs GPR:$Rn_wb), - (ins GPR:$Rt, GPR:$Rn, am2offset:$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:$offset))]>; -def STRB_POST: AI2stridx<1, 0, (outs GPR:$Rn_wb), - (ins GPR:$Rt, GPR:$Rn, am2offset:$offset), + 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:$offset))]>; + 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))]>; + 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 06ee449692a..ee0028c2ea6 100644 --- a/lib/Target/ARM/ARMLoadStoreOptimizer.cpp +++ b/lib/Target/ARM/ARMLoadStoreOptimizer.cpp @@ -766,7 +766,7 @@ static unsigned getPreIndexedLoadStoreOpcode(unsigned Opc, case ARM::LDRi12: return ARM::LDR_PRE; case ARM::STRi12: - return ARM::STR_PRE; + return ARM::STR_PRE_IMM; case ARM::VLDRS: return Mode == ARM_AM::add ? ARM::VLDMSIA_UPD : ARM::VLDMSDB_UPD; case ARM::VLDRD: @@ -790,9 +790,9 @@ static unsigned getPostIndexedLoadStoreOpcode(unsigned Opc, ARM_AM::AddrOpc Mode) { switch (Opc) { case ARM::LDRi12: - return ARM::LDR_POST; + return ARM::LDR_POST_IMM; case ARM::STRi12: - return ARM::STR_POST; + return ARM::STR_POST_IMM; case ARM::VLDRS: return Mode == ARM_AM::add ? ARM::VLDMSIA_UPD : ARM::VLDMSDB_UPD; case ARM::VLDRD: diff --git a/utils/TableGen/EDEmitter.cpp b/utils/TableGen/EDEmitter.cpp index 83d93cb83f2..db1b67f4513 100644 --- a/utils/TableGen/EDEmitter.cpp +++ b/utils/TableGen/EDEmitter.cpp @@ -639,7 +639,8 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type, MISC("addrmode_imm12", "kOperandTypeAddrModeImm12"); // R, I MISC("ldst_so_reg", "kOperandTypeLdStSOReg"); // R, R, I MISC("addrmode2", "kOperandTypeARMAddrMode2"); // R, R, I - MISC("am2offset", "kOperandTypeARMAddrMode2Offset"); // R, I + MISC("am2offset_reg", "kOperandTypeARMAddrMode2Offset"); // R, I + MISC("am2offset_imm", "kOperandTypeARMAddrMode2Offset"); // R, I MISC("addrmode3", "kOperandTypeARMAddrMode3"); // R, R, I MISC("am3offset", "kOperandTypeARMAddrMode3Offset"); // R, I MISC("ldstm_mode", "kOperandTypeARMLdStmMode"); // I