//===- ARCISelDAGToDAG.cpp - ARC dag to dag inst selector -------*- C++ -*-===//
//
// 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 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/CodeGen/TargetLowering.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"

using namespace llvm;

#define DEBUG_TYPE "arc-isel"
#define PASS_NAME "ARC DAG->DAG Pattern Instruction Selection"

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

class ARCDAGToDAGISel : public SelectionDAGISel {
public:
  static char ID;

  ARCDAGToDAGISel() = delete;

  ARCDAGToDAGISel(ARCTargetMachine &TM, CodeGenOptLevel OptLevel)
      : SelectionDAGISel(ID, 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);

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

char ARCDAGToDAGISel::ID;

} // end anonymous namespace

INITIALIZE_PASS(ARCDAGToDAGISel, DEBUG_TYPE, PASS_NAME, false, false)

/// This pass converts a legalized DAG into a ARC-specific DAG, ready for
/// instruction scheduling.
FunctionPass *llvm::createARCISelDag(ARCTargetMachine &TM,
                                     CodeGenOptLevel 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);
}
