//===----------------------------------------------------------------------===//
#include "ARM.h"
+#include "ARMAddressingModes.h"
+#include "ARMConstantPoolValue.h"
#include "ARMISelLowering.h"
#include "ARMTargetMachine.h"
-#include "ARMAddressingModes.h"
#include "llvm/CallingConv.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
///
namespace {
class ARMDAGToDAGISel : public SelectionDAGISel {
- ARMTargetLowering Lowering;
+ ARMTargetMachine &TM;
/// Subtarget - Keep a pointer to the ARMSubtarget around so that we can
/// make the right decision when generating code for different targets.
const ARMSubtarget *Subtarget;
public:
- explicit ARMDAGToDAGISel(ARMTargetMachine &TM)
- : SelectionDAGISel(Lowering), Lowering(TM),
+ explicit ARMDAGToDAGISel(ARMTargetMachine &tm)
+ : SelectionDAGISel(tm), TM(tm),
Subtarget(&TM.getSubtarget<ARMSubtarget>()) {
}
void ARMDAGToDAGISel::InstructionSelect() {
DEBUG(BB->dump());
- SelectRoot();
+ SelectRoot(*CurDAG);
CurDAG->RemoveDeadNodes();
}
if (N.getOpcode() == ISD::MUL) {
if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
// X * [3,5,9] -> X + X * [2,4,8] etc.
- int RHSC = (int)RHS->getValue();
+ int RHSC = (int)RHS->getZExtValue();
if (RHSC & 1) {
RHSC = RHSC & ~1;
ARM_AM::AddrOpc AddSub = ARM_AM::add;
// Match simple R +/- imm12 operands.
if (N.getOpcode() == ISD::ADD)
if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
- int RHSC = (int)RHS->getValue();
+ int RHSC = (int)RHS->getZExtValue();
if ((RHSC >= 0 && RHSC < 0x1000) ||
(RHSC < 0 && RHSC > -0x1000)) { // 12 bits.
Base = N.getOperand(0);
// it.
if (ConstantSDNode *Sh =
dyn_cast<ConstantSDNode>(N.getOperand(1).getOperand(1))) {
- ShAmt = Sh->getValue();
+ ShAmt = Sh->getZExtValue();
Offset = N.getOperand(1).getOperand(0);
} else {
ShOpcVal = ARM_AM::no_shift;
// fold it.
if (ConstantSDNode *Sh =
dyn_cast<ConstantSDNode>(N.getOperand(0).getOperand(1))) {
- ShAmt = Sh->getValue();
+ ShAmt = Sh->getZExtValue();
Offset = N.getOperand(0).getOperand(0);
Base = N.getOperand(1);
} else {
ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
? ARM_AM::add : ARM_AM::sub;
if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N)) {
- int Val = (int)C->getValue();
+ int Val = (int)C->getZExtValue();
if (Val >= 0 && Val < 0x1000) { // 12 bits.
Offset = CurDAG->getRegister(0, MVT::i32);
Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, Val,
// 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))) {
- ShAmt = Sh->getValue();
+ ShAmt = Sh->getZExtValue();
Offset = N.getOperand(0);
} else {
ShOpcVal = ARM_AM::no_shift;
// If the RHS is +/- imm8, fold into addr mode.
if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
- int RHSC = (int)RHS->getValue();
+ int RHSC = (int)RHS->getZExtValue();
if ((RHSC >= 0 && RHSC < 256) ||
(RHSC < 0 && RHSC > -256)) { // note -256 itself isn't allowed.
Base = N.getOperand(0);
ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
? ARM_AM::add : ARM_AM::sub;
if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N)) {
- int Val = (int)C->getValue();
+ int Val = (int)C->getZExtValue();
if (Val >= 0 && Val < 256) {
Offset = CurDAG->getRegister(0, MVT::i32);
Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, Val), MVT::i32);
// If the RHS is +/- imm8, fold into addr mode.
if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
- int RHSC = (int)RHS->getValue();
+ int RHSC = (int)RHS->getZExtValue();
if ((RHSC & 3) == 0) { // The constant is implicitly multiplied by 4.
RHSC >>= 2;
if ((RHSC >= 0 && RHSC < 256) ||
if (N.getOpcode() == ARMISD::PIC_ADD && N.hasOneUse()) {
Offset = N.getOperand(0);
SDValue N1 = N.getOperand(1);
- Label = CurDAG->getTargetConstant(cast<ConstantSDNode>(N1)->getValue(),
+ Label = CurDAG->getTargetConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
MVT::i32);
return true;
}
bool ARMDAGToDAGISel::SelectThumbAddrModeRR(SDValue Op, SDValue N,
SDValue &Base, SDValue &Offset){
+ // FIXME dl should come from the parent load or store, not the address
+ DebugLoc dl = Op.getDebugLoc();
if (N.getOpcode() != ISD::ADD) {
Base = N;
- // We must materialize a zero in a reg! Returning an constant here won't
- // work since its node is -1 so it won't get added to the selection queue.
- // Explicitly issue a tMOVri8 node!
- Offset = SDValue(CurDAG->getTargetNode(ARM::tMOVi8, MVT::i32,
+ // We must materialize a zero in a reg! Returning a constant here
+ // wouldn't work without additional code to position the node within
+ // ISel's topological ordering in a place where ISel will process it
+ // normally. Instead, just explicitly issue a tMOVri8 node!
+ Offset = SDValue(CurDAG->getTargetNode(ARM::tMOVi8, dl, MVT::i32,
CurDAG->getTargetConstant(0, MVT::i32)), 0);
return true;
}
// If the RHS is + imm5 * scale, fold into addr mode.
if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
- int RHSC = (int)RHS->getValue();
+ int RHSC = (int)RHS->getZExtValue();
if ((RHSC & (Scale-1)) == 0) { // The constant is implicitly multiplied.
RHSC /= Scale;
if (RHSC >= 0 && RHSC < 32) {
(LHSR && LHSR->getReg() == ARM::SP)) {
// If the RHS is + imm8 * scale, fold into addr mode.
if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
- int RHSC = (int)RHS->getValue();
+ int RHSC = (int)RHS->getZExtValue();
if ((RHSC & 3) == 0) { // The constant is implicitly multiplied.
RHSC >>= 2;
if (RHSC >= 0 && RHSC < 256) {
unsigned ShImmVal = 0;
if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
ShReg = CurDAG->getRegister(0, MVT::i32);
- ShImmVal = RHS->getValue() & 31;
+ ShImmVal = RHS->getZExtValue() & 31;
} else {
ShReg = N.getOperand(1);
}
SDNode *ARMDAGToDAGISel::Select(SDValue Op) {
- SDNode *N = Op.Val;
+ SDNode *N = Op.getNode();
+ DebugLoc dl = N->getDebugLoc();
if (N->isMachineOpcode())
return NULL; // Already selected.
switch (N->getOpcode()) {
default: break;
case ISD::Constant: {
- unsigned Val = cast<ConstantSDNode>(N)->getValue();
+ unsigned Val = cast<ConstantSDNode>(N)->getZExtValue();
bool UseCP = true;
if (Subtarget->isThumb())
UseCP = (Val > 255 && // MOV
SDNode *ResNode;
if (Subtarget->isThumb())
- ResNode = CurDAG->getTargetNode(ARM::tLDRcp, MVT::i32, MVT::Other,
+ ResNode = CurDAG->getTargetNode(ARM::tLDRcp, dl, MVT::i32, MVT::Other,
CPIdx, CurDAG->getEntryNode());
else {
SDValue Ops[] = {
CurDAG->getRegister(0, MVT::i32),
CurDAG->getEntryNode()
};
- ResNode=CurDAG->getTargetNode(ARM::LDRcp, MVT::i32, MVT::Other, Ops, 6);
+ ResNode=CurDAG->getTargetNode(ARM::LDRcp, dl, MVT::i32, MVT::Other,
+ Ops, 6);
}
ReplaceUses(Op, SDValue(ResNode, 0));
return NULL;
std::swap(LHSR, RHSR);
}
if (RHSR && RHSR->getReg() == ARM::SP) {
- AddToISelQueue(N0);
- AddToISelQueue(N1);
return CurDAG->SelectNodeTo(N, ARM::tADDhirr, Op.getValueType(), N0, N1);
}
break;
if (Subtarget->isThumb())
break;
if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op.getOperand(1))) {
- unsigned RHSV = C->getValue();
+ unsigned RHSV = C->getZExtValue();
if (!RHSV) break;
if (isPowerOf2_32(RHSV-1)) { // 2^n+1?
SDValue V = Op.getOperand(0);
- AddToISelQueue(V);
unsigned ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, Log2_32(RHSV-1));
SDValue Ops[] = { V, V, CurDAG->getRegister(0, MVT::i32),
CurDAG->getTargetConstant(ShImm, MVT::i32),
}
if (isPowerOf2_32(RHSV+1)) { // 2^n-1?
SDValue V = Op.getOperand(0);
- AddToISelQueue(V);
unsigned ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, Log2_32(RHSV+1));
SDValue Ops[] = { V, V, CurDAG->getRegister(0, MVT::i32),
CurDAG->getTargetConstant(ShImm, MVT::i32),
}
break;
case ARMISD::FMRRD:
- AddToISelQueue(Op.getOperand(0));
- return CurDAG->getTargetNode(ARM::FMRRD, MVT::i32, MVT::i32,
+ return CurDAG->getTargetNode(ARM::FMRRD, dl, MVT::i32, MVT::i32,
Op.getOperand(0), getAL(CurDAG),
CurDAG->getRegister(0, MVT::i32));
case ISD::UMUL_LOHI: {
- AddToISelQueue(Op.getOperand(0));
- AddToISelQueue(Op.getOperand(1));
SDValue Ops[] = { Op.getOperand(0), Op.getOperand(1),
getAL(CurDAG), CurDAG->getRegister(0, MVT::i32),
CurDAG->getRegister(0, MVT::i32) };
- return CurDAG->getTargetNode(ARM::UMULL, MVT::i32, MVT::i32, Ops, 5);
+ return CurDAG->getTargetNode(ARM::UMULL, dl, MVT::i32, MVT::i32, Ops, 5);
}
case ISD::SMUL_LOHI: {
- AddToISelQueue(Op.getOperand(0));
- AddToISelQueue(Op.getOperand(1));
SDValue Ops[] = { Op.getOperand(0), Op.getOperand(1),
getAL(CurDAG), CurDAG->getRegister(0, MVT::i32),
CurDAG->getRegister(0, MVT::i32) };
- return CurDAG->getTargetNode(ARM::SMULL, MVT::i32, MVT::i32, Ops, 5);
+ return CurDAG->getTargetNode(ARM::SMULL, dl, MVT::i32, MVT::i32, Ops, 5);
}
case ISD::LOAD: {
LoadSDNode *LD = cast<LoadSDNode>(Op);
if (Match) {
SDValue Chain = LD->getChain();
SDValue Base = LD->getBasePtr();
- AddToISelQueue(Chain);
- AddToISelQueue(Base);
- AddToISelQueue(Offset);
SDValue Ops[]= { Base, Offset, AMOpc, getAL(CurDAG),
CurDAG->getRegister(0, MVT::i32), Chain };
- return CurDAG->getTargetNode(Opcode, MVT::i32, MVT::i32,
+ return CurDAG->getTargetNode(Opcode, dl, MVT::i32, MVT::i32,
MVT::Other, Ops, 6);
}
}
assert(N2.getOpcode() == ISD::Constant);
assert(N3.getOpcode() == ISD::Register);
- AddToISelQueue(Chain);
- AddToISelQueue(N1);
- AddToISelQueue(InFlag);
SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned)
- cast<ConstantSDNode>(N2)->getValue()), MVT::i32);
+ cast<ConstantSDNode>(N2)->getZExtValue()),
+ MVT::i32);
SDValue Ops[] = { N1, Tmp2, N3, Chain, InFlag };
- SDNode *ResNode = CurDAG->getTargetNode(Opc, MVT::Other, MVT::Flag, Ops, 5);
+ SDNode *ResNode = CurDAG->getTargetNode(Opc, dl, MVT::Other,
+ MVT::Flag, Ops, 5);
Chain = SDValue(ResNode, 0);
- if (Op.Val->getNumValues() == 2) {
+ if (Op.getNode()->getNumValues() == 2) {
InFlag = SDValue(ResNode, 1);
- ReplaceUses(SDValue(Op.Val, 1), InFlag);
+ ReplaceUses(SDValue(Op.getNode(), 1), InFlag);
}
- ReplaceUses(SDValue(Op.Val, 0), SDValue(Chain.Val, Chain.ResNo));
+ ReplaceUses(SDValue(Op.getNode(), 0), SDValue(Chain.getNode(), Chain.getResNo()));
return NULL;
}
case ARMISD::CMOV: {
SDValue CPTmp2;
if (!isThumb && VT == MVT::i32 &&
SelectShifterOperandReg(Op, N1, CPTmp0, CPTmp1, CPTmp2)) {
- AddToISelQueue(N0);
- AddToISelQueue(CPTmp0);
- AddToISelQueue(CPTmp1);
- AddToISelQueue(CPTmp2);
- AddToISelQueue(InFlag);
SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned)
- cast<ConstantSDNode>(N2)->getValue()), MVT::i32);
+ cast<ConstantSDNode>(N2)->getZExtValue()),
+ MVT::i32);
SDValue Ops[] = { N0, CPTmp0, CPTmp1, CPTmp2, Tmp2, N3, InFlag };
- return CurDAG->SelectNodeTo(Op.Val, ARM::MOVCCs, MVT::i32, Ops, 7);
+ return CurDAG->SelectNodeTo(Op.getNode(), ARM::MOVCCs, MVT::i32, Ops, 7);
}
// Pattern: (ARMcmov:i32 GPR:i32:$false,
// Pattern complexity = 10 cost = 1 size = 0
if (VT == MVT::i32 &&
N3.getOpcode() == ISD::Constant &&
- Predicate_so_imm(N3.Val)) {
- AddToISelQueue(N0);
- AddToISelQueue(InFlag);
+ Predicate_so_imm(N3.getNode())) {
SDValue Tmp1 = CurDAG->getTargetConstant(((unsigned)
- cast<ConstantSDNode>(N1)->getValue()), MVT::i32);
- Tmp1 = Transform_so_imm_XFORM(Tmp1.Val);
+ cast<ConstantSDNode>(N1)->getZExtValue()),
+ MVT::i32);
+ Tmp1 = Transform_so_imm_XFORM(Tmp1.getNode());
SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned)
- cast<ConstantSDNode>(N2)->getValue()), MVT::i32);
+ cast<ConstantSDNode>(N2)->getZExtValue()),
+ MVT::i32);
SDValue Ops[] = { N0, Tmp1, Tmp2, N3, InFlag };
- return CurDAG->SelectNodeTo(Op.Val, ARM::MOVCCi, MVT::i32, Ops, 5);
+ return CurDAG->SelectNodeTo(Op.getNode(), ARM::MOVCCi, MVT::i32, Ops, 5);
}
// Pattern: (ARMcmov:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc)
// Pattern complexity = 6 cost = 11 size = 0
//
// Also FCPYScc and FCPYDcc.
- AddToISelQueue(N0);
- AddToISelQueue(N1);
- AddToISelQueue(InFlag);
SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned)
- cast<ConstantSDNode>(N2)->getValue()), MVT::i32);
+ cast<ConstantSDNode>(N2)->getZExtValue()),
+ MVT::i32);
SDValue Ops[] = { N0, N1, Tmp2, N3, InFlag };
unsigned Opc = 0;
switch (VT.getSimpleVT()) {
Opc = ARM::FCPYDcc;
break;
}
- return CurDAG->SelectNodeTo(Op.Val, Opc, VT, Ops, 5);
+ return CurDAG->SelectNodeTo(Op.getNode(), Opc, VT, Ops, 5);
}
case ARMISD::CNEG: {
MVT VT = Op.getValueType();
assert(N2.getOpcode() == ISD::Constant);
assert(N3.getOpcode() == ISD::Register);
- AddToISelQueue(N0);
- AddToISelQueue(N1);
- AddToISelQueue(InFlag);
SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned)
- cast<ConstantSDNode>(N2)->getValue()), MVT::i32);
+ cast<ConstantSDNode>(N2)->getZExtValue()),
+ MVT::i32);
SDValue Ops[] = { N0, N1, Tmp2, N3, InFlag };
unsigned Opc = 0;
switch (VT.getSimpleVT()) {
break;
case MVT::f64:
Opc = ARM::FNEGDcc;
- break;
+ break;
+ }
+ return CurDAG->SelectNodeTo(Op.getNode(), Opc, VT, Ops, 5);
+ }
+
+ case ISD::DECLARE: {
+ SDValue Chain = Op.getOperand(0);
+ SDValue N1 = Op.getOperand(1);
+ SDValue N2 = Op.getOperand(2);
+ FrameIndexSDNode *FINode = dyn_cast<FrameIndexSDNode>(N1);
+ if (!FINode)
+ break;
+ if (N2.getOpcode() == ARMISD::PIC_ADD && isa<LoadSDNode>(N2.getOperand(0)))
+ N2 = N2.getOperand(0);
+ LoadSDNode *Ld = dyn_cast<LoadSDNode>(N2);
+ if (!Ld)
+ break;
+ SDValue BasePtr = Ld->getBasePtr();
+ assert(BasePtr.getOpcode() == ARMISD::Wrapper &&
+ isa<ConstantPoolSDNode>(BasePtr.getOperand(0)) &&
+ "llvm.dbg.variable should be a constantpool node");
+ ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(BasePtr.getOperand(0));
+ GlobalValue *GV = 0;
+ if (CP->isMachineConstantPoolEntry()) {
+ ARMConstantPoolValue *ACPV = (ARMConstantPoolValue*)CP->getMachineCPVal();
+ GV = ACPV->getGV();
+ } else
+ GV = dyn_cast<GlobalValue>(CP->getConstVal());
+ if (GV) {
+ SDValue Tmp1 = CurDAG->getTargetFrameIndex(FINode->getIndex(),
+ TLI.getPointerTy());
+ SDValue Tmp2 = CurDAG->getTargetGlobalAddress(GV, TLI.getPointerTy());
+ SDValue Ops[] = { Tmp1, Tmp2, Chain };
+ return CurDAG->getTargetNode(TargetInstrInfo::DECLARE, dl,
+ MVT::Other, Ops, 3);
}
- return CurDAG->SelectNodeTo(Op.Val, Opc, VT, Ops, 5);
+ break;
}
}
+
return SelectCode(Op);
}