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

#include "ARC.h"
#include "ARCTargetMachine.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/SelectionDAG.h"
#include "llvm/CodeGen/SelectionDAGISel.h"
#include "llvm/IR/CallingConv.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetLowering.h"

using namespace llvm;

/// ARCDAGToDAGISel - ARC specific code to select ARC machine
/// instructions for SelectionDAG operations.
namespace {

class ARCDAGToDAGISel : public SelectionDAGISel {
public:
  ARCDAGToDAGISel(ARCTargetMachine &TM, CodeGenOpt::Level OptLevel)
      : SelectionDAGISel(TM, OptLevel) {}

  void Select(SDNode *N) override;

  // Complex Pattern Selectors.
  bool SelectFrameADDR_ri(SDValue Addr, SDValue &Base, SDValue &Offset);
  bool SelectAddrModeS9(SDValue Addr, SDValue &Base, SDValue &Offset);
  bool SelectAddrModeImm(SDValue Addr, SDValue &Base, SDValue &Offset);
  bool SelectAddrModeFar(SDValue Addr, SDValue &Base, SDValue &Offset);
  bool SelectCMOVPred(SDValue N, SDValue &Pred, SDValue &Reg) {
    const ConstantSDNode *CN = cast<ConstantSDNode>(N);
    Pred = CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(N), MVT::i32);
    Reg = CurDAG->getRegister(ARC::STATUS32, MVT::i32);
    return true;
  }

  StringRef getPassName() const override {
    return "ARC DAG->DAG Pattern Instruction Selection";
  }

// Include the pieces autogenerated from the target description.
#include "ARCGenDAGISel.inc"
};

} // end anonymous namespace

/// This pass converts a legalized DAG into a ARC-specific DAG, ready for
/// instruction scheduling.
FunctionPass *llvm::createARCISelDag(ARCTargetMachine &TM,
                                     CodeGenOpt::Level OptLevel) {
  return new ARCDAGToDAGISel(TM, OptLevel);
}

bool ARCDAGToDAGISel::SelectAddrModeImm(SDValue Addr, SDValue &Base,
                                        SDValue &Offset) {
  if (Addr.getOpcode() == ARCISD::GAWRAPPER) {
    Base = Addr.getOperand(0);
    Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
    return true;
  }
  return false;
}

bool ARCDAGToDAGISel::SelectAddrModeS9(SDValue Addr, SDValue &Base,
                                       SDValue &Offset) {
  if (Addr.getOpcode() == ARCISD::GAWRAPPER) {
    return false;
  }

  if (Addr.getOpcode() != ISD::ADD && Addr.getOpcode() != ISD::SUB &&
      !CurDAG->isBaseWithConstantOffset(Addr)) {
    if (Addr.getOpcode() == ISD::FrameIndex) {
      // Match frame index.
      int FI = cast<FrameIndexSDNode>(Addr)->getIndex();
      Base = CurDAG->getTargetFrameIndex(
          FI, TLI->getPointerTy(CurDAG->getDataLayout()));
    } else {
      Base = Addr;
    }
    Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
    return true;
  }

  if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) {
    int32_t RHSC = RHS->getSExtValue();
    if (Addr.getOpcode() == ISD::SUB)
      RHSC = -RHSC;

    // Do we need more than 9 bits to encode?
    if (!isInt<9>(RHSC))
      return false;
    Base = Addr.getOperand(0);
    if (Base.getOpcode() == ISD::FrameIndex) {
      int FI = cast<FrameIndexSDNode>(Base)->getIndex();
      Base = CurDAG->getTargetFrameIndex(
          FI, TLI->getPointerTy(CurDAG->getDataLayout()));
    }
    Offset = CurDAG->getTargetConstant(RHSC, SDLoc(Addr), MVT::i32);
    return true;
  }
  Base = Addr;
  Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
  return true;
}

bool ARCDAGToDAGISel::SelectAddrModeFar(SDValue Addr, SDValue &Base,
                                        SDValue &Offset) {
  if (SelectAddrModeS9(Addr, Base, Offset))
    return false;
  if (Addr.getOpcode() == ARCISD::GAWRAPPER) {
    return false;
  }
  if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) {
    int32_t RHSC = RHS->getSExtValue();
    if (Addr.getOpcode() == ISD::SUB)
      RHSC = -RHSC;
    Base = Addr.getOperand(0);
    Offset = CurDAG->getTargetConstant(RHSC, SDLoc(Addr), MVT::i32);
    return true;
  }
  return false;
}

// Is this a legal frame index addressing expression.
bool ARCDAGToDAGISel::SelectFrameADDR_ri(SDValue Addr, SDValue &Base,
                                         SDValue &Offset) {
  FrameIndexSDNode *FIN = nullptr;
  if ((FIN = dyn_cast<FrameIndexSDNode>(Addr))) {
    Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
    Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
    return true;
  }
  if (Addr.getOpcode() == ISD::ADD) {
    ConstantSDNode *CN = nullptr;
    if ((FIN = dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) &&
        (CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) &&
        (CN->getSExtValue() % 4 == 0 && CN->getSExtValue() >= 0)) {
      // Constant positive word offset from frame index
      Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
      Offset =
          CurDAG->getTargetConstant(CN->getSExtValue(), SDLoc(Addr), MVT::i32);
      return true;
    }
  }
  return false;
}

void ARCDAGToDAGISel::Select(SDNode *N) {
  switch (N->getOpcode()) {
  case ISD::Constant: {
    uint64_t CVal = cast<ConstantSDNode>(N)->getZExtValue();
    ReplaceNode(N, CurDAG->getMachineNode(
                       isInt<12>(CVal) ? ARC::MOV_rs12 : ARC::MOV_rlimm,
                       SDLoc(N), MVT::i32,
                       CurDAG->getTargetConstant(CVal, SDLoc(N), MVT::i32)));
    return;
  }
  }
  SelectCode(N);
}
