Index: lib/Target/ARM/ARMAsmPrinter.cpp =================================================================== --- lib/Target/ARM/ARMAsmPrinter.cpp +++ lib/Target/ARM/ARMAsmPrinter.cpp @@ -1542,7 +1542,6 @@ EmitJumpTableTBInst(MI, MI->getOpcode() == ARM::JUMPTABLE_TBB ? 1 : 2); return; case ARM::t2BR_JT: { - // Lower and emit the instruction itself, then the jump table following it. EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tMOVr) .addReg(ARM::PC) .addReg(MI->getOperand(0).getReg()) @@ -1651,7 +1650,6 @@ } case ARM::tBR_JTr: case ARM::BR_JTr: { - // Lower and emit the instruction itself, then the jump table following it. // mov pc, target MCInst TmpInst; unsigned Opc = MI->getOpcode() == ARM::BR_JTr ? @@ -1668,23 +1666,27 @@ EmitToStreamer(*OutStreamer, TmpInst); return; } - case ARM::BR_JTm: { - // Lower and emit the instruction itself, then the jump table following it. + case ARM::BR_JTm_i12: { // ldr pc, target MCInst TmpInst; - if (MI->getOperand(1).getReg() == 0) { - // literal offset - TmpInst.setOpcode(ARM::LDRi12); - TmpInst.addOperand(MCOperand::createReg(ARM::PC)); - TmpInst.addOperand(MCOperand::createReg(MI->getOperand(0).getReg())); - TmpInst.addOperand(MCOperand::createImm(MI->getOperand(2).getImm())); - } else { - TmpInst.setOpcode(ARM::LDRrs); - TmpInst.addOperand(MCOperand::createReg(ARM::PC)); - TmpInst.addOperand(MCOperand::createReg(MI->getOperand(0).getReg())); - TmpInst.addOperand(MCOperand::createReg(MI->getOperand(1).getReg())); - TmpInst.addOperand(MCOperand::createImm(MI->getOperand(2).getImm())); - } + TmpInst.setOpcode(ARM::LDRi12); + TmpInst.addOperand(MCOperand::createReg(ARM::PC)); + TmpInst.addOperand(MCOperand::createReg(MI->getOperand(0).getReg())); + TmpInst.addOperand(MCOperand::createImm(MI->getOperand(2).getImm())); + // Add predicate operands. + TmpInst.addOperand(MCOperand::createImm(ARMCC::AL)); + TmpInst.addOperand(MCOperand::createReg(0)); + EmitToStreamer(*OutStreamer, TmpInst); + return; + } + case ARM::BR_JTm_rs: { + // ldr pc, target + MCInst TmpInst; + TmpInst.setOpcode(ARM::LDRrs); + TmpInst.addOperand(MCOperand::createReg(ARM::PC)); + TmpInst.addOperand(MCOperand::createReg(MI->getOperand(0).getReg())); + TmpInst.addOperand(MCOperand::createReg(MI->getOperand(1).getReg())); + TmpInst.addOperand(MCOperand::createImm(MI->getOperand(2).getImm())); // Add predicate operands. TmpInst.addOperand(MCOperand::createImm(ARMCC::AL)); TmpInst.addOperand(MCOperand::createReg(0)); @@ -1692,7 +1694,6 @@ return; } case ARM::BR_JTadd: { - // Lower and emit the instruction itself, then the jump table following it. // add pc, target, idx EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::ADDrr) .addReg(ARM::PC) Index: lib/Target/ARM/ARMBaseInstrInfo.h =================================================================== --- lib/Target/ARM/ARMBaseInstrInfo.h +++ lib/Target/ARM/ARMBaseInstrInfo.h @@ -468,10 +468,10 @@ return Opc == ARM::Bcc || Opc == ARM::tBcc || Opc == ARM::t2Bcc; } -static inline -bool isJumpTableBranchOpcode(int Opc) { - return Opc == ARM::BR_JTr || Opc == ARM::BR_JTm || Opc == ARM::BR_JTadd || - Opc == ARM::tBR_JTr || Opc == ARM::t2BR_JT; +static inline bool isJumpTableBranchOpcode(int Opc) { + return Opc == ARM::BR_JTr || Opc == ARM::BR_JTm_i12 || + Opc == ARM::BR_JTm_rs || Opc == ARM::BR_JTadd || Opc == ARM::tBR_JTr || + Opc == ARM::t2BR_JT; } static inline Index: lib/Target/ARM/ARMConstantIslandPass.cpp =================================================================== --- lib/Target/ARM/ARMConstantIslandPass.cpp +++ lib/Target/ARM/ARMConstantIslandPass.cpp @@ -564,7 +564,8 @@ case ARM::BR_JTadd: case ARM::BR_JTr: case ARM::tBR_JTr: - case ARM::BR_JTm: + case ARM::BR_JTm_i12: + case ARM::BR_JTm_rs: JTOpcode = ARM::JUMPTABLE_ADDRS; break; case ARM::t2BR_JT: Index: lib/Target/ARM/ARMISelDAGToDAG.cpp =================================================================== --- lib/Target/ARM/ARMISelDAGToDAG.cpp +++ lib/Target/ARM/ARMISelDAGToDAG.cpp @@ -50,11 +50,6 @@ /// namespace { -enum AddrMode2Type { - AM2_BASE, // Simple AM2 (+-imm12) - AM2_SHOP // Shifter-op AM2 -}; - class ARMDAGToDAGISel : public SelectionDAGISel { /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can /// make the right decision when generating code for different targets. @@ -105,26 +100,6 @@ bool SelectAddrModeImm12(SDValue N, SDValue &Base, SDValue &OffImm); bool SelectLdStSOReg(SDValue N, SDValue &Base, SDValue &Offset, SDValue &Opc); - AddrMode2Type SelectAddrMode2Worker(SDValue N, SDValue &Base, - SDValue &Offset, SDValue &Opc); - bool SelectAddrMode2Base(SDValue N, SDValue &Base, SDValue &Offset, - SDValue &Opc) { - return SelectAddrMode2Worker(N, Base, Offset, Opc) == AM2_BASE; - } - - bool SelectAddrMode2ShOp(SDValue N, SDValue &Base, SDValue &Offset, - SDValue &Opc) { - return SelectAddrMode2Worker(N, Base, Offset, Opc) == AM2_SHOP; - } - - bool SelectAddrMode2(SDValue N, SDValue &Base, SDValue &Offset, - SDValue &Opc) { - SelectAddrMode2Worker(N, Base, Offset, Opc); -// return SelectAddrMode2ShOp(N, Base, Offset, Opc); - // This always matches one way or another. - return true; - } - bool SelectCMOVPred(SDValue N, SDValue &Pred, SDValue &Reg) { const ConstantSDNode *CN = cast(N); Pred = CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(N), MVT::i32); @@ -754,148 +729,6 @@ return true; } - -//----- - -AddrMode2Type ARMDAGToDAGISel::SelectAddrMode2Worker(SDValue N, - SDValue &Base, - SDValue &Offset, - SDValue &Opc) { - if (N.getOpcode() == ISD::MUL && - (!(Subtarget->isLikeA9() || Subtarget->isSwift()) || N.hasOneUse())) { - if (ConstantSDNode *RHS = dyn_cast(N.getOperand(1))) { - // X * [3,5,9] -> X + X * [2,4,8] etc. - int RHSC = (int)RHS->getZExtValue(); - if (RHSC & 1) { - RHSC = RHSC & ~1; - ARM_AM::AddrOpc AddSub = ARM_AM::add; - if (RHSC < 0) { - AddSub = ARM_AM::sub; - RHSC = - RHSC; - } - if (isPowerOf2_32(RHSC)) { - unsigned ShAmt = Log2_32(RHSC); - Base = Offset = N.getOperand(0); - Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, - ARM_AM::lsl), - SDLoc(N), MVT::i32); - return AM2_SHOP; - } - } - } - } - - if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB && - // ISD::OR that is equivalent to an ADD. - !CurDAG->isBaseWithConstantOffset(N)) { - Base = N; - if (N.getOpcode() == ISD::FrameIndex) { - int FI = cast(N)->getIndex(); - Base = CurDAG->getTargetFrameIndex( - FI, TLI->getPointerTy(CurDAG->getDataLayout())); - } else if (N.getOpcode() == ARMISD::Wrapper && - N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress && - N.getOperand(0).getOpcode() != ISD::TargetExternalSymbol && - N.getOperand(0).getOpcode() != ISD::TargetGlobalTLSAddress) { - Base = N.getOperand(0); - } - Offset = CurDAG->getRegister(0, MVT::i32); - Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(ARM_AM::add, 0, - ARM_AM::no_shift), - SDLoc(N), MVT::i32); - return AM2_BASE; - } - - // Match simple R +/- imm12 operands. - if (N.getOpcode() != ISD::SUB) { - int RHSC; - if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1, - -0x1000+1, 0x1000, RHSC)) { // 12 bits. - Base = N.getOperand(0); - if (Base.getOpcode() == ISD::FrameIndex) { - int FI = cast(Base)->getIndex(); - Base = CurDAG->getTargetFrameIndex( - FI, TLI->getPointerTy(CurDAG->getDataLayout())); - } - Offset = CurDAG->getRegister(0, MVT::i32); - - ARM_AM::AddrOpc AddSub = ARM_AM::add; - if (RHSC < 0) { - AddSub = ARM_AM::sub; - RHSC = - RHSC; - } - Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, RHSC, - ARM_AM::no_shift), - SDLoc(N), MVT::i32); - return AM2_BASE; - } - } - - if ((Subtarget->isLikeA9() || Subtarget->isSwift()) && !N.hasOneUse()) { - // Compute R +/- (R << N) and reuse it. - Base = N; - Offset = CurDAG->getRegister(0, MVT::i32); - Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(ARM_AM::add, 0, - ARM_AM::no_shift), - SDLoc(N), MVT::i32); - return AM2_BASE; - } - - // Otherwise this is R +/- [possibly shifted] R. - ARM_AM::AddrOpc AddSub = N.getOpcode() != ISD::SUB ? ARM_AM::add:ARM_AM::sub; - ARM_AM::ShiftOpc ShOpcVal = - ARM_AM::getShiftOpcForNode(N.getOperand(1).getOpcode()); - unsigned ShAmt = 0; - - Base = N.getOperand(0); - Offset = N.getOperand(1); - - if (ShOpcVal != ARM_AM::no_shift) { - // Check to see if the RHS of the shift is a constant, if not, we can't fold - // it. - if (ConstantSDNode *Sh = - dyn_cast(N.getOperand(1).getOperand(1))) { - ShAmt = Sh->getZExtValue(); - if (isShifterOpProfitable(Offset, ShOpcVal, ShAmt)) - Offset = N.getOperand(1).getOperand(0); - else { - ShAmt = 0; - ShOpcVal = ARM_AM::no_shift; - } - } else { - ShOpcVal = ARM_AM::no_shift; - } - } - - // Try matching (R shl C) + (R). - if (N.getOpcode() != ISD::SUB && ShOpcVal == ARM_AM::no_shift && - !(Subtarget->isLikeA9() || Subtarget->isSwift() || - N.getOperand(0).hasOneUse())) { - ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0).getOpcode()); - if (ShOpcVal != ARM_AM::no_shift) { - // Check to see if the RHS of the shift is a constant, if not, we can't - // fold it. - if (ConstantSDNode *Sh = - dyn_cast(N.getOperand(0).getOperand(1))) { - ShAmt = Sh->getZExtValue(); - if (isShifterOpProfitable(N.getOperand(0), ShOpcVal, ShAmt)) { - Offset = N.getOperand(0).getOperand(0); - Base = N.getOperand(1); - } else { - ShAmt = 0; - ShOpcVal = ARM_AM::no_shift; - } - } else { - ShOpcVal = ARM_AM::no_shift; - } - } - } - - Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal), - SDLoc(N), MVT::i32); - return AM2_SHOP; -} - bool ARMDAGToDAGISel::SelectAddrMode2OffsetReg(SDNode *Op, SDValue N, SDValue &Offset, SDValue &Opc) { unsigned Opcode = Op->getOpcode(); Index: lib/Target/ARM/ARMInstrInfo.td =================================================================== --- lib/Target/ARM/ARMInstrInfo.td +++ lib/Target/ARM/ARMInstrInfo.td @@ -971,21 +971,6 @@ let MIOperandInfo = (ops GPRnopc, i32imm); } - -// addrmode2 := reg +/- imm12 -// := reg +/- reg shop imm -// -// FIXME: addrmode2 should be refactored the rest of the way to always -// use explicit imm vs. reg versions above (addrmode_imm12 and ldst_so_reg). -def AddrMode2AsmOperand : AsmOperandClass { let Name = "AddrMode2"; } -def addrmode2 : MemOperand, - ComplexPattern { - let EncoderMethod = "getAddrMode2OpValue"; - let PrintMethod = "printAddrMode2Operand"; - let ParserMatchClass = AddrMode2AsmOperand; - let MIOperandInfo = (ops GPR:$base, GPR:$offsreg, i32imm:$offsimm); -} - def PostIdxRegShiftedAsmOperand : AsmOperandClass { let Name = "PostIdxRegShifted"; let ParserMethod = "parsePostIdxReg"; @@ -2380,12 +2365,15 @@ 0, IIC_Br, [(ARMbrjt GPR:$target, tjumptable:$jt)]>, Sched<[WriteBr]>; - // FIXME: This shouldn't use the generic "addrmode2," but rather be split - // into i12 and rs suffixed versions. - def BR_JTm : ARMPseudoInst<(outs), - (ins addrmode2:$target, i32imm:$jt), + def BR_JTm_i12 : ARMPseudoInst<(outs), + (ins addrmode_imm12:$target, i32imm:$jt), + 0, IIC_Br, + [(ARMbrjt (i32 (load addrmode_imm12:$target)), + tjumptable:$jt)]>, Sched<[WriteBrTbl]>; + def BR_JTm_rs : ARMPseudoInst<(outs), + (ins ldst_so_reg:$target, i32imm:$jt), 0, IIC_Br, - [(ARMbrjt (i32 (load addrmode2:$target)), + [(ARMbrjt (i32 (load ldst_so_reg:$target)), tjumptable:$jt)]>, Sched<[WriteBrTbl]>; def BR_JTadd : ARMPseudoInst<(outs), (ins GPR:$target, GPR:$idx, i32imm:$jt),