forked from OSchip/llvm-project
[ARM] Split Arm jump table branch into i12 and rs suffixed versions
This is a refactoring/cleanup of Arm `addrmode2` operand class. The patch removes it completely. Differential Revision: https://reviews.llvm.org/D39832 llvm-svn: 318291
This commit is contained in:
parent
bed400957b
commit
4a91fb93db
|
@ -1542,7 +1542,6 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) {
|
|||
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 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) {
|
|||
}
|
||||
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 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) {
|
|||
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 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) {
|
|||
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)
|
||||
|
|
|
@ -468,10 +468,10 @@ bool isCondBranchOpcode(int Opc) {
|
|||
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
|
||||
|
|
|
@ -564,7 +564,8 @@ void ARMConstantIslands::doInitialJumpTablePlacement(
|
|||
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:
|
||||
|
|
|
@ -50,11 +50,6 @@ DisableShifterOp("disable-shifter-op", cl::Hidden,
|
|||
///
|
||||
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 @@ public:
|
|||
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<ConstantSDNode>(N);
|
||||
Pred = CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(N), MVT::i32);
|
||||
|
@ -754,148 +729,6 @@ bool ARMDAGToDAGISel::SelectLdStSOReg(SDValue N, SDValue &Base, SDValue &Offset,
|
|||
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<ConstantSDNode>(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<FrameIndexSDNode>(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<FrameIndexSDNode>(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<ConstantSDNode>(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<ConstantSDNode>(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();
|
||||
|
|
|
@ -971,21 +971,6 @@ def postidx_reg : MemOperand {
|
|||
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<i32, 3, "SelectAddrMode2", []> {
|
||||
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 @@ let isBranch = 1, isTerminator = 1 in {
|
|||
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 addrmode2:$target)),
|
||||
[(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 ldst_so_reg:$target)),
|
||||
tjumptable:$jt)]>, Sched<[WriteBrTbl]>;
|
||||
def BR_JTadd : ARMPseudoInst<(outs),
|
||||
(ins GPR:$target, GPR:$idx, i32imm:$jt),
|
||||
|
|
Loading…
Reference in New Issue