//===-- ARMISelDAGToDAG.cpp - A dag to dag inst selector for ARM ----------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines an instruction selector for the ARM target.
//
//===----------------------------------------------------------------------===//

#include "ARM.h"
#include "ARMISelLowering.h"
#include "ARMTargetMachine.h"
#include "ARMAddressingModes.h"
#include "llvm/CallingConv.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Function.h"
#include "llvm/Intrinsics.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/SelectionDAG.h"
#include "llvm/CodeGen/SelectionDAGISel.h"
#include "llvm/Target/TargetLowering.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
using namespace llvm;

//===--------------------------------------------------------------------===//
/// ARMDAGToDAGISel - ARM specific code to select ARM machine
/// instructions for SelectionDAG operations.
///
namespace {
class ARMDAGToDAGISel : public SelectionDAGISel {
  ARMTargetLowering Lowering;

  /// 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:
  ARMDAGToDAGISel(ARMTargetMachine &TM)
    : SelectionDAGISel(Lowering), Lowering(TM),
    Subtarget(&TM.getSubtarget<ARMSubtarget>()) {
  }

  virtual const char *getPassName() const {
    return "ARM Instruction Selection";
  } 
  
  SDNode *Select(SDOperand Op);
  virtual void InstructionSelectBasicBlock(SelectionDAG &DAG);
  bool SelectAddrMode2(SDOperand Op, SDOperand N, SDOperand &Base,
                       SDOperand &Offset, SDOperand &Opc);
  bool SelectAddrMode2Offset(SDOperand Op, SDOperand N,
                             SDOperand &Offset, SDOperand &Opc);
  bool SelectAddrMode3(SDOperand Op, SDOperand N, SDOperand &Base,
                       SDOperand &Offset, SDOperand &Opc);
  bool SelectAddrMode3Offset(SDOperand Op, SDOperand N,
                             SDOperand &Offset, SDOperand &Opc);
  bool SelectAddrMode5(SDOperand Op, SDOperand N, SDOperand &Base,
                       SDOperand &Offset);

  bool SelectAddrModePC(SDOperand Op, SDOperand N, SDOperand &Offset,
                         SDOperand &Label);

  bool SelectThumbAddrModeRR(SDOperand Op, SDOperand N, SDOperand &Base,
                             SDOperand &Offset);
  bool SelectThumbAddrModeRI5(SDOperand Op, SDOperand N, unsigned Scale,
                              SDOperand &Base, SDOperand &OffImm,
                              SDOperand &Offset);
  bool SelectThumbAddrModeS1(SDOperand Op, SDOperand N, SDOperand &Base,
                             SDOperand &OffImm, SDOperand &Offset);
  bool SelectThumbAddrModeS2(SDOperand Op, SDOperand N, SDOperand &Base,
                             SDOperand &OffImm, SDOperand &Offset);
  bool SelectThumbAddrModeS4(SDOperand Op, SDOperand N, SDOperand &Base,
                             SDOperand &OffImm, SDOperand &Offset);
  bool SelectThumbAddrModeSP(SDOperand Op, SDOperand N, SDOperand &Base,
                             SDOperand &OffImm);

  bool SelectShifterOperandReg(SDOperand Op, SDOperand N, SDOperand &A,
                               SDOperand &B, SDOperand &C);
  
  // Include the pieces autogenerated from the target description.
#include "ARMGenDAGISel.inc"
};
}

void ARMDAGToDAGISel::InstructionSelectBasicBlock(SelectionDAG &DAG) {
  DEBUG(BB->dump());

  DAG.setRoot(SelectRoot(DAG.getRoot()));
  DAG.RemoveDeadNodes();

  ScheduleAndEmitDAG(DAG);
}

bool ARMDAGToDAGISel::SelectAddrMode2(SDOperand Op, SDOperand N,
                                      SDOperand &Base, SDOperand &Offset,
                                      SDOperand &Opc) {
  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();
      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),
                                          MVT::i32);
          return true;
        }
      }
    }
  }

  if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB) {
    Base = N;
    if (N.getOpcode() == ISD::FrameIndex) {
      int FI = cast<FrameIndexSDNode>(N)->getIndex();
      Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
    } else if (N.getOpcode() == ARMISD::Wrapper) {
      Base = N.getOperand(0);
    }
    Offset = CurDAG->getRegister(0, MVT::i32);
    Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(ARM_AM::add, 0,
                                                      ARM_AM::no_shift),
                                    MVT::i32);
    return true;
  }
  
  // Match simple R +/- imm12 operands.
  if (N.getOpcode() == ISD::ADD)
    if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
      int RHSC = (int)RHS->getValue();
      if ((RHSC >= 0 && RHSC < 0x1000) ||
          (RHSC < 0 && RHSC > -0x1000)) { // 12 bits.
        Base = N.getOperand(0);
        if (Base.getOpcode() == ISD::FrameIndex) {
          int FI = cast<FrameIndexSDNode>(Base)->getIndex();
          Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
        }
        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),
                                        MVT::i32);
        return true;
      }
    }
  
  // Otherwise this is R +/- [possibly shifted] R
  ARM_AM::AddrOpc AddSub = N.getOpcode() == ISD::ADD ? ARM_AM::add:ARM_AM::sub;
  ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(1));
  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->getValue();
      Offset = N.getOperand(1).getOperand(0);
    } else {
      ShOpcVal = ARM_AM::no_shift;
    }
  }
  
  // Try matching (R shl C) + (R).
  if (N.getOpcode() == ISD::ADD && ShOpcVal == ARM_AM::no_shift) {
    ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0));
    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->getValue();
        Offset = N.getOperand(0).getOperand(0);
        Base = N.getOperand(1);
      } else {
        ShOpcVal = ARM_AM::no_shift;
      }
    }
  }
  
  Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal),
                                  MVT::i32);
  return true;
}

bool ARMDAGToDAGISel::SelectAddrMode2Offset(SDOperand Op, SDOperand N,
                                            SDOperand &Offset, SDOperand &Opc) {
  unsigned Opcode = Op.getOpcode();
  ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
    ? cast<LoadSDNode>(Op)->getAddressingMode()
    : cast<StoreSDNode>(Op)->getAddressingMode();
  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();
    if (Val >= 0 && Val < 0x1000) { // 12 bits.
      Offset = CurDAG->getRegister(0, MVT::i32);
      Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, Val,
                                                        ARM_AM::no_shift),
                                      MVT::i32);
      return true;
    }
  }

  Offset = N;
  ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N);
  unsigned ShAmt = 0;
  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))) {
      ShAmt = Sh->getValue();
      Offset = N.getOperand(0);
    } else {
      ShOpcVal = ARM_AM::no_shift;
    }
  }

  Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal),
                                  MVT::i32);
  return true;
}


bool ARMDAGToDAGISel::SelectAddrMode3(SDOperand Op, SDOperand N,
                                      SDOperand &Base, SDOperand &Offset,
                                      SDOperand &Opc) {
  if (N.getOpcode() == ISD::SUB) {
    // X - C  is canonicalize to X + -C, no need to handle it here.
    Base = N.getOperand(0);
    Offset = N.getOperand(1);
    Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::sub, 0),MVT::i32);
    return true;
  }
  
  if (N.getOpcode() != ISD::ADD) {
    Base = N;
    if (N.getOpcode() == ISD::FrameIndex) {
      int FI = cast<FrameIndexSDNode>(N)->getIndex();
      Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
    }
    Offset = CurDAG->getRegister(0, MVT::i32);
    Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0),MVT::i32);
    return true;
  }
  
  // If the RHS is +/- imm8, fold into addr mode.
  if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
    int RHSC = (int)RHS->getValue();
    if ((RHSC >= 0 && RHSC < 256) ||
        (RHSC < 0 && RHSC > -256)) { // note -256 itself isn't allowed.
      Base = N.getOperand(0);
      if (Base.getOpcode() == ISD::FrameIndex) {
        int FI = cast<FrameIndexSDNode>(Base)->getIndex();
        Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
      }
      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::getAM3Opc(AddSub, RHSC),MVT::i32);
      return true;
    }
  }
  
  Base = N.getOperand(0);
  Offset = N.getOperand(1);
  Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0), MVT::i32);
  return true;
}

bool ARMDAGToDAGISel::SelectAddrMode3Offset(SDOperand Op, SDOperand N,
                                            SDOperand &Offset, SDOperand &Opc) {
  unsigned Opcode = Op.getOpcode();
  ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
    ? cast<LoadSDNode>(Op)->getAddressingMode()
    : cast<StoreSDNode>(Op)->getAddressingMode();
  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();
    if (Val >= 0 && Val < 256) {
      Offset = CurDAG->getRegister(0, MVT::i32);
      Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, Val), MVT::i32);
      return true;
    }
  }

  Offset = N;
  Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, 0), MVT::i32);
  return true;
}


bool ARMDAGToDAGISel::SelectAddrMode5(SDOperand Op, SDOperand N,
                                      SDOperand &Base, SDOperand &Offset) {
  if (N.getOpcode() != ISD::ADD) {
    Base = N;
    if (N.getOpcode() == ISD::FrameIndex) {
      int FI = cast<FrameIndexSDNode>(N)->getIndex();
      Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
    } else if (N.getOpcode() == ARMISD::Wrapper) {
      Base = N.getOperand(0);
    }
    Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0),
                                       MVT::i32);
    return true;
  }
  
  // If the RHS is +/- imm8, fold into addr mode.
  if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
    int RHSC = (int)RHS->getValue();
    if ((RHSC & 3) == 0) {  // The constant is implicitly multiplied by 4.
      RHSC >>= 2;
      if ((RHSC >= 0 && RHSC < 256) ||
          (RHSC < 0 && RHSC > -256)) { // note -256 itself isn't allowed.
        Base = N.getOperand(0);
        if (Base.getOpcode() == ISD::FrameIndex) {
          int FI = cast<FrameIndexSDNode>(Base)->getIndex();
          Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
        }

        ARM_AM::AddrOpc AddSub = ARM_AM::add;
        if (RHSC < 0) {
          AddSub = ARM_AM::sub;
          RHSC = - RHSC;
        }
        Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(AddSub, RHSC),
                                           MVT::i32);
        return true;
      }
    }
  }
  
  Base = N;
  Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0),
                                     MVT::i32);
  return true;
}

bool ARMDAGToDAGISel::SelectAddrModePC(SDOperand Op, SDOperand N,
                                        SDOperand &Offset, SDOperand &Label) {
  if (N.getOpcode() == ARMISD::PIC_ADD && N.hasOneUse()) {
    Offset = N.getOperand(0);
    SDOperand N1 = N.getOperand(1);
    Label  = CurDAG->getTargetConstant(cast<ConstantSDNode>(N1)->getValue(),
                                       MVT::i32);
    return true;
  }
  return false;
}

bool ARMDAGToDAGISel::SelectThumbAddrModeRR(SDOperand Op, SDOperand N,
                                            SDOperand &Base, SDOperand &Offset){
  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 = SDOperand(CurDAG->getTargetNode(ARM::tMOVi8, MVT::i32,
                                    CurDAG->getTargetConstant(0, MVT::i32)), 0);
    return true;
  }

  Base = N.getOperand(0);
  Offset = N.getOperand(1);
  return true;
}

bool
ARMDAGToDAGISel::SelectThumbAddrModeRI5(SDOperand Op, SDOperand N,
                                        unsigned Scale, SDOperand &Base,
                                        SDOperand &OffImm, SDOperand &Offset) {
  if (Scale == 4) {
    SDOperand TmpBase, TmpOffImm;
    if (SelectThumbAddrModeSP(Op, N, TmpBase, TmpOffImm))
      return false;  // We want to select tLDRspi / tSTRspi instead.
    if (N.getOpcode() == ARMISD::Wrapper &&
        N.getOperand(0).getOpcode() == ISD::TargetConstantPool)
      return false;  // We want to select tLDRpci instead.
  }

  if (N.getOpcode() != ISD::ADD) {
    Base = (N.getOpcode() == ARMISD::Wrapper) ? N.getOperand(0) : N;
    Offset = CurDAG->getRegister(0, MVT::i32);
    OffImm = CurDAG->getTargetConstant(0, MVT::i32);
    return true;
  }

  // Thumb does not have [sp, r] address mode.
  RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0));
  RegisterSDNode *RHSR = dyn_cast<RegisterSDNode>(N.getOperand(1));
  if ((LHSR && LHSR->getReg() == ARM::SP) ||
      (RHSR && RHSR->getReg() == ARM::SP)) {
    Base = N;
    Offset = CurDAG->getRegister(0, MVT::i32);
    OffImm = CurDAG->getTargetConstant(0, MVT::i32);
    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();
    if ((RHSC & (Scale-1)) == 0) {  // The constant is implicitly multiplied.
      RHSC /= Scale;
      if (RHSC >= 0 && RHSC < 32) {
        Base = N.getOperand(0);
        Offset = CurDAG->getRegister(0, MVT::i32);
        OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32);
        return true;
      }
    }
  }

  Base = N.getOperand(0);
  Offset = N.getOperand(1);
  OffImm = CurDAG->getTargetConstant(0, MVT::i32);
  return true;
}

bool ARMDAGToDAGISel::SelectThumbAddrModeS1(SDOperand Op, SDOperand N,
                                            SDOperand &Base, SDOperand &OffImm,
                                            SDOperand &Offset) {
  return SelectThumbAddrModeRI5(Op, N, 1, Base, OffImm, Offset);
}

bool ARMDAGToDAGISel::SelectThumbAddrModeS2(SDOperand Op, SDOperand N,
                                            SDOperand &Base, SDOperand &OffImm,
                                            SDOperand &Offset) {
  return SelectThumbAddrModeRI5(Op, N, 2, Base, OffImm, Offset);
}

bool ARMDAGToDAGISel::SelectThumbAddrModeS4(SDOperand Op, SDOperand N,
                                            SDOperand &Base, SDOperand &OffImm,
                                            SDOperand &Offset) {
  return SelectThumbAddrModeRI5(Op, N, 4, Base, OffImm, Offset);
}

bool ARMDAGToDAGISel::SelectThumbAddrModeSP(SDOperand Op, SDOperand N,
                                           SDOperand &Base, SDOperand &OffImm) {
  if (N.getOpcode() == ISD::FrameIndex) {
    int FI = cast<FrameIndexSDNode>(N)->getIndex();
    Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
    OffImm = CurDAG->getTargetConstant(0, MVT::i32);
    return true;
  }

  if (N.getOpcode() != ISD::ADD)
    return false;

  RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0));
  if (N.getOperand(0).getOpcode() == ISD::FrameIndex ||
      (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();
      if ((RHSC & 3) == 0) {  // The constant is implicitly multiplied.
        RHSC >>= 2;
        if (RHSC >= 0 && RHSC < 256) {
          Base = N.getOperand(0);
          if (Base.getOpcode() == ISD::FrameIndex) {
            int FI = cast<FrameIndexSDNode>(Base)->getIndex();
            Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
          }
          OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32);
          return true;
        }
      }
    }
  }
  
  return false;
}

bool ARMDAGToDAGISel::SelectShifterOperandReg(SDOperand Op,
                                              SDOperand N, 
                                              SDOperand &BaseReg,
                                              SDOperand &ShReg,
                                              SDOperand &Opc) {
  ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N);

  // Don't match base register only case. That is matched to a separate
  // lower complexity pattern with explicit register operand.
  if (ShOpcVal == ARM_AM::no_shift) return false;
  
  BaseReg = N.getOperand(0);
  unsigned ShImmVal = 0;
  if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
    ShReg = CurDAG->getRegister(0, MVT::i32);
    ShImmVal = RHS->getValue() & 31;
  } else {
    ShReg = N.getOperand(1);
  }
  Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal),
                                  MVT::i32);
  return true;
}

/// getAL - Returns a ARMCC::AL immediate node.
static inline SDOperand getAL(SelectionDAG *CurDAG) {
  return CurDAG->getTargetConstant((uint64_t)ARMCC::AL, MVT::i32);
}


SDNode *ARMDAGToDAGISel::Select(SDOperand Op) {
  SDNode *N = Op.Val;
  unsigned Opcode = N->getOpcode();

  if (Opcode >= ISD::BUILTIN_OP_END && Opcode < ARMISD::FIRST_NUMBER)
    return NULL;   // Already selected.

  switch (N->getOpcode()) {
  default: break;
  case ISD::Constant: {
    unsigned Val = cast<ConstantSDNode>(N)->getValue();
    bool UseCP = true;
    if (Subtarget->isThumb())
      UseCP = (Val > 255 &&                          // MOV
               ~Val > 255 &&                         // MOV + MVN
               !ARM_AM::isThumbImmShiftedVal(Val));  // MOV + LSL
    else
      UseCP = (ARM_AM::getSOImmVal(Val) == -1 &&     // MOV
               ARM_AM::getSOImmVal(~Val) == -1 &&    // MVN
               !ARM_AM::isSOImmTwoPartVal(Val));     // two instrs.
    if (UseCP) {
      SDOperand CPIdx =
        CurDAG->getTargetConstantPool(ConstantInt::get(Type::Int32Ty, Val),
                                      TLI.getPointerTy());

      SDNode *ResNode;
      if (Subtarget->isThumb())
        ResNode = CurDAG->getTargetNode(ARM::tLDRcp, MVT::i32, MVT::Other,
                                        CPIdx, CurDAG->getEntryNode());
      else {
        SDOperand Ops[] = {
          CPIdx, 
          CurDAG->getRegister(0, MVT::i32),
          CurDAG->getTargetConstant(0, MVT::i32),
          getAL(CurDAG),
          CurDAG->getRegister(0, MVT::i32),
          CurDAG->getEntryNode()
        };
        ResNode=CurDAG->getTargetNode(ARM::LDRcp, MVT::i32, MVT::Other, Ops, 6);
      }
      ReplaceUses(Op, SDOperand(ResNode, 0));
      return NULL;
    }
      
    // Other cases are autogenerated.
    break;
  }
  case ISD::FrameIndex: {
    // Selects to ADDri FI, 0 which in turn will become ADDri SP, imm.
    int FI = cast<FrameIndexSDNode>(N)->getIndex();
    SDOperand TFI = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
    if (Subtarget->isThumb())
      return CurDAG->SelectNodeTo(N, ARM::tADDrSPi, MVT::i32, TFI,
                                  CurDAG->getTargetConstant(0, MVT::i32));
    else {
      SDOperand Ops[] = { TFI, CurDAG->getTargetConstant(0, MVT::i32),
                          getAL(CurDAG), CurDAG->getRegister(0, MVT::i32),
                          CurDAG->getRegister(0, MVT::i32) };
      return CurDAG->SelectNodeTo(N, ARM::ADDri, MVT::i32, Ops, 5);
    }
  }
  case ISD::ADD: {
    // Select add sp, c to tADDhirr.
    SDOperand N0 = Op.getOperand(0);
    SDOperand N1 = Op.getOperand(1);
    RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(Op.getOperand(0));
    RegisterSDNode *RHSR = dyn_cast<RegisterSDNode>(Op.getOperand(1));
    if (LHSR && LHSR->getReg() == ARM::SP) {
      std::swap(N0, N1);
      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;
  }
  case ISD::MUL:
    if (Subtarget->isThumb())
      break;
    if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op.getOperand(1))) {
      unsigned RHSV = C->getValue();
      if (!RHSV) break;
      if (isPowerOf2_32(RHSV-1)) {  // 2^n+1?
        SDOperand V = Op.getOperand(0);
        AddToISelQueue(V);
        unsigned ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, Log2_32(RHSV-1));
        SDOperand Ops[] = { V, V, CurDAG->getRegister(0, MVT::i32),
                            CurDAG->getTargetConstant(ShImm, MVT::i32),
                            getAL(CurDAG), CurDAG->getRegister(0, MVT::i32),
                            CurDAG->getRegister(0, MVT::i32) };
        return CurDAG->SelectNodeTo(N, ARM::ADDrs, MVT::i32, Ops, 7);
      }
      if (isPowerOf2_32(RHSV+1)) {  // 2^n-1?
        SDOperand V = Op.getOperand(0);
        AddToISelQueue(V);
        unsigned ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, Log2_32(RHSV+1));
        SDOperand Ops[] = { V, V, CurDAG->getRegister(0, MVT::i32),
                            CurDAG->getTargetConstant(ShImm, MVT::i32),
                            getAL(CurDAG), CurDAG->getRegister(0, MVT::i32),
                            CurDAG->getRegister(0, MVT::i32) };
        return CurDAG->SelectNodeTo(N, ARM::RSBrs, MVT::i32, Ops, 7);
      }
    }
    break;
  case ARMISD::FMRRD:
    AddToISelQueue(Op.getOperand(0));
    return CurDAG->getTargetNode(ARM::FMRRD, 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));
    SDOperand 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);
  }
  case ISD::SMUL_LOHI: {
    AddToISelQueue(Op.getOperand(0));
    AddToISelQueue(Op.getOperand(1));
    SDOperand 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);
  }
  case ISD::LOAD: {
    LoadSDNode *LD = cast<LoadSDNode>(Op);
    ISD::MemIndexedMode AM = LD->getAddressingMode();
    MVT::ValueType LoadedVT = LD->getMemoryVT();
    if (AM != ISD::UNINDEXED) {
      SDOperand Offset, AMOpc;
      bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC);
      unsigned Opcode = 0;
      bool Match = false;
      if (LoadedVT == MVT::i32 &&
          SelectAddrMode2Offset(Op, LD->getOffset(), Offset, AMOpc)) {
        Opcode = isPre ? ARM::LDR_PRE : ARM::LDR_POST;
        Match = true;
      } else if (LoadedVT == MVT::i16 &&
                 SelectAddrMode3Offset(Op, LD->getOffset(), Offset, AMOpc)) {
        Match = true;
        Opcode = (LD->getExtensionType() == ISD::SEXTLOAD)
          ? (isPre ? ARM::LDRSH_PRE : ARM::LDRSH_POST)
          : (isPre ? ARM::LDRH_PRE : ARM::LDRH_POST);
      } else if (LoadedVT == MVT::i8 || LoadedVT == MVT::i1) {
        if (LD->getExtensionType() == ISD::SEXTLOAD) {
          if (SelectAddrMode3Offset(Op, LD->getOffset(), Offset, AMOpc)) {
            Match = true;
            Opcode = isPre ? ARM::LDRSB_PRE : ARM::LDRSB_POST;
          }
        } else {
          if (SelectAddrMode2Offset(Op, LD->getOffset(), Offset, AMOpc)) {
            Match = true;
            Opcode = isPre ? ARM::LDRB_PRE : ARM::LDRB_POST;
          }
        }
      }

      if (Match) {
        SDOperand Chain = LD->getChain();
        SDOperand Base = LD->getBasePtr();
        AddToISelQueue(Chain);
        AddToISelQueue(Base);
        AddToISelQueue(Offset);
        SDOperand Ops[]= { Base, Offset, AMOpc, getAL(CurDAG),
                           CurDAG->getRegister(0, MVT::i32), Chain };
        return CurDAG->getTargetNode(Opcode, MVT::i32, MVT::i32,
                                     MVT::Other, Ops, 6);
      }
    }
    // Other cases are autogenerated.
    break;
  }
  case ARMISD::BRCOND: {
    // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
    // Emits: (Bcc:void (bb:Other):$dst, (imm:i32):$cc)
    // Pattern complexity = 6  cost = 1  size = 0

    // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
    // Emits: (tBcc:void (bb:Other):$dst, (imm:i32):$cc)
    // Pattern complexity = 6  cost = 1  size = 0

    unsigned Opc = Subtarget->isThumb() ? ARM::tBcc : ARM::Bcc;
    SDOperand Chain = Op.getOperand(0);
    SDOperand N1 = Op.getOperand(1);
    SDOperand N2 = Op.getOperand(2);
    SDOperand N3 = Op.getOperand(3);
    SDOperand InFlag = Op.getOperand(4);
    assert(N1.getOpcode() == ISD::BasicBlock);
    assert(N2.getOpcode() == ISD::Constant);
    assert(N3.getOpcode() == ISD::Register);

    AddToISelQueue(Chain);
    AddToISelQueue(N1);
    AddToISelQueue(InFlag);
    SDOperand Tmp2 = CurDAG->getTargetConstant(((unsigned)
                               cast<ConstantSDNode>(N2)->getValue()), MVT::i32);
    SDOperand Ops[] = { N1, Tmp2, N3, Chain, InFlag };
    SDNode *ResNode = CurDAG->getTargetNode(Opc, MVT::Other, MVT::Flag, Ops, 5);
    Chain = SDOperand(ResNode, 0);
    if (Op.Val->getNumValues() == 2) {
      InFlag = SDOperand(ResNode, 1);
      ReplaceUses(SDOperand(Op.Val, 1), InFlag);
    }
    ReplaceUses(SDOperand(Op.Val, 0), SDOperand(Chain.Val, Chain.ResNo));
    return NULL;
  }
  case ARMISD::CMOV: {
    bool isThumb = Subtarget->isThumb();
    MVT::ValueType VT = Op.getValueType();
    SDOperand N0 = Op.getOperand(0);
    SDOperand N1 = Op.getOperand(1);
    SDOperand N2 = Op.getOperand(2);
    SDOperand N3 = Op.getOperand(3);
    SDOperand InFlag = Op.getOperand(4);
    assert(N2.getOpcode() == ISD::Constant);
    assert(N3.getOpcode() == ISD::Register);

    // Pattern: (ARMcmov:i32 GPR:i32:$false, so_reg:i32:$true, (imm:i32):$cc)
    // Emits: (MOVCCs:i32 GPR:i32:$false, so_reg:i32:$true, (imm:i32):$cc)
    // Pattern complexity = 18  cost = 1  size = 0
    SDOperand CPTmp0;
    SDOperand CPTmp1;
    SDOperand CPTmp2;
    if (!isThumb && VT == MVT::i32 &&
        SelectShifterOperandReg(Op, N1, CPTmp0, CPTmp1, CPTmp2)) {
      AddToISelQueue(N0);
      AddToISelQueue(CPTmp0);
      AddToISelQueue(CPTmp1);
      AddToISelQueue(CPTmp2);
      AddToISelQueue(InFlag);
      SDOperand Tmp2 = CurDAG->getTargetConstant(((unsigned)
                               cast<ConstantSDNode>(N2)->getValue()), MVT::i32);
      SDOperand Ops[] = { N0, CPTmp0, CPTmp1, CPTmp2, Tmp2, N3, InFlag };
      return CurDAG->SelectNodeTo(Op.Val, ARM::MOVCCs, MVT::i32, Ops, 7);
    }

    // Pattern: (ARMcmov:i32 GPR:i32:$false,
    //             (imm:i32)<<P:Predicate_so_imm>><<X:so_imm_XFORM>>:$true,
    //             (imm:i32):$cc)
    // Emits: (MOVCCi:i32 GPR:i32:$false,
    //           (so_imm_XFORM:i32 (imm:i32):$true), (imm:i32):$cc)
    // Pattern complexity = 10  cost = 1  size = 0
    if (VT == MVT::i32 &&
        N3.getOpcode() == ISD::Constant &&
        Predicate_so_imm(N3.Val)) {
      AddToISelQueue(N0);
      AddToISelQueue(InFlag);
      SDOperand Tmp1 = CurDAG->getTargetConstant(((unsigned)
                               cast<ConstantSDNode>(N1)->getValue()), MVT::i32);
      Tmp1 = Transform_so_imm_XFORM(Tmp1.Val);
      SDOperand Tmp2 = CurDAG->getTargetConstant(((unsigned)
                               cast<ConstantSDNode>(N2)->getValue()), MVT::i32);
      SDOperand Ops[] = { N0, Tmp1, Tmp2, N3, InFlag };
      return CurDAG->SelectNodeTo(Op.Val, ARM::MOVCCi, MVT::i32, Ops, 5);
    }

    // Pattern: (ARMcmov:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc)
    // Emits: (MOVCCr:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc)
    // Pattern complexity = 6  cost = 1  size = 0
    //
    // Pattern: (ARMcmov:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc)
    // Emits: (tMOVCCr: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);
    SDOperand Tmp2 = CurDAG->getTargetConstant(((unsigned)
                               cast<ConstantSDNode>(N2)->getValue()), MVT::i32);
    SDOperand Ops[] = { N0, N1, Tmp2, N3, InFlag };
    unsigned Opc = 0;
    switch (VT) {
    default: assert(false && "Illegal conditional move type!");
      break;
    case MVT::i32:
      Opc = isThumb ? ARM::tMOVCCr : ARM::MOVCCr;
      break;
    case MVT::f32:
      Opc = ARM::FCPYScc;
      break;
    case MVT::f64:
      Opc = ARM::FCPYDcc;
      break; 
    }
    return CurDAG->SelectNodeTo(Op.Val, Opc, VT, Ops, 5);
  }
  case ARMISD::CNEG: {
    MVT::ValueType VT = Op.getValueType();
    SDOperand N0 = Op.getOperand(0);
    SDOperand N1 = Op.getOperand(1);
    SDOperand N2 = Op.getOperand(2);
    SDOperand N3 = Op.getOperand(3);
    SDOperand InFlag = Op.getOperand(4);
    assert(N2.getOpcode() == ISD::Constant);
    assert(N3.getOpcode() == ISD::Register);

    AddToISelQueue(N0);
    AddToISelQueue(N1);
    AddToISelQueue(InFlag);
    SDOperand Tmp2 = CurDAG->getTargetConstant(((unsigned)
                               cast<ConstantSDNode>(N2)->getValue()), MVT::i32);
    SDOperand Ops[] = { N0, N1, Tmp2, N3, InFlag };
    unsigned Opc = 0;
    switch (VT) {
    default: assert(false && "Illegal conditional move type!");
      break;
    case MVT::f32:
      Opc = ARM::FNEGScc;
      break;
    case MVT::f64:
      Opc = ARM::FNEGDcc;
      break; 
    }
    return CurDAG->SelectNodeTo(Op.Val, Opc, VT, Ops, 5);
  }
  }
  return SelectCode(Op);
}

/// createARMISelDag - This pass converts a legalized DAG into a
/// ARM-specific DAG, ready for instruction scheduling.
///
FunctionPass *llvm::createARMISelDag(ARMTargetMachine &TM) {
  return new ARMDAGToDAGISel(TM);
}
