Add specializations of addrmode2 that allow differentiating those forms

which require the use of the shifter-operand. This will be used to split
the ldr/str instructions such that those versions needing the shifter operand
can get a different scheduling itenerary, as in some cases, the use of the
shifter can cause different scheduling than the simpler forms.

llvm-svn: 115066
This commit is contained in:
Jim Grosbach 2010-09-29 19:03:54 +00:00
parent c0ba019a19
commit 0860520527
2 changed files with 49 additions and 11 deletions

View File

@ -46,6 +46,12 @@ DisableShifterOp("disable-shifter-op", cl::Hidden,
/// instructions for SelectionDAG operations. /// instructions for SelectionDAG operations.
/// ///
namespace { namespace {
enum AddrMode2Type {
AM2_BASE, // Simple AM2 (+-imm12)
AM2_SHOP // Shifter-op AM2
};
class ARMDAGToDAGISel : public SelectionDAGISel { class ARMDAGToDAGISel : public SelectionDAGISel {
ARMBaseTargetMachine &TM; ARMBaseTargetMachine &TM;
@ -74,8 +80,25 @@ public:
bool SelectShifterOperandReg(SDValue N, SDValue &A, bool SelectShifterOperandReg(SDValue N, SDValue &A,
SDValue &B, SDValue &C); SDValue &B, SDValue &C);
bool SelectAddrMode2(SDValue N, SDValue &Base, AddrMode2Type SelectAddrMode2Worker(SDValue N, SDValue &Base,
SDValue &Offset, SDValue &Opc); 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);
// This always matches one way or another.
return true;
}
bool SelectAddrMode2Offset(SDNode *Op, SDValue N, bool SelectAddrMode2Offset(SDNode *Op, SDValue N,
SDValue &Offset, SDValue &Opc); SDValue &Offset, SDValue &Opc);
bool SelectAddrMode3(SDValue N, SDValue &Base, bool SelectAddrMode3(SDValue N, SDValue &Base,
@ -245,8 +268,9 @@ bool ARMDAGToDAGISel::SelectShifterOperandReg(SDValue N,
return true; return true;
} }
bool ARMDAGToDAGISel::SelectAddrMode2(SDValue N, AddrMode2Type ARMDAGToDAGISel::SelectAddrMode2Worker(SDValue N,
SDValue &Base, SDValue &Offset, SDValue &Base,
SDValue &Offset,
SDValue &Opc) { SDValue &Opc) {
if (N.getOpcode() == ISD::MUL) { if (N.getOpcode() == ISD::MUL) {
if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
@ -265,7 +289,7 @@ bool ARMDAGToDAGISel::SelectAddrMode2(SDValue N,
Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt,
ARM_AM::lsl), ARM_AM::lsl),
MVT::i32); MVT::i32);
return true; return AM2_SHOP;
} }
} }
} }
@ -285,7 +309,7 @@ bool ARMDAGToDAGISel::SelectAddrMode2(SDValue N,
Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(ARM_AM::add, 0, Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(ARM_AM::add, 0,
ARM_AM::no_shift), ARM_AM::no_shift),
MVT::i32); MVT::i32);
return true; return AM2_BASE;
} }
// Match simple R +/- imm12 operands. // Match simple R +/- imm12 operands.
@ -309,7 +333,7 @@ bool ARMDAGToDAGISel::SelectAddrMode2(SDValue N,
Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, RHSC, Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, RHSC,
ARM_AM::no_shift), ARM_AM::no_shift),
MVT::i32); MVT::i32);
return true; return AM2_BASE;
} }
} }
} }
@ -353,7 +377,7 @@ bool ARMDAGToDAGISel::SelectAddrMode2(SDValue N,
Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal), Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal),
MVT::i32); MVT::i32);
return true; return AM2_SHOP;
} }
bool ARMDAGToDAGISel::SelectAddrMode2Offset(SDNode *Op, SDValue N, bool ARMDAGToDAGISel::SelectAddrMode2Offset(SDNode *Op, SDValue N,

View File

@ -369,8 +369,22 @@ def imm0_31 : Operand<i32>, PatLeaf<(imm), [{
// Define ARM specific addressing modes. // Define ARM specific addressing modes.
// addrmode2 := reg +/- reg shop imm // addrmode2base := reg +/- imm12
// addrmode2 := reg +/- imm12 //
def addrmode2base : Operand<i32>,
ComplexPattern<i32, 3, "SelectAddrMode2Base", []> {
let PrintMethod = "printAddrMode2Operand";
let MIOperandInfo = (ops GPR:$base, GPR:$offsreg, i32imm:$offsimm);
}
// addrmode2shop := reg +/- reg shop imm
//
def addrmode2shop : Operand<i32>,
ComplexPattern<i32, 3, "SelectAddrMode2ShOp", []> {
let PrintMethod = "printAddrMode2Operand";
let MIOperandInfo = (ops GPR:$base, GPR:$offsreg, i32imm:$offsimm);
}
// addrmode2 := (addrmode2base || addrmode2shop)
// //
def addrmode2 : Operand<i32>, def addrmode2 : Operand<i32>,
ComplexPattern<i32, 3, "SelectAddrMode2", []> { ComplexPattern<i32, 3, "SelectAddrMode2", []> {