//===- ARMFastISel.cpp - ARM FastISel implementation ----------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file defines the ARM-specific support for the FastISel class. Some
// of the target-specific code is generated by tablegen in the file
// ARMGenFastISel.inc, which is #included here.
//
//===----------------------------------------------------------------------===//

#include "ARM.h"
#include "ARMBaseInstrInfo.h"
#include "ARMBaseRegisterInfo.h"
#include "ARMCallingConv.h"
#include "ARMConstantPoolValue.h"
#include "ARMISelLowering.h"
#include "ARMMachineFunctionInfo.h"
#include "ARMSubtarget.h"
#include "MCTargetDesc/ARMAddressingModes.h"
#include "MCTargetDesc/ARMBaseInfo.h"
#include "Utils/ARMBaseInfo.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/CallingConvLower.h"
#include "llvm/CodeGen/FastISel.h"
#include "llvm/CodeGen/FunctionLoweringInfo.h"
#include "llvm/CodeGen/ISDOpcodes.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineMemOperand.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/RuntimeLibcalls.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
#include "llvm/CodeGen/TargetLowering.h"
#include "llvm/CodeGen/TargetOpcodes.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/CodeGen/ValueTypes.h"
#include "llvm/IR/Argument.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/CallingConv.h"
#include "llvm/IR/Constant.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GetElementPtrTypeIterator.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Operator.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/User.h"
#include "llvm/IR/Value.h"
#include "llvm/MC/MCInstrDesc.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MachineValueType.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include <cassert>
#include <cstdint>
#include <utility>

using namespace llvm;

namespace {

  // All possible address modes, plus some.
  struct Address {
    enum {
      RegBase,
      FrameIndexBase
    } BaseType = RegBase;

    union {
      unsigned Reg;
      int FI;
    } Base;

    int Offset = 0;

    // Innocuous defaults for our address.
    Address() {
      Base.Reg = 0;
    }
  };

class ARMFastISel final : public FastISel {
  /// 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;
  Module &M;
  const TargetMachine &TM;
  const TargetInstrInfo &TII;
  const TargetLowering &TLI;
  ARMFunctionInfo *AFI;

  // Convenience variables to avoid some queries.
  bool isThumb2;
  LLVMContext *Context;

  public:
    explicit ARMFastISel(FunctionLoweringInfo &funcInfo,
                         const TargetLibraryInfo *libInfo)
        : FastISel(funcInfo, libInfo),
          Subtarget(
              &static_cast<const ARMSubtarget &>(funcInfo.MF->getSubtarget())),
          M(const_cast<Module &>(*funcInfo.Fn->getParent())),
          TM(funcInfo.MF->getTarget()), TII(*Subtarget->getInstrInfo()),
          TLI(*Subtarget->getTargetLowering()) {
      AFI = funcInfo.MF->getInfo<ARMFunctionInfo>();
      isThumb2 = AFI->isThumbFunction();
      Context = &funcInfo.Fn->getContext();
    }

  private:
    // Code from FastISel.cpp.

    unsigned fastEmitInst_r(unsigned MachineInstOpcode,
                            const TargetRegisterClass *RC,
                            unsigned Op0, bool Op0IsKill);
    unsigned fastEmitInst_rr(unsigned MachineInstOpcode,
                             const TargetRegisterClass *RC,
                             unsigned Op0, bool Op0IsKill,
                             unsigned Op1, bool Op1IsKill);
    unsigned fastEmitInst_ri(unsigned MachineInstOpcode,
                             const TargetRegisterClass *RC,
                             unsigned Op0, bool Op0IsKill,
                             uint64_t Imm);
    unsigned fastEmitInst_i(unsigned MachineInstOpcode,
                            const TargetRegisterClass *RC,
                            uint64_t Imm);

    // Backend specific FastISel code.

    bool fastSelectInstruction(const Instruction *I) override;
    unsigned fastMaterializeConstant(const Constant *C) override;
    unsigned fastMaterializeAlloca(const AllocaInst *AI) override;
    bool tryToFoldLoadIntoMI(MachineInstr *MI, unsigned OpNo,
                             const LoadInst *LI) override;
    bool fastLowerArguments() override;

  #include "ARMGenFastISel.inc"

    // Instruction selection routines.

    bool SelectLoad(const Instruction *I);
    bool SelectStore(const Instruction *I);
    bool SelectBranch(const Instruction *I);
    bool SelectIndirectBr(const Instruction *I);
    bool SelectCmp(const Instruction *I);
    bool SelectFPExt(const Instruction *I);
    bool SelectFPTrunc(const Instruction *I);
    bool SelectBinaryIntOp(const Instruction *I, unsigned ISDOpcode);
    bool SelectBinaryFPOp(const Instruction *I, unsigned ISDOpcode);
    bool SelectIToFP(const Instruction *I, bool isSigned);
    bool SelectFPToI(const Instruction *I, bool isSigned);
    bool SelectDiv(const Instruction *I, bool isSigned);
    bool SelectRem(const Instruction *I, bool isSigned);
    bool SelectCall(const Instruction *I, const char *IntrMemName);
    bool SelectIntrinsicCall(const IntrinsicInst &I);
    bool SelectSelect(const Instruction *I);
    bool SelectRet(const Instruction *I);
    bool SelectTrunc(const Instruction *I);
    bool SelectIntExt(const Instruction *I);
    bool SelectShift(const Instruction *I, ARM_AM::ShiftOpc ShiftTy);

    // Utility routines.

    bool isPositionIndependent() const;
    bool isTypeLegal(Type *Ty, MVT &VT);
    bool isLoadTypeLegal(Type *Ty, MVT &VT);
    bool ARMEmitCmp(const Value *Src1Value, const Value *Src2Value,
                    bool isZExt, bool isEquality);
    bool ARMEmitLoad(MVT VT, unsigned &ResultReg, Address &Addr,
                     unsigned Alignment = 0, bool isZExt = true,
                     bool allocReg = true);
    bool ARMEmitStore(MVT VT, unsigned SrcReg, Address &Addr,
                      unsigned Alignment = 0);
    bool ARMComputeAddress(const Value *Obj, Address &Addr);
    void ARMSimplifyAddress(Address &Addr, MVT VT, bool useAM3);
    bool ARMIsMemCpySmall(uint64_t Len);
    bool ARMTryEmitSmallMemCpy(Address Dest, Address Src, uint64_t Len,
                               unsigned Alignment);
    unsigned ARMEmitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, bool isZExt);
    unsigned ARMMaterializeFP(const ConstantFP *CFP, MVT VT);
    unsigned ARMMaterializeInt(const Constant *C, MVT VT);
    unsigned ARMMaterializeGV(const GlobalValue *GV, MVT VT);
    unsigned ARMMoveToFPReg(MVT VT, unsigned SrcReg);
    unsigned ARMMoveToIntReg(MVT VT, unsigned SrcReg);
    unsigned ARMSelectCallOp(bool UseReg);
    unsigned ARMLowerPICELF(const GlobalValue *GV, unsigned Align, MVT VT);

    const TargetLowering *getTargetLowering() { return &TLI; }

    // Call handling routines.

    CCAssignFn *CCAssignFnForCall(CallingConv::ID CC,
                                  bool Return,
                                  bool isVarArg);
    bool ProcessCallArgs(SmallVectorImpl<Value*> &Args,
                         SmallVectorImpl<unsigned> &ArgRegs,
                         SmallVectorImpl<MVT> &ArgVTs,
                         SmallVectorImpl<ISD::ArgFlagsTy> &ArgFlags,
                         SmallVectorImpl<unsigned> &RegArgs,
                         CallingConv::ID CC,
                         unsigned &NumBytes,
                         bool isVarArg);
    unsigned getLibcallReg(const Twine &Name);
    bool FinishCall(MVT RetVT, SmallVectorImpl<unsigned> &UsedRegs,
                    const Instruction *I, CallingConv::ID CC,
                    unsigned &NumBytes, bool isVarArg);
    bool ARMEmitLibcall(const Instruction *I, RTLIB::Libcall Call);

    // OptionalDef handling routines.

    bool isARMNEONPred(const MachineInstr *MI);
    bool DefinesOptionalPredicate(MachineInstr *MI, bool *CPSR);
    const MachineInstrBuilder &AddOptionalDefs(const MachineInstrBuilder &MIB);
    void AddLoadStoreOperands(MVT VT, Address &Addr,
                              const MachineInstrBuilder &MIB,
                              MachineMemOperand::Flags Flags, bool useAM3);
};

} // end anonymous namespace

// DefinesOptionalPredicate - This is different from DefinesPredicate in that
// we don't care about implicit defs here, just places we'll need to add a
// default CCReg argument. Sets CPSR if we're setting CPSR instead of CCR.
bool ARMFastISel::DefinesOptionalPredicate(MachineInstr *MI, bool *CPSR) {
  if (!MI->hasOptionalDef())
    return false;

  // Look to see if our OptionalDef is defining CPSR or CCR.
  for (const MachineOperand &MO : MI->operands()) {
    if (!MO.isReg() || !MO.isDef()) continue;
    if (MO.getReg() == ARM::CPSR)
      *CPSR = true;
  }
  return true;
}

bool ARMFastISel::isARMNEONPred(const MachineInstr *MI) {
  const MCInstrDesc &MCID = MI->getDesc();

  // If we're a thumb2 or not NEON function we'll be handled via isPredicable.
  if ((MCID.TSFlags & ARMII::DomainMask) != ARMII::DomainNEON ||
       AFI->isThumb2Function())
    return MI->isPredicable();

  for (const MCOperandInfo &opInfo : MCID.operands())
    if (opInfo.isPredicate())
      return true;

  return false;
}

// If the machine is predicable go ahead and add the predicate operands, if
// it needs default CC operands add those.
// TODO: If we want to support thumb1 then we'll need to deal with optional
// CPSR defs that need to be added before the remaining operands. See s_cc_out
// for descriptions why.
const MachineInstrBuilder &
ARMFastISel::AddOptionalDefs(const MachineInstrBuilder &MIB) {
  MachineInstr *MI = &*MIB;

  // Do we use a predicate? or...
  // Are we NEON in ARM mode and have a predicate operand? If so, I know
  // we're not predicable but add it anyways.
  if (isARMNEONPred(MI))
    MIB.add(predOps(ARMCC::AL));

  // Do we optionally set a predicate?  Preds is size > 0 iff the predicate
  // defines CPSR. All other OptionalDefines in ARM are the CCR register.
  bool CPSR = false;
  if (DefinesOptionalPredicate(MI, &CPSR))
    MIB.add(CPSR ? t1CondCodeOp() : condCodeOp());
  return MIB;
}

unsigned ARMFastISel::fastEmitInst_r(unsigned MachineInstOpcode,
                                     const TargetRegisterClass *RC,
                                     unsigned Op0, bool Op0IsKill) {
  unsigned ResultReg = createResultReg(RC);
  const MCInstrDesc &II = TII.get(MachineInstOpcode);

  // Make sure the input operand is sufficiently constrained to be legal
  // for this instruction.
  Op0 = constrainOperandRegClass(II, Op0, 1);
  if (II.getNumDefs() >= 1) {
    AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II,
                            ResultReg).addReg(Op0, Op0IsKill * RegState::Kill));
  } else {
    AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II)
                   .addReg(Op0, Op0IsKill * RegState::Kill));
    AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
                   TII.get(TargetOpcode::COPY), ResultReg)
                   .addReg(II.ImplicitDefs[0]));
  }
  return ResultReg;
}

unsigned ARMFastISel::fastEmitInst_rr(unsigned MachineInstOpcode,
                                      const TargetRegisterClass *RC,
                                      unsigned Op0, bool Op0IsKill,
                                      unsigned Op1, bool Op1IsKill) {
  unsigned ResultReg = createResultReg(RC);
  const MCInstrDesc &II = TII.get(MachineInstOpcode);

  // Make sure the input operands are sufficiently constrained to be legal
  // for this instruction.
  Op0 = constrainOperandRegClass(II, Op0, 1);
  Op1 = constrainOperandRegClass(II, Op1, 2);

  if (II.getNumDefs() >= 1) {
    AddOptionalDefs(
        BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II, ResultReg)
            .addReg(Op0, Op0IsKill * RegState::Kill)
            .addReg(Op1, Op1IsKill * RegState::Kill));
  } else {
    AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II)
                   .addReg(Op0, Op0IsKill * RegState::Kill)
                   .addReg(Op1, Op1IsKill * RegState::Kill));
    AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
                           TII.get(TargetOpcode::COPY), ResultReg)
                   .addReg(II.ImplicitDefs[0]));
  }
  return ResultReg;
}

unsigned ARMFastISel::fastEmitInst_ri(unsigned MachineInstOpcode,
                                      const TargetRegisterClass *RC,
                                      unsigned Op0, bool Op0IsKill,
                                      uint64_t Imm) {
  unsigned ResultReg = createResultReg(RC);
  const MCInstrDesc &II = TII.get(MachineInstOpcode);

  // Make sure the input operand is sufficiently constrained to be legal
  // for this instruction.
  Op0 = constrainOperandRegClass(II, Op0, 1);
  if (II.getNumDefs() >= 1) {
    AddOptionalDefs(
        BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II, ResultReg)
            .addReg(Op0, Op0IsKill * RegState::Kill)
            .addImm(Imm));
  } else {
    AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II)
                   .addReg(Op0, Op0IsKill * RegState::Kill)
                   .addImm(Imm));
    AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
                           TII.get(TargetOpcode::COPY), ResultReg)
                   .addReg(II.ImplicitDefs[0]));
  }
  return ResultReg;
}

unsigned ARMFastISel::fastEmitInst_i(unsigned MachineInstOpcode,
                                     const TargetRegisterClass *RC,
                                     uint64_t Imm) {
  unsigned ResultReg = createResultReg(RC);
  const MCInstrDesc &II = TII.get(MachineInstOpcode);

  if (II.getNumDefs() >= 1) {
    AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II,
                            ResultReg).addImm(Imm));
  } else {
    AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II)
                   .addImm(Imm));
    AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
                           TII.get(TargetOpcode::COPY), ResultReg)
                   .addReg(II.ImplicitDefs[0]));
  }
  return ResultReg;
}

// TODO: Don't worry about 64-bit now, but when this is fixed remove the
// checks from the various callers.
unsigned ARMFastISel::ARMMoveToFPReg(MVT VT, unsigned SrcReg) {
  if (VT == MVT::f64) return 0;

  unsigned MoveReg = createResultReg(TLI.getRegClassFor(VT));
  AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
                          TII.get(ARM::VMOVSR), MoveReg)
                  .addReg(SrcReg));
  return MoveReg;
}

unsigned ARMFastISel::ARMMoveToIntReg(MVT VT, unsigned SrcReg) {
  if (VT == MVT::i64) return 0;

  unsigned MoveReg = createResultReg(TLI.getRegClassFor(VT));
  AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
                          TII.get(ARM::VMOVRS), MoveReg)
                  .addReg(SrcReg));
  return MoveReg;
}

// For double width floating point we need to materialize two constants
// (the high and the low) into integer registers then use a move to get
// the combined constant into an FP reg.
unsigned ARMFastISel::ARMMaterializeFP(const ConstantFP *CFP, MVT VT) {
  const APFloat Val = CFP->getValueAPF();
  bool is64bit = VT == MVT::f64;

  // This checks to see if we can use VFP3 instructions to materialize
  // a constant, otherwise we have to go through the constant pool.
  if (TLI.isFPImmLegal(Val, VT)) {
    int Imm;
    unsigned Opc;
    if (is64bit) {
      Imm = ARM_AM::getFP64Imm(Val);
      Opc = ARM::FCONSTD;
    } else {
      Imm = ARM_AM::getFP32Imm(Val);
      Opc = ARM::FCONSTS;
    }
    unsigned DestReg = createResultReg(TLI.getRegClassFor(VT));
    AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
                            TII.get(Opc), DestReg).addImm(Imm));
    return DestReg;
  }

  // Require VFP2 for loading fp constants.
  if (!Subtarget->hasVFP2Base()) return false;

  // MachineConstantPool wants an explicit alignment.
  unsigned Align = DL.getPrefTypeAlignment(CFP->getType());
  if (Align == 0) {
    // TODO: Figure out if this is correct.
    Align = DL.getTypeAllocSize(CFP->getType());
  }
  unsigned Idx = MCP.getConstantPoolIndex(cast<Constant>(CFP), Align);
  unsigned DestReg = createResultReg(TLI.getRegClassFor(VT));
  unsigned Opc = is64bit ? ARM::VLDRD : ARM::VLDRS;

  // The extra reg is for addrmode5.
  AddOptionalDefs(
      BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), DestReg)
          .addConstantPoolIndex(Idx)
          .addReg(0));
  return DestReg;
}

unsigned ARMFastISel::ARMMaterializeInt(const Constant *C, MVT VT) {
  if (VT != MVT::i32 && VT != MVT::i16 && VT != MVT::i8 && VT != MVT::i1)
    return 0;

  // If we can do this in a single instruction without a constant pool entry
  // do so now.
  const ConstantInt *CI = cast<ConstantInt>(C);
  if (Subtarget->hasV6T2Ops() && isUInt<16>(CI->getZExtValue())) {
    unsigned Opc = isThumb2 ? ARM::t2MOVi16 : ARM::MOVi16;
    const TargetRegisterClass *RC = isThumb2 ? &ARM::rGPRRegClass :
      &ARM::GPRRegClass;
    unsigned ImmReg = createResultReg(RC);
    AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
                            TII.get(Opc), ImmReg)
                    .addImm(CI->getZExtValue()));
    return ImmReg;
  }

  // Use MVN to emit negative constants.
  if (VT == MVT::i32 && Subtarget->hasV6T2Ops() && CI->isNegative()) {
    unsigned Imm = (unsigned)~(CI->getSExtValue());
    bool UseImm = isThumb2 ? (ARM_AM::getT2SOImmVal(Imm) != -1) :
      (ARM_AM::getSOImmVal(Imm) != -1);
    if (UseImm) {
      unsigned Opc = isThumb2 ? ARM::t2MVNi : ARM::MVNi;
      const TargetRegisterClass *RC = isThumb2 ? &ARM::rGPRRegClass :
                                                 &ARM::GPRRegClass;
      unsigned ImmReg = createResultReg(RC);
      AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
                              TII.get(Opc), ImmReg)
                      .addImm(Imm));
      return ImmReg;
    }
  }

  unsigned ResultReg = 0;
  if (Subtarget->useMovt())
    ResultReg = fastEmit_i(VT, VT, ISD::Constant, CI->getZExtValue());

  if (ResultReg)
    return ResultReg;

  // Load from constant pool.  For now 32-bit only.
  if (VT != MVT::i32)
    return 0;

  // MachineConstantPool wants an explicit alignment.
  unsigned Align = DL.getPrefTypeAlignment(C->getType());
  if (Align == 0) {
    // TODO: Figure out if this is correct.
    Align = DL.getTypeAllocSize(C->getType());
  }
  unsigned Idx = MCP.getConstantPoolIndex(C, Align);
  ResultReg = createResultReg(TLI.getRegClassFor(VT));
  if (isThumb2)
    AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
                            TII.get(ARM::t2LDRpci), ResultReg)
                      .addConstantPoolIndex(Idx));
  else {
    // The extra immediate is for addrmode2.
    ResultReg = constrainOperandRegClass(TII.get(ARM::LDRcp), ResultReg, 0);
    AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
                            TII.get(ARM::LDRcp), ResultReg)
                      .addConstantPoolIndex(Idx)
                      .addImm(0));
  }
  return ResultReg;
}

bool ARMFastISel::isPositionIndependent() const {
  return TLI.isPositionIndependent();
}

unsigned ARMFastISel::ARMMaterializeGV(const GlobalValue *GV, MVT VT) {
  // For now 32-bit only.
  if (VT != MVT::i32 || GV->isThreadLocal()) return 0;

  // ROPI/RWPI not currently supported.
  if (Subtarget->isROPI() || Subtarget->isRWPI())
    return 0;

  bool IsIndirect = Subtarget->isGVIndirectSymbol(GV);
  const TargetRegisterClass *RC = isThumb2 ? &ARM::rGPRRegClass
                                           : &ARM::GPRRegClass;
  unsigned DestReg = createResultReg(RC);

  // FastISel TLS support on non-MachO is broken, punt to SelectionDAG.
  const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV);
  bool IsThreadLocal = GVar && GVar->isThreadLocal();
  if (!Subtarget->isTargetMachO() && IsThreadLocal) return 0;

  bool IsPositionIndependent = isPositionIndependent();
  // Use movw+movt when possible, it avoids constant pool entries.
  // Non-darwin targets only support static movt relocations in FastISel.
  if (Subtarget->useMovt() &&
      (Subtarget->isTargetMachO() || !IsPositionIndependent)) {
    unsigned Opc;
    unsigned char TF = 0;
    if (Subtarget->isTargetMachO())
      TF = ARMII::MO_NONLAZY;

    if (IsPositionIndependent)
      Opc = isThumb2 ? ARM::t2MOV_ga_pcrel : ARM::MOV_ga_pcrel;
    else
      Opc = isThumb2 ? ARM::t2MOVi32imm : ARM::MOVi32imm;
    AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
                            TII.get(Opc), DestReg).addGlobalAddress(GV, 0, TF));
  } else {
    // MachineConstantPool wants an explicit alignment.
    unsigned Align = DL.getPrefTypeAlignment(GV->getType());
    if (Align == 0) {
      // TODO: Figure out if this is correct.
      Align = DL.getTypeAllocSize(GV->getType());
    }

    if (Subtarget->isTargetELF() && IsPositionIndependent)
      return ARMLowerPICELF(GV, Align, VT);

    // Grab index.
    unsigned PCAdj = IsPositionIndependent ? (Subtarget->isThumb() ? 4 : 8) : 0;
    unsigned Id = AFI->createPICLabelUId();
    ARMConstantPoolValue *CPV = ARMConstantPoolConstant::Create(GV, Id,
                                                                ARMCP::CPValue,
                                                                PCAdj);
    unsigned Idx = MCP.getConstantPoolIndex(CPV, Align);

    // Load value.
    MachineInstrBuilder MIB;
    if (isThumb2) {
      unsigned Opc = IsPositionIndependent ? ARM::t2LDRpci_pic : ARM::t2LDRpci;
      MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc),
                    DestReg).addConstantPoolIndex(Idx);
      if (IsPositionIndependent)
        MIB.addImm(Id);
      AddOptionalDefs(MIB);
    } else {
      // The extra immediate is for addrmode2.
      DestReg = constrainOperandRegClass(TII.get(ARM::LDRcp), DestReg, 0);
      MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
                    TII.get(ARM::LDRcp), DestReg)
                .addConstantPoolIndex(Idx)
                .addImm(0);
      AddOptionalDefs(MIB);

      if (IsPositionIndependent) {
        unsigned Opc = IsIndirect ? ARM::PICLDR : ARM::PICADD;
        unsigned NewDestReg = createResultReg(TLI.getRegClassFor(VT));

        MachineInstrBuilder MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt,
                                          DbgLoc, TII.get(Opc), NewDestReg)
                                  .addReg(DestReg)
                                  .addImm(Id);
        AddOptionalDefs(MIB);
        return NewDestReg;
      }
    }
  }

  if (IsIndirect) {
    MachineInstrBuilder MIB;
    unsigned NewDestReg = createResultReg(TLI.getRegClassFor(VT));
    if (isThumb2)
      MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
                    TII.get(ARM::t2LDRi12), NewDestReg)
            .addReg(DestReg)
            .addImm(0);
    else
      MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
                    TII.get(ARM::LDRi12), NewDestReg)
                .addReg(DestReg)
                .addImm(0);
    DestReg = NewDestReg;
    AddOptionalDefs(MIB);
  }

  return DestReg;
}

unsigned ARMFastISel::fastMaterializeConstant(const Constant *C) {
  EVT CEVT = TLI.getValueType(DL, C->getType(), true);

  // Only handle simple types.
  if (!CEVT.isSimple()) return 0;
  MVT VT = CEVT.getSimpleVT();

  if (const ConstantFP *CFP = dyn_cast<ConstantFP>(C))
    return ARMMaterializeFP(CFP, VT);
  else if (const GlobalValue *GV = dyn_cast<GlobalValue>(C))
    return ARMMaterializeGV(GV, VT);
  else if (isa<ConstantInt>(C))
    return ARMMaterializeInt(C, VT);

  return 0;
}

// TODO: unsigned ARMFastISel::TargetMaterializeFloatZero(const ConstantFP *CF);

unsigned ARMFastISel::fastMaterializeAlloca(const AllocaInst *AI) {
  // Don't handle dynamic allocas.
  if (!FuncInfo.StaticAllocaMap.count(AI)) return 0;

  MVT VT;
  if (!isLoadTypeLegal(AI->getType(), VT)) return 0;

  DenseMap<const AllocaInst*, int>::iterator SI =
    FuncInfo.StaticAllocaMap.find(AI);

  // This will get lowered later into the correct offsets and registers
  // via rewriteXFrameIndex.
  if (SI != FuncInfo.StaticAllocaMap.end()) {
    unsigned Opc = isThumb2 ? ARM::t2ADDri : ARM::ADDri;
    const TargetRegisterClass* RC = TLI.getRegClassFor(VT);
    unsigned ResultReg = createResultReg(RC);
    ResultReg = constrainOperandRegClass(TII.get(Opc), ResultReg, 0);

    AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
                            TII.get(Opc), ResultReg)
                            .addFrameIndex(SI->second)
                            .addImm(0));
    return ResultReg;
  }

  return 0;
}

bool ARMFastISel::isTypeLegal(Type *Ty, MVT &VT) {
  EVT evt = TLI.getValueType(DL, Ty, true);

  // Only handle simple types.
  if (evt == MVT::Other || !evt.isSimple()) return false;
  VT = evt.getSimpleVT();

  // Handle all legal types, i.e. a register that will directly hold this
  // value.
  return TLI.isTypeLegal(VT);
}

bool ARMFastISel::isLoadTypeLegal(Type *Ty, MVT &VT) {
  if (isTypeLegal(Ty, VT)) return true;

  // If this is a type than can be sign or zero-extended to a basic operation
  // go ahead and accept it now.
  if (VT == MVT::i1 || VT == MVT::i8 || VT == MVT::i16)
    return true;

  return false;
}

// Computes the address to get to an object.
bool ARMFastISel::ARMComputeAddress(const Value *Obj, Address &Addr) {
  // Some boilerplate from the X86 FastISel.
  const User *U = nullptr;
  unsigned Opcode = Instruction::UserOp1;
  if (const Instruction *I = dyn_cast<Instruction>(Obj)) {
    // Don't walk into other basic blocks unless the object is an alloca from
    // another block, otherwise it may not have a virtual register assigned.
    if (FuncInfo.StaticAllocaMap.count(static_cast<const AllocaInst *>(Obj)) ||
        FuncInfo.MBBMap[I->getParent()] == FuncInfo.MBB) {
      Opcode = I->getOpcode();
      U = I;
    }
  } else if (const ConstantExpr *C = dyn_cast<ConstantExpr>(Obj)) {
    Opcode = C->getOpcode();
    U = C;
  }

  if (PointerType *Ty = dyn_cast<PointerType>(Obj->getType()))
    if (Ty->getAddressSpace() > 255)
      // Fast instruction selection doesn't support the special
      // address spaces.
      return false;

  switch (Opcode) {
    default:
    break;
    case Instruction::BitCast:
      // Look through bitcasts.
      return ARMComputeAddress(U->getOperand(0), Addr);
    case Instruction::IntToPtr:
      // Look past no-op inttoptrs.
      if (TLI.getValueType(DL, U->getOperand(0)->getType()) ==
          TLI.getPointerTy(DL))
        return ARMComputeAddress(U->getOperand(0), Addr);
      break;
    case Instruction::PtrToInt:
      // Look past no-op ptrtoints.
      if (TLI.getValueType(DL, U->getType()) == TLI.getPointerTy(DL))
        return ARMComputeAddress(U->getOperand(0), Addr);
      break;
    case Instruction::GetElementPtr: {
      Address SavedAddr = Addr;
      int TmpOffset = Addr.Offset;

      // Iterate through the GEP folding the constants into offsets where
      // we can.
      gep_type_iterator GTI = gep_type_begin(U);
      for (User::const_op_iterator i = U->op_begin() + 1, e = U->op_end();
           i != e; ++i, ++GTI) {
        const Value *Op = *i;
        if (StructType *STy = GTI.getStructTypeOrNull()) {
          const StructLayout *SL = DL.getStructLayout(STy);
          unsigned Idx = cast<ConstantInt>(Op)->getZExtValue();
          TmpOffset += SL->getElementOffset(Idx);
        } else {
          uint64_t S = DL.getTypeAllocSize(GTI.getIndexedType());
          while (true) {
            if (const ConstantInt *CI = dyn_cast<ConstantInt>(Op)) {
              // Constant-offset addressing.
              TmpOffset += CI->getSExtValue() * S;
              break;
            }
            if (canFoldAddIntoGEP(U, Op)) {
              // A compatible add with a constant operand. Fold the constant.
              ConstantInt *CI =
              cast<ConstantInt>(cast<AddOperator>(Op)->getOperand(1));
              TmpOffset += CI->getSExtValue() * S;
              // Iterate on the other operand.
              Op = cast<AddOperator>(Op)->getOperand(0);
              continue;
            }
            // Unsupported
            goto unsupported_gep;
          }
        }
      }

      // Try to grab the base operand now.
      Addr.Offset = TmpOffset;
      if (ARMComputeAddress(U->getOperand(0), Addr)) return true;

      // We failed, restore everything and try the other options.
      Addr = SavedAddr;

      unsupported_gep:
      break;
    }
    case Instruction::Alloca: {
      const AllocaInst *AI = cast<AllocaInst>(Obj);
      DenseMap<const AllocaInst*, int>::iterator SI =
        FuncInfo.StaticAllocaMap.find(AI);
      if (SI != FuncInfo.StaticAllocaMap.end()) {
        Addr.BaseType = Address::FrameIndexBase;
        Addr.Base.FI = SI->second;
        return true;
      }
      break;
    }
  }

  // Try to get this in a register if nothing else has worked.
  if (Addr.Base.Reg == 0) Addr.Base.Reg = getRegForValue(Obj);
  return Addr.Base.Reg != 0;
}

void ARMFastISel::ARMSimplifyAddress(Address &Addr, MVT VT, bool useAM3) {
  bool needsLowering = false;
  switch (VT.SimpleTy) {
    default: llvm_unreachable("Unhandled load/store type!");
    case MVT::i1:
    case MVT::i8:
    case MVT::i16:
    case MVT::i32:
      if (!useAM3) {
        // Integer loads/stores handle 12-bit offsets.
        needsLowering = ((Addr.Offset & 0xfff) != Addr.Offset);
        // Handle negative offsets.
        if (needsLowering && isThumb2)
          needsLowering = !(Subtarget->hasV6T2Ops() && Addr.Offset < 0 &&
                            Addr.Offset > -256);
      } else {
        // ARM halfword load/stores and signed byte loads use +/-imm8 offsets.
        needsLowering = (Addr.Offset > 255 || Addr.Offset < -255);
      }
      break;
    case MVT::f32:
    case MVT::f64:
      // Floating point operands handle 8-bit offsets.
      needsLowering = ((Addr.Offset & 0xff) != Addr.Offset);
      break;
  }

  // If this is a stack pointer and the offset needs to be simplified then
  // put the alloca address into a register, set the base type back to
  // register and continue. This should almost never happen.
  if (needsLowering && Addr.BaseType == Address::FrameIndexBase) {
    const TargetRegisterClass *RC = isThumb2 ? &ARM::tGPRRegClass
                                             : &ARM::GPRRegClass;
    unsigned ResultReg = createResultReg(RC);
    unsigned Opc = isThumb2 ? ARM::t2ADDri : ARM::ADDri;
    AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
                            TII.get(Opc), ResultReg)
                            .addFrameIndex(Addr.Base.FI)
                            .addImm(0));
    Addr.Base.Reg = ResultReg;
    Addr.BaseType = Address::RegBase;
  }

  // Since the offset is too large for the load/store instruction
  // get the reg+offset into a register.
  if (needsLowering) {
    Addr.Base.Reg = fastEmit_ri_(MVT::i32, ISD::ADD, Addr.Base.Reg,
                                 /*Op0IsKill*/false, Addr.Offset, MVT::i32);
    Addr.Offset = 0;
  }
}

void ARMFastISel::AddLoadStoreOperands(MVT VT, Address &Addr,
                                       const MachineInstrBuilder &MIB,
                                       MachineMemOperand::Flags Flags,
                                       bool useAM3) {
  // addrmode5 output depends on the selection dag addressing dividing the
  // offset by 4 that it then later multiplies. Do this here as well.
  if (VT.SimpleTy == MVT::f32 || VT.SimpleTy == MVT::f64)
    Addr.Offset /= 4;

  // Frame base works a bit differently. Handle it separately.
  if (Addr.BaseType == Address::FrameIndexBase) {
    int FI = Addr.Base.FI;
    int Offset = Addr.Offset;
    MachineMemOperand *MMO = FuncInfo.MF->getMachineMemOperand(
        MachinePointerInfo::getFixedStack(*FuncInfo.MF, FI, Offset), Flags,
        MFI.getObjectSize(FI), MFI.getObjectAlignment(FI));
    // Now add the rest of the operands.
    MIB.addFrameIndex(FI);

    // ARM halfword load/stores and signed byte loads need an additional
    // operand.
    if (useAM3) {
      int Imm = (Addr.Offset < 0) ? (0x100 | -Addr.Offset) : Addr.Offset;
      MIB.addReg(0);
      MIB.addImm(Imm);
    } else {
      MIB.addImm(Addr.Offset);
    }
    MIB.addMemOperand(MMO);
  } else {
    // Now add the rest of the operands.
    MIB.addReg(Addr.Base.Reg);

    // ARM halfword load/stores and signed byte loads need an additional
    // operand.
    if (useAM3) {
      int Imm = (Addr.Offset < 0) ? (0x100 | -Addr.Offset) : Addr.Offset;
      MIB.addReg(0);
      MIB.addImm(Imm);
    } else {
      MIB.addImm(Addr.Offset);
    }
  }
  AddOptionalDefs(MIB);
}

bool ARMFastISel::ARMEmitLoad(MVT VT, unsigned &ResultReg, Address &Addr,
                              unsigned Alignment, bool isZExt, bool allocReg) {
  unsigned Opc;
  bool useAM3 = false;
  bool needVMOV = false;
  const TargetRegisterClass *RC;
  switch (VT.SimpleTy) {
    // This is mostly going to be Neon/vector support.
    default: return false;
    case MVT::i1:
    case MVT::i8:
      if (isThumb2) {
        if (Addr.Offset < 0 && Addr.Offset > -256 && Subtarget->hasV6T2Ops())
          Opc = isZExt ? ARM::t2LDRBi8 : ARM::t2LDRSBi8;
        else
          Opc = isZExt ? ARM::t2LDRBi12 : ARM::t2LDRSBi12;
      } else {
        if (isZExt) {
          Opc = ARM::LDRBi12;
        } else {
          Opc = ARM::LDRSB;
          useAM3 = true;
        }
      }
      RC = isThumb2 ? &ARM::rGPRRegClass : &ARM::GPRnopcRegClass;
      break;
    case MVT::i16:
      if (Alignment && Alignment < 2 && !Subtarget->allowsUnalignedMem())
        return false;

      if (isThumb2) {
        if (Addr.Offset < 0 && Addr.Offset > -256 && Subtarget->hasV6T2Ops())
          Opc = isZExt ? ARM::t2LDRHi8 : ARM::t2LDRSHi8;
        else
          Opc = isZExt ? ARM::t2LDRHi12 : ARM::t2LDRSHi12;
      } else {
        Opc = isZExt ? ARM::LDRH : ARM::LDRSH;
        useAM3 = true;
      }
      RC = isThumb2 ? &ARM::rGPRRegClass : &ARM::GPRnopcRegClass;
      break;
    case MVT::i32:
      if (Alignment && Alignment < 4 && !Subtarget->allowsUnalignedMem())
        return false;

      if (isThumb2) {
        if (Addr.Offset < 0 && Addr.Offset > -256 && Subtarget->hasV6T2Ops())
          Opc = ARM::t2LDRi8;
        else
          Opc = ARM::t2LDRi12;
      } else {
        Opc = ARM::LDRi12;
      }
      RC = isThumb2 ? &ARM::rGPRRegClass : &ARM::GPRnopcRegClass;
      break;
    case MVT::f32:
      if (!Subtarget->hasVFP2Base()) return false;
      // Unaligned loads need special handling. Floats require word-alignment.
      if (Alignment && Alignment < 4) {
        needVMOV = true;
        VT = MVT::i32;
        Opc = isThumb2 ? ARM::t2LDRi12 : ARM::LDRi12;
        RC = isThumb2 ? &ARM::rGPRRegClass : &ARM::GPRnopcRegClass;
      } else {
        Opc = ARM::VLDRS;
        RC = TLI.getRegClassFor(VT);
      }
      break;
    case MVT::f64:
      // Can load and store double precision even without FeatureFP64
      if (!Subtarget->hasVFP2Base()) return false;
      // FIXME: Unaligned loads need special handling.  Doublewords require
      // word-alignment.
      if (Alignment && Alignment < 4)
        return false;

      Opc = ARM::VLDRD;
      RC = TLI.getRegClassFor(VT);
      break;
  }
  // Simplify this down to something we can handle.
  ARMSimplifyAddress(Addr, VT, useAM3);

  // Create the base instruction, then add the operands.
  if (allocReg)
    ResultReg = createResultReg(RC);
  assert(ResultReg > 255 && "Expected an allocated virtual register.");
  MachineInstrBuilder MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
                                    TII.get(Opc), ResultReg);
  AddLoadStoreOperands(VT, Addr, MIB, MachineMemOperand::MOLoad, useAM3);

  // If we had an unaligned load of a float we've converted it to an regular
  // load.  Now we must move from the GRP to the FP register.
  if (needVMOV) {
    unsigned MoveReg = createResultReg(TLI.getRegClassFor(MVT::f32));
    AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
                            TII.get(ARM::VMOVSR), MoveReg)
                    .addReg(ResultReg));
    ResultReg = MoveReg;
  }
  return true;
}

bool ARMFastISel::SelectLoad(const Instruction *I) {
  // Atomic loads need special handling.
  if (cast<LoadInst>(I)->isAtomic())
    return false;

  const Value *SV = I->getOperand(0);
  if (TLI.supportSwiftError()) {
    // Swifterror values can come from either a function parameter with
    // swifterror attribute or an alloca with swifterror attribute.
    if (const Argument *Arg = dyn_cast<Argument>(SV)) {
      if (Arg->hasSwiftErrorAttr())
        return false;
    }

    if (const AllocaInst *Alloca = dyn_cast<AllocaInst>(SV)) {
      if (Alloca->isSwiftError())
        return false;
    }
  }

  // Verify we have a legal type before going any further.
  MVT VT;
  if (!isLoadTypeLegal(I->getType(), VT))
    return false;

  // See if we can handle this address.
  Address Addr;
  if (!ARMComputeAddress(I->getOperand(0), Addr)) return false;

  unsigned ResultReg;
  if (!ARMEmitLoad(VT, ResultReg, Addr, cast<LoadInst>(I)->getAlignment()))
    return false;
  updateValueMap(I, ResultReg);
  return true;
}

bool ARMFastISel::ARMEmitStore(MVT VT, unsigned SrcReg, Address &Addr,
                               unsigned Alignment) {
  unsigned StrOpc;
  bool useAM3 = false;
  switch (VT.SimpleTy) {
    // This is mostly going to be Neon/vector support.
    default: return false;
    case MVT::i1: {
      unsigned Res = createResultReg(isThumb2 ? &ARM::tGPRRegClass
                                              : &ARM::GPRRegClass);
      unsigned Opc = isThumb2 ? ARM::t2ANDri : ARM::ANDri;
      SrcReg = constrainOperandRegClass(TII.get(Opc), SrcReg, 1);
      AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
                              TII.get(Opc), Res)
                      .addReg(SrcReg).addImm(1));
      SrcReg = Res;
      LLVM_FALLTHROUGH;
    }
    case MVT::i8:
      if (isThumb2) {
        if (Addr.Offset < 0 && Addr.Offset > -256 && Subtarget->hasV6T2Ops())
          StrOpc = ARM::t2STRBi8;
        else
          StrOpc = ARM::t2STRBi12;
      } else {
        StrOpc = ARM::STRBi12;
      }
      break;
    case MVT::i16:
      if (Alignment && Alignment < 2 && !Subtarget->allowsUnalignedMem())
        return false;

      if (isThumb2) {
        if (Addr.Offset < 0 && Addr.Offset > -256 && Subtarget->hasV6T2Ops())
          StrOpc = ARM::t2STRHi8;
        else
          StrOpc = ARM::t2STRHi12;
      } else {
        StrOpc = ARM::STRH;
        useAM3 = true;
      }
      break;
    case MVT::i32:
      if (Alignment && Alignment < 4 && !Subtarget->allowsUnalignedMem())
        return false;

      if (isThumb2) {
        if (Addr.Offset < 0 && Addr.Offset > -256 && Subtarget->hasV6T2Ops())
          StrOpc = ARM::t2STRi8;
        else
          StrOpc = ARM::t2STRi12;
      } else {
        StrOpc = ARM::STRi12;
      }
      break;
    case MVT::f32:
      if (!Subtarget->hasVFP2Base()) return false;
      // Unaligned stores need special handling. Floats require word-alignment.
      if (Alignment && Alignment < 4) {
        unsigned MoveReg = createResultReg(TLI.getRegClassFor(MVT::i32));
        AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
                                TII.get(ARM::VMOVRS), MoveReg)
                        .addReg(SrcReg));
        SrcReg = MoveReg;
        VT = MVT::i32;
        StrOpc = isThumb2 ? ARM::t2STRi12 : ARM::STRi12;
      } else {
        StrOpc = ARM::VSTRS;
      }
      break;
    case MVT::f64:
      // Can load and store double precision even without FeatureFP64
      if (!Subtarget->hasVFP2Base()) return false;
      // FIXME: Unaligned stores need special handling.  Doublewords require
      // word-alignment.
      if (Alignment && Alignment < 4)
          return false;

      StrOpc = ARM::VSTRD;
      break;
  }
  // Simplify this down to something we can handle.
  ARMSimplifyAddress(Addr, VT, useAM3);

  // Create the base instruction, then add the operands.
  SrcReg = constrainOperandRegClass(TII.get(StrOpc), SrcReg, 0);
  MachineInstrBuilder MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
                                    TII.get(StrOpc))
                            .addReg(SrcReg);
  AddLoadStoreOperands(VT, Addr, MIB, MachineMemOperand::MOStore, useAM3);
  return true;
}

bool ARMFastISel::SelectStore(const Instruction *I) {
  Value *Op0 = I->getOperand(0);
  unsigned SrcReg = 0;

  // Atomic stores need special handling.
  if (cast<StoreInst>(I)->isAtomic())
    return false;

  const Value *PtrV = I->getOperand(1);
  if (TLI.supportSwiftError()) {
    // Swifterror values can come from either a function parameter with
    // swifterror attribute or an alloca with swifterror attribute.
    if (const Argument *Arg = dyn_cast<Argument>(PtrV)) {
      if (Arg->hasSwiftErrorAttr())
        return false;
    }

    if (const AllocaInst *Alloca = dyn_cast<AllocaInst>(PtrV)) {
      if (Alloca->isSwiftError())
        return false;
    }
  }

  // Verify we have a legal type before going any further.
  MVT VT;
  if (!isLoadTypeLegal(I->getOperand(0)->getType(), VT))
    return false;

  // Get the value to be stored into a register.
  SrcReg = getRegForValue(Op0);
  if (SrcReg == 0) return false;

  // See if we can handle this address.
  Address Addr;
  if (!ARMComputeAddress(I->getOperand(1), Addr))
    return false;

  if (!ARMEmitStore(VT, SrcReg, Addr, cast<StoreInst>(I)->getAlignment()))
    return false;
  return true;
}

static ARMCC::CondCodes getComparePred(CmpInst::Predicate Pred) {
  switch (Pred) {
    // Needs two compares...
    case CmpInst::FCMP_ONE:
    case CmpInst::FCMP_UEQ:
    default:
      // AL is our "false" for now. The other two need more compares.
      return ARMCC::AL;
    case CmpInst::ICMP_EQ:
    case CmpInst::FCMP_OEQ:
      return ARMCC::EQ;
    case CmpInst::ICMP_SGT:
    case CmpInst::FCMP_OGT:
      return ARMCC::GT;
    case CmpInst::ICMP_SGE:
    case CmpInst::FCMP_OGE:
      return ARMCC::GE;
    case CmpInst::ICMP_UGT:
    case CmpInst::FCMP_UGT:
      return ARMCC::HI;
    case CmpInst::FCMP_OLT:
      return ARMCC::MI;
    case CmpInst::ICMP_ULE:
    case CmpInst::FCMP_OLE:
      return ARMCC::LS;
    case CmpInst::FCMP_ORD:
      return ARMCC::VC;
    case CmpInst::FCMP_UNO:
      return ARMCC::VS;
    case CmpInst::FCMP_UGE:
      return ARMCC::PL;
    case CmpInst::ICMP_SLT:
    case CmpInst::FCMP_ULT:
      return ARMCC::LT;
    case CmpInst::ICMP_SLE:
    case CmpInst::FCMP_ULE:
      return ARMCC::LE;
    case CmpInst::FCMP_UNE:
    case CmpInst::ICMP_NE:
      return ARMCC::NE;
    case CmpInst::ICMP_UGE:
      return ARMCC::HS;
    case CmpInst::ICMP_ULT:
      return ARMCC::LO;
  }
}

bool ARMFastISel::SelectBranch(const Instruction *I) {
  const BranchInst *BI = cast<BranchInst>(I);
  MachineBasicBlock *TBB = FuncInfo.MBBMap[BI->getSuccessor(0)];
  MachineBasicBlock *FBB = FuncInfo.MBBMap[BI->getSuccessor(1)];

  // Simple branch support.

  // If we can, avoid recomputing the compare - redoing it could lead to wonky
  // behavior.
  if (const CmpInst *CI = dyn_cast<CmpInst>(BI->getCondition())) {
    if (CI->hasOneUse() && (CI->getParent() == I->getParent())) {
      // Get the compare predicate.
      // Try to take advantage of fallthrough opportunities.
      CmpInst::Predicate Predicate = CI->getPredicate();
      if (FuncInfo.MBB->isLayoutSuccessor(TBB)) {
        std::swap(TBB, FBB);
        Predicate = CmpInst::getInversePredicate(Predicate);
      }

      ARMCC::CondCodes ARMPred = getComparePred(Predicate);

      // We may not handle every CC for now.
      if (ARMPred == ARMCC::AL) return false;

      // Emit the compare.
      if (!ARMEmitCmp(CI->getOperand(0), CI->getOperand(1), CI->isUnsigned(),
                      CI->isEquality()))
        return false;

      unsigned BrOpc = isThumb2 ? ARM::t2Bcc : ARM::Bcc;
      BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(BrOpc))
      .addMBB(TBB).addImm(ARMPred).addReg(ARM::CPSR);
      finishCondBranch(BI->getParent(), TBB, FBB);
      return true;
    }
  } else if (TruncInst *TI = dyn_cast<TruncInst>(BI->getCondition())) {
    MVT SourceVT;
    if (TI->hasOneUse() && TI->getParent() == I->getParent() &&
        (isLoadTypeLegal(TI->getOperand(0)->getType(), SourceVT))) {
      unsigned TstOpc = isThumb2 ? ARM::t2TSTri : ARM::TSTri;
      unsigned OpReg = getRegForValue(TI->getOperand(0));
      OpReg = constrainOperandRegClass(TII.get(TstOpc), OpReg, 0);
      AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
                              TII.get(TstOpc))
                      .addReg(OpReg).addImm(1));

      unsigned CCMode = ARMCC::NE;
      if (FuncInfo.MBB->isLayoutSuccessor(TBB)) {
        std::swap(TBB, FBB);
        CCMode = ARMCC::EQ;
      }

      unsigned BrOpc = isThumb2 ? ARM::t2Bcc : ARM::Bcc;
      BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(BrOpc))
      .addMBB(TBB).addImm(CCMode).addReg(ARM::CPSR);

      finishCondBranch(BI->getParent(), TBB, FBB);
      return true;
    }
  } else if (const ConstantInt *CI =
             dyn_cast<ConstantInt>(BI->getCondition())) {
    uint64_t Imm = CI->getZExtValue();
    MachineBasicBlock *Target = (Imm == 0) ? FBB : TBB;
    fastEmitBranch(Target, DbgLoc);
    return true;
  }

  unsigned CmpReg = getRegForValue(BI->getCondition());
  if (CmpReg == 0) return false;

  // We've been divorced from our compare!  Our block was split, and
  // now our compare lives in a predecessor block.  We musn't
  // re-compare here, as the children of the compare aren't guaranteed
  // live across the block boundary (we *could* check for this).
  // Regardless, the compare has been done in the predecessor block,
  // and it left a value for us in a virtual register.  Ergo, we test
  // the one-bit value left in the virtual register.
  unsigned TstOpc = isThumb2 ? ARM::t2TSTri : ARM::TSTri;
  CmpReg = constrainOperandRegClass(TII.get(TstOpc), CmpReg, 0);
  AddOptionalDefs(
      BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(TstOpc))
          .addReg(CmpReg)
          .addImm(1));

  unsigned CCMode = ARMCC::NE;
  if (FuncInfo.MBB->isLayoutSuccessor(TBB)) {
    std::swap(TBB, FBB);
    CCMode = ARMCC::EQ;
  }

  unsigned BrOpc = isThumb2 ? ARM::t2Bcc : ARM::Bcc;
  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(BrOpc))
                  .addMBB(TBB).addImm(CCMode).addReg(ARM::CPSR);
  finishCondBranch(BI->getParent(), TBB, FBB);
  return true;
}

bool ARMFastISel::SelectIndirectBr(const Instruction *I) {
  unsigned AddrReg = getRegForValue(I->getOperand(0));
  if (AddrReg == 0) return false;

  unsigned Opc = isThumb2 ? ARM::tBRIND : ARM::BX;
  assert(isThumb2 || Subtarget->hasV4TOps());

  AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
                          TII.get(Opc)).addReg(AddrReg));

  const IndirectBrInst *IB = cast<IndirectBrInst>(I);
  for (const BasicBlock *SuccBB : IB->successors())
    FuncInfo.MBB->addSuccessor(FuncInfo.MBBMap[SuccBB]);

  return true;
}

bool ARMFastISel::ARMEmitCmp(const Value *Src1Value, const Value *Src2Value,
                             bool isZExt, bool isEquality) {
  Type *Ty = Src1Value->getType();
  EVT SrcEVT = TLI.getValueType(DL, Ty, true);
  if (!SrcEVT.isSimple()) return false;
  MVT SrcVT = SrcEVT.getSimpleVT();

  if (Ty->isFloatTy() && !Subtarget->hasVFP2Base())
    return false;

  if (Ty->isDoubleTy() && (!Subtarget->hasVFP2Base() || !Subtarget->hasFP64()))
    return false;

  // Check to see if the 2nd operand is a constant that we can encode directly
  // in the compare.
  int Imm = 0;
  bool UseImm = false;
  bool isNegativeImm = false;
  // FIXME: At -O0 we don't have anything that canonicalizes operand order.
  // Thus, Src1Value may be a ConstantInt, but we're missing it.
  if (const ConstantInt *ConstInt = dyn_cast<ConstantInt>(Src2Value)) {
    if (SrcVT == MVT::i32 || SrcVT == MVT::i16 || SrcVT == MVT::i8 ||
        SrcVT == MVT::i1) {
      const APInt &CIVal = ConstInt->getValue();
      Imm = (isZExt) ? (int)CIVal.getZExtValue() : (int)CIVal.getSExtValue();
      // For INT_MIN/LONG_MIN (i.e., 0x80000000) we need to use a cmp, rather
      // then a cmn, because there is no way to represent 2147483648 as a
      // signed 32-bit int.
      if (Imm < 0 && Imm != (int)0x80000000) {
        isNegativeImm = true;
        Imm = -Imm;
      }
      UseImm = isThumb2 ? (ARM_AM::getT2SOImmVal(Imm) != -1) :
        (ARM_AM::getSOImmVal(Imm) != -1);
    }
  } else if (const ConstantFP *ConstFP = dyn_cast<ConstantFP>(Src2Value)) {
    if (SrcVT == MVT::f32 || SrcVT == MVT::f64)
      if (ConstFP->isZero() && !ConstFP->isNegative())
        UseImm = true;
  }

  unsigned CmpOpc;
  bool isICmp = true;
  bool needsExt = false;
  switch (SrcVT.SimpleTy) {
    default: return false;
    // TODO: Verify compares.
    case MVT::f32:
      isICmp = false;
      // Equality comparisons shouldn't raise Invalid on uordered inputs.
      if (isEquality)
        CmpOpc = UseImm ? ARM::VCMPZS : ARM::VCMPS;
      else
        CmpOpc = UseImm ? ARM::VCMPEZS : ARM::VCMPES;
      break;
    case MVT::f64:
      isICmp = false;
      // Equality comparisons shouldn't raise Invalid on uordered inputs.
      if (isEquality)
        CmpOpc = UseImm ? ARM::VCMPZD : ARM::VCMPD;
      else
      CmpOpc = UseImm ? ARM::VCMPEZD : ARM::VCMPED;
      break;
    case MVT::i1:
    case MVT::i8:
    case MVT::i16:
      needsExt = true;
      LLVM_FALLTHROUGH;
    case MVT::i32:
      if (isThumb2) {
        if (!UseImm)
          CmpOpc = ARM::t2CMPrr;
        else
          CmpOpc = isNegativeImm ? ARM::t2CMNri : ARM::t2CMPri;
      } else {
        if (!UseImm)
          CmpOpc = ARM::CMPrr;
        else
          CmpOpc = isNegativeImm ? ARM::CMNri : ARM::CMPri;
      }
      break;
  }

  unsigned SrcReg1 = getRegForValue(Src1Value);
  if (SrcReg1 == 0) return false;

  unsigned SrcReg2 = 0;
  if (!UseImm) {
    SrcReg2 = getRegForValue(Src2Value);
    if (SrcReg2 == 0) return false;
  }

  // We have i1, i8, or i16, we need to either zero extend or sign extend.
  if (needsExt) {
    SrcReg1 = ARMEmitIntExt(SrcVT, SrcReg1, MVT::i32, isZExt);
    if (SrcReg1 == 0) return false;
    if (!UseImm) {
      SrcReg2 = ARMEmitIntExt(SrcVT, SrcReg2, MVT::i32, isZExt);
      if (SrcReg2 == 0) return false;
    }
  }

  const MCInstrDesc &II = TII.get(CmpOpc);
  SrcReg1 = constrainOperandRegClass(II, SrcReg1, 0);
  if (!UseImm) {
    SrcReg2 = constrainOperandRegClass(II, SrcReg2, 1);
    AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II)
                    .addReg(SrcReg1).addReg(SrcReg2));
  } else {
    MachineInstrBuilder MIB;
    MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II)
      .addReg(SrcReg1);

    // Only add immediate for icmp as the immediate for fcmp is an implicit 0.0.
    if (isICmp)
      MIB.addImm(Imm);
    AddOptionalDefs(MIB);
  }

  // For floating point we need to move the result to a comparison register
  // that we can then use for branches.
  if (Ty->isFloatTy() || Ty->isDoubleTy())
    AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
                            TII.get(ARM::FMSTAT)));
  return true;
}

bool ARMFastISel::SelectCmp(const Instruction *I) {
  const CmpInst *CI = cast<CmpInst>(I);

  // Get the compare predicate.
  ARMCC::CondCodes ARMPred = getComparePred(CI->getPredicate());

  // We may not handle every CC for now.
  if (ARMPred == ARMCC::AL) return false;

  // Emit the compare.
  if (!ARMEmitCmp(CI->getOperand(0), CI->getOperand(1), CI->isUnsigned(),
                  CI->isEquality()))
    return false;

  // Now set a register based on the comparison. Explicitly set the predicates
  // here.
  unsigned MovCCOpc = isThumb2 ? ARM::t2MOVCCi : ARM::MOVCCi;
  const TargetRegisterClass *RC = isThumb2 ? &ARM::rGPRRegClass
                                           : &ARM::GPRRegClass;
  unsigned DestReg = createResultReg(RC);
  Constant *Zero = ConstantInt::get(Type::getInt32Ty(*Context), 0);
  unsigned ZeroReg = fastMaterializeConstant(Zero);
  // ARMEmitCmp emits a FMSTAT when necessary, so it's always safe to use CPSR.
  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(MovCCOpc), DestReg)
          .addReg(ZeroReg).addImm(1)
          .addImm(ARMPred).addReg(ARM::CPSR);

  updateValueMap(I, DestReg);
  return true;
}

bool ARMFastISel::SelectFPExt(const Instruction *I) {
  // Make sure we have VFP and that we're extending float to double.
  if (!Subtarget->hasVFP2Base() || !Subtarget->hasFP64()) return false;

  Value *V = I->getOperand(0);
  if (!I->getType()->isDoubleTy() ||
      !V->getType()->isFloatTy()) return false;

  unsigned Op = getRegForValue(V);
  if (Op == 0) return false;

  unsigned Result = createResultReg(&ARM::DPRRegClass);
  AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
                          TII.get(ARM::VCVTDS), Result)
                  .addReg(Op));
  updateValueMap(I, Result);
  return true;
}

bool ARMFastISel::SelectFPTrunc(const Instruction *I) {
  // Make sure we have VFP and that we're truncating double to float.
  if (!Subtarget->hasVFP2Base() || !Subtarget->hasFP64()) return false;

  Value *V = I->getOperand(0);
  if (!(I->getType()->isFloatTy() &&
        V->getType()->isDoubleTy())) return false;

  unsigned Op = getRegForValue(V);
  if (Op == 0) return false;

  unsigned Result = createResultReg(&ARM::SPRRegClass);
  AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
                          TII.get(ARM::VCVTSD), Result)
                  .addReg(Op));
  updateValueMap(I, Result);
  return true;
}

bool ARMFastISel::SelectIToFP(const Instruction *I, bool isSigned) {
  // Make sure we have VFP.
  if (!Subtarget->hasVFP2Base()) return false;

  MVT DstVT;
  Type *Ty = I->getType();
  if (!isTypeLegal(Ty, DstVT))
    return false;

  Value *Src = I->getOperand(0);
  EVT SrcEVT = TLI.getValueType(DL, Src->getType(), true);
  if (!SrcEVT.isSimple())
    return false;
  MVT SrcVT = SrcEVT.getSimpleVT();
  if (SrcVT != MVT::i32 && SrcVT != MVT::i16 && SrcVT != MVT::i8)
    return false;

  unsigned SrcReg = getRegForValue(Src);
  if (SrcReg == 0) return false;

  // Handle sign-extension.
  if (SrcVT == MVT::i16 || SrcVT == MVT::i8) {
    SrcReg = ARMEmitIntExt(SrcVT, SrcReg, MVT::i32,
                                       /*isZExt*/!isSigned);
    if (SrcReg == 0) return false;
  }

  // The conversion routine works on fp-reg to fp-reg and the operand above
  // was an integer, move it to the fp registers if possible.
  unsigned FP = ARMMoveToFPReg(MVT::f32, SrcReg);
  if (FP == 0) return false;

  unsigned Opc;
  if (Ty->isFloatTy()) Opc = isSigned ? ARM::VSITOS : ARM::VUITOS;
  else if (Ty->isDoubleTy() && Subtarget->hasFP64())
    Opc = isSigned ? ARM::VSITOD : ARM::VUITOD;
  else return false;

  unsigned ResultReg = createResultReg(TLI.getRegClassFor(DstVT));
  AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
                          TII.get(Opc), ResultReg).addReg(FP));
  updateValueMap(I, ResultReg);
  return true;
}

bool ARMFastISel::SelectFPToI(const Instruction *I, bool isSigned) {
  // Make sure we have VFP.
  if (!Subtarget->hasVFP2Base()) return false;

  MVT DstVT;
  Type *RetTy = I->getType();
  if (!isTypeLegal(RetTy, DstVT))
    return false;

  unsigned Op = getRegForValue(I->getOperand(0));
  if (Op == 0) return false;

  unsigned Opc;
  Type *OpTy = I->getOperand(0)->getType();
  if (OpTy->isFloatTy()) Opc = isSigned ? ARM::VTOSIZS : ARM::VTOUIZS;
  else if (OpTy->isDoubleTy() && Subtarget->hasFP64())
    Opc = isSigned ? ARM::VTOSIZD : ARM::VTOUIZD;
  else return false;

  // f64->s32/u32 or f32->s32/u32 both need an intermediate f32 reg.
  unsigned ResultReg = createResultReg(TLI.getRegClassFor(MVT::f32));
  AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
                          TII.get(Opc), ResultReg).addReg(Op));

  // This result needs to be in an integer register, but the conversion only
  // takes place in fp-regs.
  unsigned IntReg = ARMMoveToIntReg(DstVT, ResultReg);
  if (IntReg == 0) return false;

  updateValueMap(I, IntReg);
  return true;
}

bool ARMFastISel::SelectSelect(const Instruction *I) {
  MVT VT;
  if (!isTypeLegal(I->getType(), VT))
    return false;

  // Things need to be register sized for register moves.
  if (VT != MVT::i32) return false;

  unsigned CondReg = getRegForValue(I->getOperand(0));
  if (CondReg == 0) return false;
  unsigned Op1Reg = getRegForValue(I->getOperand(1));
  if (Op1Reg == 0) return false;

  // Check to see if we can use an immediate in the conditional move.
  int Imm = 0;
  bool UseImm = false;
  bool isNegativeImm = false;
  if (const ConstantInt *ConstInt = dyn_cast<ConstantInt>(I->getOperand(2))) {
    assert(VT == MVT::i32 && "Expecting an i32.");
    Imm = (int)ConstInt->getValue().getZExtValue();
    if (Imm < 0) {
      isNegativeImm = true;
      Imm = ~Imm;
    }
    UseImm = isThumb2 ? (ARM_AM::getT2SOImmVal(Imm) != -1) :
      (ARM_AM::getSOImmVal(Imm) != -1);
  }

  unsigned Op2Reg = 0;
  if (!UseImm) {
    Op2Reg = getRegForValue(I->getOperand(2));
    if (Op2Reg == 0) return false;
  }

  unsigned TstOpc = isThumb2 ? ARM::t2TSTri : ARM::TSTri;
  CondReg = constrainOperandRegClass(TII.get(TstOpc), CondReg, 0);
  AddOptionalDefs(
      BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(TstOpc))
          .addReg(CondReg)
          .addImm(1));

  unsigned MovCCOpc;
  const TargetRegisterClass *RC;
  if (!UseImm) {
    RC = isThumb2 ? &ARM::tGPRRegClass : &ARM::GPRRegClass;
    MovCCOpc = isThumb2 ? ARM::t2MOVCCr : ARM::MOVCCr;
  } else {
    RC = isThumb2 ? &ARM::rGPRRegClass : &ARM::GPRRegClass;
    if (!isNegativeImm)
      MovCCOpc = isThumb2 ? ARM::t2MOVCCi : ARM::MOVCCi;
    else
      MovCCOpc = isThumb2 ? ARM::t2MVNCCi : ARM::MVNCCi;
  }
  unsigned ResultReg = createResultReg(RC);
  if (!UseImm) {
    Op2Reg = constrainOperandRegClass(TII.get(MovCCOpc), Op2Reg, 1);
    Op1Reg = constrainOperandRegClass(TII.get(MovCCOpc), Op1Reg, 2);
    BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(MovCCOpc),
            ResultReg)
        .addReg(Op2Reg)
        .addReg(Op1Reg)
        .addImm(ARMCC::NE)
        .addReg(ARM::CPSR);
  } else {
    Op1Reg = constrainOperandRegClass(TII.get(MovCCOpc), Op1Reg, 1);
    BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(MovCCOpc),
            ResultReg)
        .addReg(Op1Reg)
        .addImm(Imm)
        .addImm(ARMCC::EQ)
        .addReg(ARM::CPSR);
  }
  updateValueMap(I, ResultReg);
  return true;
}

bool ARMFastISel::SelectDiv(const Instruction *I, bool isSigned) {
  MVT VT;
  Type *Ty = I->getType();
  if (!isTypeLegal(Ty, VT))
    return false;

  // If we have integer div support we should have selected this automagically.
  // In case we have a real miss go ahead and return false and we'll pick
  // it up later.
  if (Subtarget->hasDivideInThumbMode())
    return false;

  // Otherwise emit a libcall.
  RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
  if (VT == MVT::i8)
    LC = isSigned ? RTLIB::SDIV_I8 : RTLIB::UDIV_I8;
  else if (VT == MVT::i16)
    LC = isSigned ? RTLIB::SDIV_I16 : RTLIB::UDIV_I16;
  else if (VT == MVT::i32)
    LC = isSigned ? RTLIB::SDIV_I32 : RTLIB::UDIV_I32;
  else if (VT == MVT::i64)
    LC = isSigned ? RTLIB::SDIV_I64 : RTLIB::UDIV_I64;
  else if (VT == MVT::i128)
    LC = isSigned ? RTLIB::SDIV_I128 : RTLIB::UDIV_I128;
  assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported SDIV!");

  return ARMEmitLibcall(I, LC);
}

bool ARMFastISel::SelectRem(const Instruction *I, bool isSigned) {
  MVT VT;
  Type *Ty = I->getType();
  if (!isTypeLegal(Ty, VT))
    return false;

  // Many ABIs do not provide a libcall for standalone remainder, so we need to
  // use divrem (see the RTABI 4.3.1). Since FastISel can't handle non-double
  // multi-reg returns, we'll have to bail out.
  if (!TLI.hasStandaloneRem(VT)) {
    return false;
  }

  RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
  if (VT == MVT::i8)
    LC = isSigned ? RTLIB::SREM_I8 : RTLIB::UREM_I8;
  else if (VT == MVT::i16)
    LC = isSigned ? RTLIB::SREM_I16 : RTLIB::UREM_I16;
  else if (VT == MVT::i32)
    LC = isSigned ? RTLIB::SREM_I32 : RTLIB::UREM_I32;
  else if (VT == MVT::i64)
    LC = isSigned ? RTLIB::SREM_I64 : RTLIB::UREM_I64;
  else if (VT == MVT::i128)
    LC = isSigned ? RTLIB::SREM_I128 : RTLIB::UREM_I128;
  assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported SREM!");

  return ARMEmitLibcall(I, LC);
}

bool ARMFastISel::SelectBinaryIntOp(const Instruction *I, unsigned ISDOpcode) {
  EVT DestVT = TLI.getValueType(DL, I->getType(), true);

  // We can get here in the case when we have a binary operation on a non-legal
  // type and the target independent selector doesn't know how to handle it.
  if (DestVT != MVT::i16 && DestVT != MVT::i8 && DestVT != MVT::i1)
    return false;

  unsigned Opc;
  switch (ISDOpcode) {
    default: return false;
    case ISD::ADD:
      Opc = isThumb2 ? ARM::t2ADDrr : ARM::ADDrr;
      break;
    case ISD::OR:
      Opc = isThumb2 ? ARM::t2ORRrr : ARM::ORRrr;
      break;
    case ISD::SUB:
      Opc = isThumb2 ? ARM::t2SUBrr : ARM::SUBrr;
      break;
  }

  unsigned SrcReg1 = getRegForValue(I->getOperand(0));
  if (SrcReg1 == 0) return false;

  // TODO: Often the 2nd operand is an immediate, which can be encoded directly
  // in the instruction, rather then materializing the value in a register.
  unsigned SrcReg2 = getRegForValue(I->getOperand(1));
  if (SrcReg2 == 0) return false;

  unsigned ResultReg = createResultReg(&ARM::GPRnopcRegClass);
  SrcReg1 = constrainOperandRegClass(TII.get(Opc), SrcReg1, 1);
  SrcReg2 = constrainOperandRegClass(TII.get(Opc), SrcReg2, 2);
  AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
                          TII.get(Opc), ResultReg)
                  .addReg(SrcReg1).addReg(SrcReg2));
  updateValueMap(I, ResultReg);
  return true;
}

bool ARMFastISel::SelectBinaryFPOp(const Instruction *I, unsigned ISDOpcode) {
  EVT FPVT = TLI.getValueType(DL, I->getType(), true);
  if (!FPVT.isSimple()) return false;
  MVT VT = FPVT.getSimpleVT();

  // FIXME: Support vector types where possible.
  if (VT.isVector())
    return false;

  // We can get here in the case when we want to use NEON for our fp
  // operations, but can't figure out how to. Just use the vfp instructions
  // if we have them.
  // FIXME: It'd be nice to use NEON instructions.
  Type *Ty = I->getType();
  if (Ty->isFloatTy() && !Subtarget->hasVFP2Base())
    return false;
  if (Ty->isDoubleTy() && (!Subtarget->hasVFP2Base() || !Subtarget->hasFP64()))
    return false;

  unsigned Opc;
  bool is64bit = VT == MVT::f64 || VT == MVT::i64;
  switch (ISDOpcode) {
    default: return false;
    case ISD::FADD:
      Opc = is64bit ? ARM::VADDD : ARM::VADDS;
      break;
    case ISD::FSUB:
      Opc = is64bit ? ARM::VSUBD : ARM::VSUBS;
      break;
    case ISD::FMUL:
      Opc = is64bit ? ARM::VMULD : ARM::VMULS;
      break;
  }
  unsigned Op1 = getRegForValue(I->getOperand(0));
  if (Op1 == 0) return false;

  unsigned Op2 = getRegForValue(I->getOperand(1));
  if (Op2 == 0) return false;

  unsigned ResultReg = createResultReg(TLI.getRegClassFor(VT.SimpleTy));
  AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
                          TII.get(Opc), ResultReg)
                  .addReg(Op1).addReg(Op2));
  updateValueMap(I, ResultReg);
  return true;
}

// Call Handling Code

// This is largely taken directly from CCAssignFnForNode
// TODO: We may not support all of this.
CCAssignFn *ARMFastISel::CCAssignFnForCall(CallingConv::ID CC,
                                           bool Return,
                                           bool isVarArg) {
  switch (CC) {
  default:
    report_fatal_error("Unsupported calling convention");
  case CallingConv::Fast:
    if (Subtarget->hasVFP2Base() && !isVarArg) {
      if (!Subtarget->isAAPCS_ABI())
        return (Return ? RetFastCC_ARM_APCS : FastCC_ARM_APCS);
      // For AAPCS ABI targets, just use VFP variant of the calling convention.
      return (Return ? RetCC_ARM_AAPCS_VFP : CC_ARM_AAPCS_VFP);
    }
    LLVM_FALLTHROUGH;
  case CallingConv::C:
  case CallingConv::CXX_FAST_TLS:
    // Use target triple & subtarget features to do actual dispatch.
    if (Subtarget->isAAPCS_ABI()) {
      if (Subtarget->hasVFP2Base() &&
          TM.Options.FloatABIType == FloatABI::Hard && !isVarArg)
        return (Return ? RetCC_ARM_AAPCS_VFP: CC_ARM_AAPCS_VFP);
      else
        return (Return ? RetCC_ARM_AAPCS: CC_ARM_AAPCS);
    } else {
      return (Return ? RetCC_ARM_APCS: CC_ARM_APCS);
    }
  case CallingConv::ARM_AAPCS_VFP:
  case CallingConv::Swift:
    if (!isVarArg)
      return (Return ? RetCC_ARM_AAPCS_VFP: CC_ARM_AAPCS_VFP);
    // Fall through to soft float variant, variadic functions don't
    // use hard floating point ABI.
    LLVM_FALLTHROUGH;
  case CallingConv::ARM_AAPCS:
    return (Return ? RetCC_ARM_AAPCS: CC_ARM_AAPCS);
  case CallingConv::ARM_APCS:
    return (Return ? RetCC_ARM_APCS: CC_ARM_APCS);
  case CallingConv::GHC:
    if (Return)
      report_fatal_error("Can't return in GHC call convention");
    else
      return CC_ARM_APCS_GHC;
  }
}

bool ARMFastISel::ProcessCallArgs(SmallVectorImpl<Value*> &Args,
                                  SmallVectorImpl<unsigned> &ArgRegs,
                                  SmallVectorImpl<MVT> &ArgVTs,
                                  SmallVectorImpl<ISD::ArgFlagsTy> &ArgFlags,
                                  SmallVectorImpl<unsigned> &RegArgs,
                                  CallingConv::ID CC,
                                  unsigned &NumBytes,
                                  bool isVarArg) {
  SmallVector<CCValAssign, 16> ArgLocs;
  CCState CCInfo(CC, isVarArg, *FuncInfo.MF, ArgLocs, *Context);
  CCInfo.AnalyzeCallOperands(ArgVTs, ArgFlags,
                             CCAssignFnForCall(CC, false, isVarArg));

  // Check that we can handle all of the arguments. If we can't, then bail out
  // now before we add code to the MBB.
  for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
    CCValAssign &VA = ArgLocs[i];
    MVT ArgVT = ArgVTs[VA.getValNo()];

    // We don't handle NEON/vector parameters yet.
    if (ArgVT.isVector() || ArgVT.getSizeInBits() > 64)
      return false;

    // Now copy/store arg to correct locations.
    if (VA.isRegLoc() && !VA.needsCustom()) {
      continue;
    } else if (VA.needsCustom()) {
      // TODO: We need custom lowering for vector (v2f64) args.
      if (VA.getLocVT() != MVT::f64 ||
          // TODO: Only handle register args for now.
          !VA.isRegLoc() || !ArgLocs[++i].isRegLoc())
        return false;
    } else {
      switch (ArgVT.SimpleTy) {
      default:
        return false;
      case MVT::i1:
      case MVT::i8:
      case MVT::i16:
      case MVT::i32:
        break;
      case MVT::f32:
        if (!Subtarget->hasVFP2Base())
          return false;
        break;
      case MVT::f64:
        if (!Subtarget->hasVFP2Base())
          return false;
        break;
      }
    }
  }

  // At the point, we are able to handle the call's arguments in fast isel.

  // Get a count of how many bytes are to be pushed on the stack.
  NumBytes = CCInfo.getNextStackOffset();

  // Issue CALLSEQ_START
  unsigned AdjStackDown = TII.getCallFrameSetupOpcode();
  AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
                          TII.get(AdjStackDown))
                  .addImm(NumBytes).addImm(0));

  // Process the args.
  for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
    CCValAssign &VA = ArgLocs[i];
    const Value *ArgVal = Args[VA.getValNo()];
    unsigned Arg = ArgRegs[VA.getValNo()];
    MVT ArgVT = ArgVTs[VA.getValNo()];

    assert((!ArgVT.isVector() && ArgVT.getSizeInBits() <= 64) &&
           "We don't handle NEON/vector parameters yet.");

    // Handle arg promotion, etc.
    switch (VA.getLocInfo()) {
      case CCValAssign::Full: break;
      case CCValAssign::SExt: {
        MVT DestVT = VA.getLocVT();
        Arg = ARMEmitIntExt(ArgVT, Arg, DestVT, /*isZExt*/false);
        assert(Arg != 0 && "Failed to emit a sext");
        ArgVT = DestVT;
        break;
      }
      case CCValAssign::AExt:
      // Intentional fall-through.  Handle AExt and ZExt.
      case CCValAssign::ZExt: {
        MVT DestVT = VA.getLocVT();
        Arg = ARMEmitIntExt(ArgVT, Arg, DestVT, /*isZExt*/true);
        assert(Arg != 0 && "Failed to emit a zext");
        ArgVT = DestVT;
        break;
      }
      case CCValAssign::BCvt: {
        unsigned BC = fastEmit_r(ArgVT, VA.getLocVT(), ISD::BITCAST, Arg,
                                 /*TODO: Kill=*/false);
        assert(BC != 0 && "Failed to emit a bitcast!");
        Arg = BC;
        ArgVT = VA.getLocVT();
        break;
      }
      default: llvm_unreachable("Unknown arg promotion!");
    }

    // Now copy/store arg to correct locations.
    if (VA.isRegLoc() && !VA.needsCustom()) {
      BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
              TII.get(TargetOpcode::COPY), VA.getLocReg()).addReg(Arg);
      RegArgs.push_back(VA.getLocReg());
    } else if (VA.needsCustom()) {
      // TODO: We need custom lowering for vector (v2f64) args.
      assert(VA.getLocVT() == MVT::f64 &&
             "Custom lowering for v2f64 args not available");

      // FIXME: ArgLocs[++i] may extend beyond ArgLocs.size()
      CCValAssign &NextVA = ArgLocs[++i];

      assert(VA.isRegLoc() && NextVA.isRegLoc() &&
             "We only handle register args!");

      AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
                              TII.get(ARM::VMOVRRD), VA.getLocReg())
                      .addReg(NextVA.getLocReg(), RegState::Define)
                      .addReg(Arg));
      RegArgs.push_back(VA.getLocReg());
      RegArgs.push_back(NextVA.getLocReg());
    } else {
      assert(VA.isMemLoc());
      // Need to store on the stack.

      // Don't emit stores for undef values.
      if (isa<UndefValue>(ArgVal))
        continue;

      Address Addr;
      Addr.BaseType = Address::RegBase;
      Addr.Base.Reg = ARM::SP;
      Addr.Offset = VA.getLocMemOffset();

      bool EmitRet = ARMEmitStore(ArgVT, Arg, Addr); (void)EmitRet;
      assert(EmitRet && "Could not emit a store for argument!");
    }
  }

  return true;
}

bool ARMFastISel::FinishCall(MVT RetVT, SmallVectorImpl<unsigned> &UsedRegs,
                             const Instruction *I, CallingConv::ID CC,
                             unsigned &NumBytes, bool isVarArg) {
  // Issue CALLSEQ_END
  unsigned AdjStackUp = TII.getCallFrameDestroyOpcode();
  AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
                          TII.get(AdjStackUp))
                  .addImm(NumBytes).addImm(0));

  // Now the return value.
  if (RetVT != MVT::isVoid) {
    SmallVector<CCValAssign, 16> RVLocs;
    CCState CCInfo(CC, isVarArg, *FuncInfo.MF, RVLocs, *Context);
    CCInfo.AnalyzeCallResult(RetVT, CCAssignFnForCall(CC, true, isVarArg));

    // Copy all of the result registers out of their specified physreg.
    if (RVLocs.size() == 2 && RetVT == MVT::f64) {
      // For this move we copy into two registers and then move into the
      // double fp reg we want.
      MVT DestVT = RVLocs[0].getValVT();
      const TargetRegisterClass* DstRC = TLI.getRegClassFor(DestVT);
      unsigned ResultReg = createResultReg(DstRC);
      AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
                              TII.get(ARM::VMOVDRR), ResultReg)
                      .addReg(RVLocs[0].getLocReg())
                      .addReg(RVLocs[1].getLocReg()));

      UsedRegs.push_back(RVLocs[0].getLocReg());
      UsedRegs.push_back(RVLocs[1].getLocReg());

      // Finally update the result.
      updateValueMap(I, ResultReg);
    } else {
      assert(RVLocs.size() == 1 &&"Can't handle non-double multi-reg retvals!");
      MVT CopyVT = RVLocs[0].getValVT();

      // Special handling for extended integers.
      if (RetVT == MVT::i1 || RetVT == MVT::i8 || RetVT == MVT::i16)
        CopyVT = MVT::i32;

      const TargetRegisterClass* DstRC = TLI.getRegClassFor(CopyVT);

      unsigned ResultReg = createResultReg(DstRC);
      BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
              TII.get(TargetOpcode::COPY),
              ResultReg).addReg(RVLocs[0].getLocReg());
      UsedRegs.push_back(RVLocs[0].getLocReg());

      // Finally update the result.
      updateValueMap(I, ResultReg);
    }
  }

  return true;
}

bool ARMFastISel::SelectRet(const Instruction *I) {
  const ReturnInst *Ret = cast<ReturnInst>(I);
  const Function &F = *I->getParent()->getParent();

  if (!FuncInfo.CanLowerReturn)
    return false;

  if (TLI.supportSwiftError() &&
      F.getAttributes().hasAttrSomewhere(Attribute::SwiftError))
    return false;

  if (TLI.supportSplitCSR(FuncInfo.MF))
    return false;

  // Build a list of return value registers.
  SmallVector<unsigned, 4> RetRegs;

  CallingConv::ID CC = F.getCallingConv();
  if (Ret->getNumOperands() > 0) {
    SmallVector<ISD::OutputArg, 4> Outs;
    GetReturnInfo(CC, F.getReturnType(), F.getAttributes(), Outs, TLI, DL);

    // Analyze operands of the call, assigning locations to each operand.
    SmallVector<CCValAssign, 16> ValLocs;
    CCState CCInfo(CC, F.isVarArg(), *FuncInfo.MF, ValLocs, I->getContext());
    CCInfo.AnalyzeReturn(Outs, CCAssignFnForCall(CC, true /* is Ret */,
                                                 F.isVarArg()));

    const Value *RV = Ret->getOperand(0);
    unsigned Reg = getRegForValue(RV);
    if (Reg == 0)
      return false;

    // Only handle a single return value for now.
    if (ValLocs.size() != 1)
      return false;

    CCValAssign &VA = ValLocs[0];

    // Don't bother handling odd stuff for now.
    if (VA.getLocInfo() != CCValAssign::Full)
      return false;
    // Only handle register returns for now.
    if (!VA.isRegLoc())
      return false;

    unsigned SrcReg = Reg + VA.getValNo();
    EVT RVEVT = TLI.getValueType(DL, RV->getType());
    if (!RVEVT.isSimple()) return false;
    MVT RVVT = RVEVT.getSimpleVT();
    MVT DestVT = VA.getValVT();
    // Special handling for extended integers.
    if (RVVT != DestVT) {
      if (RVVT != MVT::i1 && RVVT != MVT::i8 && RVVT != MVT::i16)
        return false;

      assert(DestVT == MVT::i32 && "ARM should always ext to i32");

      // Perform extension if flagged as either zext or sext.  Otherwise, do
      // nothing.
      if (Outs[0].Flags.isZExt() || Outs[0].Flags.isSExt()) {
        SrcReg = ARMEmitIntExt(RVVT, SrcReg, DestVT, Outs[0].Flags.isZExt());
        if (SrcReg == 0) return false;
      }
    }

    // Make the copy.
    unsigned DstReg = VA.getLocReg();
    const TargetRegisterClass* SrcRC = MRI.getRegClass(SrcReg);
    // Avoid a cross-class copy. This is very unlikely.
    if (!SrcRC->contains(DstReg))
      return false;
    BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
            TII.get(TargetOpcode::COPY), DstReg).addReg(SrcReg);

    // Add register to return instruction.
    RetRegs.push_back(VA.getLocReg());
  }

  MachineInstrBuilder MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
                                    TII.get(Subtarget->getReturnOpcode()));
  AddOptionalDefs(MIB);
  for (unsigned R : RetRegs)
    MIB.addReg(R, RegState::Implicit);
  return true;
}

unsigned ARMFastISel::ARMSelectCallOp(bool UseReg) {
  if (UseReg)
    return isThumb2 ? ARM::tBLXr : ARM::BLX;
  else
    return isThumb2 ? ARM::tBL : ARM::BL;
}

unsigned ARMFastISel::getLibcallReg(const Twine &Name) {
  // Manually compute the global's type to avoid building it when unnecessary.
  Type *GVTy = Type::getInt32PtrTy(*Context, /*AS=*/0);
  EVT LCREVT = TLI.getValueType(DL, GVTy);
  if (!LCREVT.isSimple()) return 0;

  GlobalValue *GV = new GlobalVariable(M, Type::getInt32Ty(*Context), false,
                                       GlobalValue::ExternalLinkage, nullptr,
                                       Name);
  assert(GV->getType() == GVTy && "We miscomputed the type for the global!");
  return ARMMaterializeGV(GV, LCREVT.getSimpleVT());
}

// A quick function that will emit a call for a named libcall in F with the
// vector of passed arguments for the Instruction in I. We can assume that we
// can emit a call for any libcall we can produce. This is an abridged version
// of the full call infrastructure since we won't need to worry about things
// like computed function pointers or strange arguments at call sites.
// TODO: Try to unify this and the normal call bits for ARM, then try to unify
// with X86.
bool ARMFastISel::ARMEmitLibcall(const Instruction *I, RTLIB::Libcall Call) {
  CallingConv::ID CC = TLI.getLibcallCallingConv(Call);

  // Handle *simple* calls for now.
  Type *RetTy = I->getType();
  MVT RetVT;
  if (RetTy->isVoidTy())
    RetVT = MVT::isVoid;
  else if (!isTypeLegal(RetTy, RetVT))
    return false;

  // Can't handle non-double multi-reg retvals.
  if (RetVT != MVT::isVoid && RetVT != MVT::i32) {
    SmallVector<CCValAssign, 16> RVLocs;
    CCState CCInfo(CC, false, *FuncInfo.MF, RVLocs, *Context);
    CCInfo.AnalyzeCallResult(RetVT, CCAssignFnForCall(CC, true, false));
    if (RVLocs.size() >= 2 && RetVT != MVT::f64)
      return false;
  }

  // Set up the argument vectors.
  SmallVector<Value*, 8> Args;
  SmallVector<unsigned, 8> ArgRegs;
  SmallVector<MVT, 8> ArgVTs;
  SmallVector<ISD::ArgFlagsTy, 8> ArgFlags;
  Args.reserve(I->getNumOperands());
  ArgRegs.reserve(I->getNumOperands());
  ArgVTs.reserve(I->getNumOperands());
  ArgFlags.reserve(I->getNumOperands());
  for (Value *Op :  I->operands()) {
    unsigned Arg = getRegForValue(Op);
    if (Arg == 0) return false;

    Type *ArgTy = Op->getType();
    MVT ArgVT;
    if (!isTypeLegal(ArgTy, ArgVT)) return false;

    ISD::ArgFlagsTy Flags;
    unsigned OriginalAlignment = DL.getABITypeAlignment(ArgTy);
    Flags.setOrigAlign(OriginalAlignment);

    Args.push_back(Op);
    ArgRegs.push_back(Arg);
    ArgVTs.push_back(ArgVT);
    ArgFlags.push_back(Flags);
  }

  // Handle the arguments now that we've gotten them.
  SmallVector<unsigned, 4> RegArgs;
  unsigned NumBytes;
  if (!ProcessCallArgs(Args, ArgRegs, ArgVTs, ArgFlags,
                       RegArgs, CC, NumBytes, false))
    return false;

  unsigned CalleeReg = 0;
  if (Subtarget->genLongCalls()) {
    CalleeReg = getLibcallReg(TLI.getLibcallName(Call));
    if (CalleeReg == 0) return false;
  }

  // Issue the call.
  unsigned CallOpc = ARMSelectCallOp(Subtarget->genLongCalls());
  MachineInstrBuilder MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt,
                                    DbgLoc, TII.get(CallOpc));
  // BL / BLX don't take a predicate, but tBL / tBLX do.
  if (isThumb2)
    MIB.add(predOps(ARMCC::AL));
  if (Subtarget->genLongCalls())
    MIB.addReg(CalleeReg);
  else
    MIB.addExternalSymbol(TLI.getLibcallName(Call));

  // Add implicit physical register uses to the call.
  for (unsigned R : RegArgs)
    MIB.addReg(R, RegState::Implicit);

  // Add a register mask with the call-preserved registers.
  // Proper defs for return values will be added by setPhysRegsDeadExcept().
  MIB.addRegMask(TRI.getCallPreservedMask(*FuncInfo.MF, CC));

  // Finish off the call including any return values.
  SmallVector<unsigned, 4> UsedRegs;
  if (!FinishCall(RetVT, UsedRegs, I, CC, NumBytes, false)) return false;

  // Set all unused physreg defs as dead.
  static_cast<MachineInstr *>(MIB)->setPhysRegsDeadExcept(UsedRegs, TRI);

  return true;
}

bool ARMFastISel::SelectCall(const Instruction *I,
                             const char *IntrMemName = nullptr) {
  const CallInst *CI = cast<CallInst>(I);
  const Value *Callee = CI->getCalledValue();

  // Can't handle inline asm.
  if (isa<InlineAsm>(Callee)) return false;

  // Allow SelectionDAG isel to handle tail calls.
  if (CI->isTailCall()) return false;

  // Check the calling convention.
  ImmutableCallSite CS(CI);
  CallingConv::ID CC = CS.getCallingConv();

  // TODO: Avoid some calling conventions?

  FunctionType *FTy = CS.getFunctionType();
  bool isVarArg = FTy->isVarArg();

  // Handle *simple* calls for now.
  Type *RetTy = I->getType();
  MVT RetVT;
  if (RetTy->isVoidTy())
    RetVT = MVT::isVoid;
  else if (!isTypeLegal(RetTy, RetVT) && RetVT != MVT::i16 &&
           RetVT != MVT::i8  && RetVT != MVT::i1)
    return false;

  // Can't handle non-double multi-reg retvals.
  if (RetVT != MVT::isVoid && RetVT != MVT::i1 && RetVT != MVT::i8 &&
      RetVT != MVT::i16 && RetVT != MVT::i32) {
    SmallVector<CCValAssign, 16> RVLocs;
    CCState CCInfo(CC, isVarArg, *FuncInfo.MF, RVLocs, *Context);
    CCInfo.AnalyzeCallResult(RetVT, CCAssignFnForCall(CC, true, isVarArg));
    if (RVLocs.size() >= 2 && RetVT != MVT::f64)
      return false;
  }

  // Set up the argument vectors.
  SmallVector<Value*, 8> Args;
  SmallVector<unsigned, 8> ArgRegs;
  SmallVector<MVT, 8> ArgVTs;
  SmallVector<ISD::ArgFlagsTy, 8> ArgFlags;
  unsigned arg_size = CS.arg_size();
  Args.reserve(arg_size);
  ArgRegs.reserve(arg_size);
  ArgVTs.reserve(arg_size);
  ArgFlags.reserve(arg_size);
  for (ImmutableCallSite::arg_iterator i = CS.arg_begin(), e = CS.arg_end();
       i != e; ++i) {
    // If we're lowering a memory intrinsic instead of a regular call, skip the
    // last argument, which shouldn't be passed to the underlying function.
    if (IntrMemName && e - i <= 1)
      break;

    ISD::ArgFlagsTy Flags;
    unsigned ArgIdx = i - CS.arg_begin();
    if (CS.paramHasAttr(ArgIdx, Attribute::SExt))
      Flags.setSExt();
    if (CS.paramHasAttr(ArgIdx, Attribute::ZExt))
      Flags.setZExt();

    // FIXME: Only handle *easy* calls for now.
    if (CS.paramHasAttr(ArgIdx, Attribute::InReg) ||
        CS.paramHasAttr(ArgIdx, Attribute::StructRet) ||
        CS.paramHasAttr(ArgIdx, Attribute::SwiftSelf) ||
        CS.paramHasAttr(ArgIdx, Attribute::SwiftError) ||
        CS.paramHasAttr(ArgIdx, Attribute::Nest) ||
        CS.paramHasAttr(ArgIdx, Attribute::ByVal))
      return false;

    Type *ArgTy = (*i)->getType();
    MVT ArgVT;
    if (!isTypeLegal(ArgTy, ArgVT) && ArgVT != MVT::i16 && ArgVT != MVT::i8 &&
        ArgVT != MVT::i1)
      return false;

    unsigned Arg = getRegForValue(*i);
    if (Arg == 0)
      return false;

    unsigned OriginalAlignment = DL.getABITypeAlignment(ArgTy);
    Flags.setOrigAlign(OriginalAlignment);

    Args.push_back(*i);
    ArgRegs.push_back(Arg);
    ArgVTs.push_back(ArgVT);
    ArgFlags.push_back(Flags);
  }

  // Handle the arguments now that we've gotten them.
  SmallVector<unsigned, 4> RegArgs;
  unsigned NumBytes;
  if (!ProcessCallArgs(Args, ArgRegs, ArgVTs, ArgFlags,
                       RegArgs, CC, NumBytes, isVarArg))
    return false;

  bool UseReg = false;
  const GlobalValue *GV = dyn_cast<GlobalValue>(Callee);
  if (!GV || Subtarget->genLongCalls()) UseReg = true;

  unsigned CalleeReg = 0;
  if (UseReg) {
    if (IntrMemName)
      CalleeReg = getLibcallReg(IntrMemName);
    else
      CalleeReg = getRegForValue(Callee);

    if (CalleeReg == 0) return false;
  }

  // Issue the call.
  unsigned CallOpc = ARMSelectCallOp(UseReg);
  MachineInstrBuilder MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt,
                                    DbgLoc, TII.get(CallOpc));

  // ARM calls don't take a predicate, but tBL / tBLX do.
  if(isThumb2)
    MIB.add(predOps(ARMCC::AL));
  if (UseReg)
    MIB.addReg(CalleeReg);
  else if (!IntrMemName)
    MIB.addGlobalAddress(GV, 0, 0);
  else
    MIB.addExternalSymbol(IntrMemName, 0);

  // Add implicit physical register uses to the call.
  for (unsigned R : RegArgs)
    MIB.addReg(R, RegState::Implicit);

  // Add a register mask with the call-preserved registers.
  // Proper defs for return values will be added by setPhysRegsDeadExcept().
  MIB.addRegMask(TRI.getCallPreservedMask(*FuncInfo.MF, CC));

  // Finish off the call including any return values.
  SmallVector<unsigned, 4> UsedRegs;
  if (!FinishCall(RetVT, UsedRegs, I, CC, NumBytes, isVarArg))
    return false;

  // Set all unused physreg defs as dead.
  static_cast<MachineInstr *>(MIB)->setPhysRegsDeadExcept(UsedRegs, TRI);

  return true;
}

bool ARMFastISel::ARMIsMemCpySmall(uint64_t Len) {
  return Len <= 16;
}

bool ARMFastISel::ARMTryEmitSmallMemCpy(Address Dest, Address Src,
                                        uint64_t Len, unsigned Alignment) {
  // Make sure we don't bloat code by inlining very large memcpy's.
  if (!ARMIsMemCpySmall(Len))
    return false;

  while (Len) {
    MVT VT;
    if (!Alignment || Alignment >= 4) {
      if (Len >= 4)
        VT = MVT::i32;
      else if (Len >= 2)
        VT = MVT::i16;
      else {
        assert(Len == 1 && "Expected a length of 1!");
        VT = MVT::i8;
      }
    } else {
      // Bound based on alignment.
      if (Len >= 2 && Alignment == 2)
        VT = MVT::i16;
      else {
        VT = MVT::i8;
      }
    }

    bool RV;
    unsigned ResultReg;
    RV = ARMEmitLoad(VT, ResultReg, Src);
    assert(RV && "Should be able to handle this load.");
    RV = ARMEmitStore(VT, ResultReg, Dest);
    assert(RV && "Should be able to handle this store.");
    (void)RV;

    unsigned Size = VT.getSizeInBits()/8;
    Len -= Size;
    Dest.Offset += Size;
    Src.Offset += Size;
  }

  return true;
}

bool ARMFastISel::SelectIntrinsicCall(const IntrinsicInst &I) {
  // FIXME: Handle more intrinsics.
  switch (I.getIntrinsicID()) {
  default: return false;
  case Intrinsic::frameaddress: {
    MachineFrameInfo &MFI = FuncInfo.MF->getFrameInfo();
    MFI.setFrameAddressIsTaken(true);

    unsigned LdrOpc = isThumb2 ? ARM::t2LDRi12 : ARM::LDRi12;
    const TargetRegisterClass *RC = isThumb2 ? &ARM::tGPRRegClass
                                             : &ARM::GPRRegClass;

    const ARMBaseRegisterInfo *RegInfo =
        static_cast<const ARMBaseRegisterInfo *>(Subtarget->getRegisterInfo());
    unsigned FramePtr = RegInfo->getFrameRegister(*(FuncInfo.MF));
    unsigned SrcReg = FramePtr;

    // Recursively load frame address
    // ldr r0 [fp]
    // ldr r0 [r0]
    // ldr r0 [r0]
    // ...
    unsigned DestReg;
    unsigned Depth = cast<ConstantInt>(I.getOperand(0))->getZExtValue();
    while (Depth--) {
      DestReg = createResultReg(RC);
      AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
                              TII.get(LdrOpc), DestReg)
                      .addReg(SrcReg).addImm(0));
      SrcReg = DestReg;
    }
    updateValueMap(&I, SrcReg);
    return true;
  }
  case Intrinsic::memcpy:
  case Intrinsic::memmove: {
    const MemTransferInst &MTI = cast<MemTransferInst>(I);
    // Don't handle volatile.
    if (MTI.isVolatile())
      return false;

    // Disable inlining for memmove before calls to ComputeAddress.  Otherwise,
    // we would emit dead code because we don't currently handle memmoves.
    bool isMemCpy = (I.getIntrinsicID() == Intrinsic::memcpy);
    if (isa<ConstantInt>(MTI.getLength()) && isMemCpy) {
      // Small memcpy's are common enough that we want to do them without a call
      // if possible.
      uint64_t Len = cast<ConstantInt>(MTI.getLength())->getZExtValue();
      if (ARMIsMemCpySmall(Len)) {
        Address Dest, Src;
        if (!ARMComputeAddress(MTI.getRawDest(), Dest) ||
            !ARMComputeAddress(MTI.getRawSource(), Src))
          return false;
        unsigned Alignment = MinAlign(MTI.getDestAlignment(),
                                      MTI.getSourceAlignment());
        if (ARMTryEmitSmallMemCpy(Dest, Src, Len, Alignment))
          return true;
      }
    }

    if (!MTI.getLength()->getType()->isIntegerTy(32))
      return false;

    if (MTI.getSourceAddressSpace() > 255 || MTI.getDestAddressSpace() > 255)
      return false;

    const char *IntrMemName = isa<MemCpyInst>(I) ? "memcpy" : "memmove";
    return SelectCall(&I, IntrMemName);
  }
  case Intrinsic::memset: {
    const MemSetInst &MSI = cast<MemSetInst>(I);
    // Don't handle volatile.
    if (MSI.isVolatile())
      return false;

    if (!MSI.getLength()->getType()->isIntegerTy(32))
      return false;

    if (MSI.getDestAddressSpace() > 255)
      return false;

    return SelectCall(&I, "memset");
  }
  case Intrinsic::trap: {
    BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(
      Subtarget->useNaClTrap() ? ARM::TRAPNaCl : ARM::TRAP));
    return true;
  }
  }
}

bool ARMFastISel::SelectTrunc(const Instruction *I) {
  // The high bits for a type smaller than the register size are assumed to be
  // undefined.
  Value *Op = I->getOperand(0);

  EVT SrcVT, DestVT;
  SrcVT = TLI.getValueType(DL, Op->getType(), true);
  DestVT = TLI.getValueType(DL, I->getType(), true);

  if (SrcVT != MVT::i32 && SrcVT != MVT::i16 && SrcVT != MVT::i8)
    return false;
  if (DestVT != MVT::i16 && DestVT != MVT::i8 && DestVT != MVT::i1)
    return false;

  unsigned SrcReg = getRegForValue(Op);
  if (!SrcReg) return false;

  // Because the high bits are undefined, a truncate doesn't generate
  // any code.
  updateValueMap(I, SrcReg);
  return true;
}

unsigned ARMFastISel::ARMEmitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT,
                                    bool isZExt) {
  if (DestVT != MVT::i32 && DestVT != MVT::i16 && DestVT != MVT::i8)
    return 0;
  if (SrcVT != MVT::i16 && SrcVT != MVT::i8 && SrcVT != MVT::i1)
    return 0;

  // Table of which combinations can be emitted as a single instruction,
  // and which will require two.
  static const uint8_t isSingleInstrTbl[3][2][2][2] = {
    //            ARM                     Thumb
    //           !hasV6Ops  hasV6Ops     !hasV6Ops  hasV6Ops
    //    ext:     s  z      s  z          s  z      s  z
    /*  1 */ { { { 0, 1 }, { 0, 1 } }, { { 0, 0 }, { 0, 1 } } },
    /*  8 */ { { { 0, 1 }, { 1, 1 } }, { { 0, 0 }, { 1, 1 } } },
    /* 16 */ { { { 0, 0 }, { 1, 1 } }, { { 0, 0 }, { 1, 1 } } }
  };

  // Target registers for:
  //  - For ARM can never be PC.
  //  - For 16-bit Thumb are restricted to lower 8 registers.
  //  - For 32-bit Thumb are restricted to non-SP and non-PC.
  static const TargetRegisterClass *RCTbl[2][2] = {
    // Instructions: Two                     Single
    /* ARM      */ { &ARM::GPRnopcRegClass, &ARM::GPRnopcRegClass },
    /* Thumb    */ { &ARM::tGPRRegClass,    &ARM::rGPRRegClass    }
  };

  // Table governing the instruction(s) to be emitted.
  static const struct InstructionTable {
    uint32_t Opc   : 16;
    uint32_t hasS  :  1; // Some instructions have an S bit, always set it to 0.
    uint32_t Shift :  7; // For shift operand addressing mode, used by MOVsi.
    uint32_t Imm   :  8; // All instructions have either a shift or a mask.
  } IT[2][2][3][2] = {
    { // Two instructions (first is left shift, second is in this table).
      { // ARM                Opc           S  Shift             Imm
        /*  1 bit sext */ { { ARM::MOVsi  , 1, ARM_AM::asr     ,  31 },
        /*  1 bit zext */   { ARM::MOVsi  , 1, ARM_AM::lsr     ,  31 } },
        /*  8 bit sext */ { { ARM::MOVsi  , 1, ARM_AM::asr     ,  24 },
        /*  8 bit zext */   { ARM::MOVsi  , 1, ARM_AM::lsr     ,  24 } },
        /* 16 bit sext */ { { ARM::MOVsi  , 1, ARM_AM::asr     ,  16 },
        /* 16 bit zext */   { ARM::MOVsi  , 1, ARM_AM::lsr     ,  16 } }
      },
      { // Thumb              Opc           S  Shift             Imm
        /*  1 bit sext */ { { ARM::tASRri , 0, ARM_AM::no_shift,  31 },
        /*  1 bit zext */   { ARM::tLSRri , 0, ARM_AM::no_shift,  31 } },
        /*  8 bit sext */ { { ARM::tASRri , 0, ARM_AM::no_shift,  24 },
        /*  8 bit zext */   { ARM::tLSRri , 0, ARM_AM::no_shift,  24 } },
        /* 16 bit sext */ { { ARM::tASRri , 0, ARM_AM::no_shift,  16 },
        /* 16 bit zext */   { ARM::tLSRri , 0, ARM_AM::no_shift,  16 } }
      }
    },
    { // Single instruction.
      { // ARM                Opc           S  Shift             Imm
        /*  1 bit sext */ { { ARM::KILL   , 0, ARM_AM::no_shift,   0 },
        /*  1 bit zext */   { ARM::ANDri  , 1, ARM_AM::no_shift,   1 } },
        /*  8 bit sext */ { { ARM::SXTB   , 0, ARM_AM::no_shift,   0 },
        /*  8 bit zext */   { ARM::ANDri  , 1, ARM_AM::no_shift, 255 } },
        /* 16 bit sext */ { { ARM::SXTH   , 0, ARM_AM::no_shift,   0 },
        /* 16 bit zext */   { ARM::UXTH   , 0, ARM_AM::no_shift,   0 } }
      },
      { // Thumb              Opc           S  Shift             Imm
        /*  1 bit sext */ { { ARM::KILL   , 0, ARM_AM::no_shift,   0 },
        /*  1 bit zext */   { ARM::t2ANDri, 1, ARM_AM::no_shift,   1 } },
        /*  8 bit sext */ { { ARM::t2SXTB , 0, ARM_AM::no_shift,   0 },
        /*  8 bit zext */   { ARM::t2ANDri, 1, ARM_AM::no_shift, 255 } },
        /* 16 bit sext */ { { ARM::t2SXTH , 0, ARM_AM::no_shift,   0 },
        /* 16 bit zext */   { ARM::t2UXTH , 0, ARM_AM::no_shift,   0 } }
      }
    }
  };

  unsigned SrcBits = SrcVT.getSizeInBits();
  unsigned DestBits = DestVT.getSizeInBits();
  (void) DestBits;
  assert((SrcBits < DestBits) && "can only extend to larger types");
  assert((DestBits == 32 || DestBits == 16 || DestBits == 8) &&
         "other sizes unimplemented");
  assert((SrcBits == 16 || SrcBits == 8 || SrcBits == 1) &&
         "other sizes unimplemented");

  bool hasV6Ops = Subtarget->hasV6Ops();
  unsigned Bitness = SrcBits / 8;  // {1,8,16}=>{0,1,2}
  assert((Bitness < 3) && "sanity-check table bounds");

  bool isSingleInstr = isSingleInstrTbl[Bitness][isThumb2][hasV6Ops][isZExt];
  const TargetRegisterClass *RC = RCTbl[isThumb2][isSingleInstr];
  const InstructionTable *ITP = &IT[isSingleInstr][isThumb2][Bitness][isZExt];
  unsigned Opc = ITP->Opc;
  assert(ARM::KILL != Opc && "Invalid table entry");
  unsigned hasS = ITP->hasS;
  ARM_AM::ShiftOpc Shift = (ARM_AM::ShiftOpc) ITP->Shift;
  assert(((Shift == ARM_AM::no_shift) == (Opc != ARM::MOVsi)) &&
         "only MOVsi has shift operand addressing mode");
  unsigned Imm = ITP->Imm;

  // 16-bit Thumb instructions always set CPSR (unless they're in an IT block).
  bool setsCPSR = &ARM::tGPRRegClass == RC;
  unsigned LSLOpc = isThumb2 ? ARM::tLSLri : ARM::MOVsi;
  unsigned ResultReg;
  // MOVsi encodes shift and immediate in shift operand addressing mode.
  // The following condition has the same value when emitting two
  // instruction sequences: both are shifts.
  bool ImmIsSO = (Shift != ARM_AM::no_shift);

  // Either one or two instructions are emitted.
  // They're always of the form:
  //   dst = in OP imm
  // CPSR is set only by 16-bit Thumb instructions.
  // Predicate, if any, is AL.
  // S bit, if available, is always 0.
  // When two are emitted the first's result will feed as the second's input,
  // that value is then dead.
  unsigned NumInstrsEmitted = isSingleInstr ? 1 : 2;
  for (unsigned Instr = 0; Instr != NumInstrsEmitted; ++Instr) {
    ResultReg = createResultReg(RC);
    bool isLsl = (0 == Instr) && !isSingleInstr;
    unsigned Opcode = isLsl ? LSLOpc : Opc;
    ARM_AM::ShiftOpc ShiftAM = isLsl ? ARM_AM::lsl : Shift;
    unsigned ImmEnc = ImmIsSO ? ARM_AM::getSORegOpc(ShiftAM, Imm) : Imm;
    bool isKill = 1 == Instr;
    MachineInstrBuilder MIB = BuildMI(
        *FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opcode), ResultReg);
    if (setsCPSR)
      MIB.addReg(ARM::CPSR, RegState::Define);
    SrcReg = constrainOperandRegClass(TII.get(Opcode), SrcReg, 1 + setsCPSR);
    MIB.addReg(SrcReg, isKill * RegState::Kill)
        .addImm(ImmEnc)
        .add(predOps(ARMCC::AL));
    if (hasS)
      MIB.add(condCodeOp());
    // Second instruction consumes the first's result.
    SrcReg = ResultReg;
  }

  return ResultReg;
}

bool ARMFastISel::SelectIntExt(const Instruction *I) {
  // On ARM, in general, integer casts don't involve legal types; this code
  // handles promotable integers.
  Type *DestTy = I->getType();
  Value *Src = I->getOperand(0);
  Type *SrcTy = Src->getType();

  bool isZExt = isa<ZExtInst>(I);
  unsigned SrcReg = getRegForValue(Src);
  if (!SrcReg) return false;

  EVT SrcEVT, DestEVT;
  SrcEVT = TLI.getValueType(DL, SrcTy, true);
  DestEVT = TLI.getValueType(DL, DestTy, true);
  if (!SrcEVT.isSimple()) return false;
  if (!DestEVT.isSimple()) return false;

  MVT SrcVT = SrcEVT.getSimpleVT();
  MVT DestVT = DestEVT.getSimpleVT();
  unsigned ResultReg = ARMEmitIntExt(SrcVT, SrcReg, DestVT, isZExt);
  if (ResultReg == 0) return false;
  updateValueMap(I, ResultReg);
  return true;
}

bool ARMFastISel::SelectShift(const Instruction *I,
                              ARM_AM::ShiftOpc ShiftTy) {
  // We handle thumb2 mode by target independent selector
  // or SelectionDAG ISel.
  if (isThumb2)
    return false;

  // Only handle i32 now.
  EVT DestVT = TLI.getValueType(DL, I->getType(), true);
  if (DestVT != MVT::i32)
    return false;

  unsigned Opc = ARM::MOVsr;
  unsigned ShiftImm;
  Value *Src2Value = I->getOperand(1);
  if (const ConstantInt *CI = dyn_cast<ConstantInt>(Src2Value)) {
    ShiftImm = CI->getZExtValue();

    // Fall back to selection DAG isel if the shift amount
    // is zero or greater than the width of the value type.
    if (ShiftImm == 0 || ShiftImm >=32)
      return false;

    Opc = ARM::MOVsi;
  }

  Value *Src1Value = I->getOperand(0);
  unsigned Reg1 = getRegForValue(Src1Value);
  if (Reg1 == 0) return false;

  unsigned Reg2 = 0;
  if (Opc == ARM::MOVsr) {
    Reg2 = getRegForValue(Src2Value);
    if (Reg2 == 0) return false;
  }

  unsigned ResultReg = createResultReg(&ARM::GPRnopcRegClass);
  if(ResultReg == 0) return false;

  MachineInstrBuilder MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
                                    TII.get(Opc), ResultReg)
                            .addReg(Reg1);

  if (Opc == ARM::MOVsi)
    MIB.addImm(ARM_AM::getSORegOpc(ShiftTy, ShiftImm));
  else if (Opc == ARM::MOVsr) {
    MIB.addReg(Reg2);
    MIB.addImm(ARM_AM::getSORegOpc(ShiftTy, 0));
  }

  AddOptionalDefs(MIB);
  updateValueMap(I, ResultReg);
  return true;
}

// TODO: SoftFP support.
bool ARMFastISel::fastSelectInstruction(const Instruction *I) {
  switch (I->getOpcode()) {
    case Instruction::Load:
      return SelectLoad(I);
    case Instruction::Store:
      return SelectStore(I);
    case Instruction::Br:
      return SelectBranch(I);
    case Instruction::IndirectBr:
      return SelectIndirectBr(I);
    case Instruction::ICmp:
    case Instruction::FCmp:
      return SelectCmp(I);
    case Instruction::FPExt:
      return SelectFPExt(I);
    case Instruction::FPTrunc:
      return SelectFPTrunc(I);
    case Instruction::SIToFP:
      return SelectIToFP(I, /*isSigned*/ true);
    case Instruction::UIToFP:
      return SelectIToFP(I, /*isSigned*/ false);
    case Instruction::FPToSI:
      return SelectFPToI(I, /*isSigned*/ true);
    case Instruction::FPToUI:
      return SelectFPToI(I, /*isSigned*/ false);
    case Instruction::Add:
      return SelectBinaryIntOp(I, ISD::ADD);
    case Instruction::Or:
      return SelectBinaryIntOp(I, ISD::OR);
    case Instruction::Sub:
      return SelectBinaryIntOp(I, ISD::SUB);
    case Instruction::FAdd:
      return SelectBinaryFPOp(I, ISD::FADD);
    case Instruction::FSub:
      return SelectBinaryFPOp(I, ISD::FSUB);
    case Instruction::FMul:
      return SelectBinaryFPOp(I, ISD::FMUL);
    case Instruction::SDiv:
      return SelectDiv(I, /*isSigned*/ true);
    case Instruction::UDiv:
      return SelectDiv(I, /*isSigned*/ false);
    case Instruction::SRem:
      return SelectRem(I, /*isSigned*/ true);
    case Instruction::URem:
      return SelectRem(I, /*isSigned*/ false);
    case Instruction::Call:
      if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(I))
        return SelectIntrinsicCall(*II);
      return SelectCall(I);
    case Instruction::Select:
      return SelectSelect(I);
    case Instruction::Ret:
      return SelectRet(I);
    case Instruction::Trunc:
      return SelectTrunc(I);
    case Instruction::ZExt:
    case Instruction::SExt:
      return SelectIntExt(I);
    case Instruction::Shl:
      return SelectShift(I, ARM_AM::lsl);
    case Instruction::LShr:
      return SelectShift(I, ARM_AM::lsr);
    case Instruction::AShr:
      return SelectShift(I, ARM_AM::asr);
    default: break;
  }
  return false;
}

// This table describes sign- and zero-extend instructions which can be
// folded into a preceding load. All of these extends have an immediate
// (sometimes a mask and sometimes a shift) that's applied after
// extension.
static const struct FoldableLoadExtendsStruct {
  uint16_t Opc[2];  // ARM, Thumb.
  uint8_t ExpectedImm;
  uint8_t isZExt     : 1;
  uint8_t ExpectedVT : 7;
} FoldableLoadExtends[] = {
  { { ARM::SXTH,  ARM::t2SXTH  },   0, 0, MVT::i16 },
  { { ARM::UXTH,  ARM::t2UXTH  },   0, 1, MVT::i16 },
  { { ARM::ANDri, ARM::t2ANDri }, 255, 1, MVT::i8  },
  { { ARM::SXTB,  ARM::t2SXTB  },   0, 0, MVT::i8  },
  { { ARM::UXTB,  ARM::t2UXTB  },   0, 1, MVT::i8  }
};

/// The specified machine instr operand is a vreg, and that
/// vreg is being provided by the specified load instruction.  If possible,
/// try to fold the load as an operand to the instruction, returning true if
/// successful.
bool ARMFastISel::tryToFoldLoadIntoMI(MachineInstr *MI, unsigned OpNo,
                                      const LoadInst *LI) {
  // Verify we have a legal type before going any further.
  MVT VT;
  if (!isLoadTypeLegal(LI->getType(), VT))
    return false;

  // Combine load followed by zero- or sign-extend.
  // ldrb r1, [r0]       ldrb r1, [r0]
  // uxtb r2, r1     =>
  // mov  r3, r2         mov  r3, r1
  if (MI->getNumOperands() < 3 || !MI->getOperand(2).isImm())
    return false;
  const uint64_t Imm = MI->getOperand(2).getImm();

  bool Found = false;
  bool isZExt;
  for (const FoldableLoadExtendsStruct &FLE : FoldableLoadExtends) {
    if (FLE.Opc[isThumb2] == MI->getOpcode() &&
        (uint64_t)FLE.ExpectedImm == Imm &&
        MVT((MVT::SimpleValueType)FLE.ExpectedVT) == VT) {
      Found = true;
      isZExt = FLE.isZExt;
    }
  }
  if (!Found) return false;

  // See if we can handle this address.
  Address Addr;
  if (!ARMComputeAddress(LI->getOperand(0), Addr)) return false;

  unsigned ResultReg = MI->getOperand(0).getReg();
  if (!ARMEmitLoad(VT, ResultReg, Addr, LI->getAlignment(), isZExt, false))
    return false;
  MachineBasicBlock::iterator I(MI);
  removeDeadCode(I, std::next(I));
  return true;
}

unsigned ARMFastISel::ARMLowerPICELF(const GlobalValue *GV,
                                     unsigned Align, MVT VT) {
  bool UseGOT_PREL = !TM.shouldAssumeDSOLocal(*GV->getParent(), GV);

  LLVMContext *Context = &MF->getFunction().getContext();
  unsigned ARMPCLabelIndex = AFI->createPICLabelUId();
  unsigned PCAdj = Subtarget->isThumb() ? 4 : 8;
  ARMConstantPoolValue *CPV = ARMConstantPoolConstant::Create(
      GV, ARMPCLabelIndex, ARMCP::CPValue, PCAdj,
      UseGOT_PREL ? ARMCP::GOT_PREL : ARMCP::no_modifier,
      /*AddCurrentAddress=*/UseGOT_PREL);

  unsigned ConstAlign =
      MF->getDataLayout().getPrefTypeAlignment(Type::getInt32PtrTy(*Context));
  unsigned Idx = MF->getConstantPool()->getConstantPoolIndex(CPV, ConstAlign);
  MachineMemOperand *CPMMO =
      MF->getMachineMemOperand(MachinePointerInfo::getConstantPool(*MF),
                               MachineMemOperand::MOLoad, 4, 4);

  unsigned TempReg = MF->getRegInfo().createVirtualRegister(&ARM::rGPRRegClass);
  unsigned Opc = isThumb2 ? ARM::t2LDRpci : ARM::LDRcp;
  MachineInstrBuilder MIB =
      BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), TempReg)
          .addConstantPoolIndex(Idx)
          .addMemOperand(CPMMO);
  if (Opc == ARM::LDRcp)
    MIB.addImm(0);
  MIB.add(predOps(ARMCC::AL));

  // Fix the address by adding pc.
  unsigned DestReg = createResultReg(TLI.getRegClassFor(VT));
  Opc = Subtarget->isThumb() ? ARM::tPICADD : UseGOT_PREL ? ARM::PICLDR
                                                          : ARM::PICADD;
  DestReg = constrainOperandRegClass(TII.get(Opc), DestReg, 0);
  MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), DestReg)
            .addReg(TempReg)
            .addImm(ARMPCLabelIndex);

  if (!Subtarget->isThumb())
    MIB.add(predOps(ARMCC::AL));

  if (UseGOT_PREL && Subtarget->isThumb()) {
    unsigned NewDestReg = createResultReg(TLI.getRegClassFor(VT));
    MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
                  TII.get(ARM::t2LDRi12), NewDestReg)
              .addReg(DestReg)
              .addImm(0);
    DestReg = NewDestReg;
    AddOptionalDefs(MIB);
  }
  return DestReg;
}

bool ARMFastISel::fastLowerArguments() {
  if (!FuncInfo.CanLowerReturn)
    return false;

  const Function *F = FuncInfo.Fn;
  if (F->isVarArg())
    return false;

  CallingConv::ID CC = F->getCallingConv();
  switch (CC) {
  default:
    return false;
  case CallingConv::Fast:
  case CallingConv::C:
  case CallingConv::ARM_AAPCS_VFP:
  case CallingConv::ARM_AAPCS:
  case CallingConv::ARM_APCS:
  case CallingConv::Swift:
    break;
  }

  // Only handle simple cases. i.e. Up to 4 i8/i16/i32 scalar arguments
  // which are passed in r0 - r3.
  for (const Argument &Arg : F->args()) {
    if (Arg.getArgNo() >= 4)
      return false;

    if (Arg.hasAttribute(Attribute::InReg) ||
        Arg.hasAttribute(Attribute::StructRet) ||
        Arg.hasAttribute(Attribute::SwiftSelf) ||
        Arg.hasAttribute(Attribute::SwiftError) ||
        Arg.hasAttribute(Attribute::ByVal))
      return false;

    Type *ArgTy = Arg.getType();
    if (ArgTy->isStructTy() || ArgTy->isArrayTy() || ArgTy->isVectorTy())
      return false;

    EVT ArgVT = TLI.getValueType(DL, ArgTy);
    if (!ArgVT.isSimple()) return false;
    switch (ArgVT.getSimpleVT().SimpleTy) {
    case MVT::i8:
    case MVT::i16:
    case MVT::i32:
      break;
    default:
      return false;
    }
  }

  static const MCPhysReg GPRArgRegs[] = {
    ARM::R0, ARM::R1, ARM::R2, ARM::R3
  };

  const TargetRegisterClass *RC = &ARM::rGPRRegClass;
  for (const Argument &Arg : F->args()) {
    unsigned ArgNo = Arg.getArgNo();
    unsigned SrcReg = GPRArgRegs[ArgNo];
    unsigned DstReg = FuncInfo.MF->addLiveIn(SrcReg, RC);
    // FIXME: Unfortunately it's necessary to emit a copy from the livein copy.
    // Without this, EmitLiveInCopies may eliminate the livein if its only
    // use is a bitcast (which isn't turned into an instruction).
    unsigned ResultReg = createResultReg(RC);
    BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
            TII.get(TargetOpcode::COPY),
            ResultReg).addReg(DstReg, getKillRegState(true));
    updateValueMap(&Arg, ResultReg);
  }

  return true;
}

namespace llvm {

  FastISel *ARM::createFastISel(FunctionLoweringInfo &funcInfo,
                                const TargetLibraryInfo *libInfo) {
    if (funcInfo.MF->getSubtarget<ARMSubtarget>().useFastISel())
      return new ARMFastISel(funcInfo, libInfo);

    return nullptr;
  }

} // end namespace llvm
