//===- DAGISelEmitter.cpp - Generate an instruction selector --------------===//
//
// 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 tablegen backend emits a DAG instruction selector.
//
//===----------------------------------------------------------------------===//

#include "Common/CodeGenDAGPatterns.h"
#include "Common/CodeGenInstruction.h"
#include "Common/CodeGenTarget.h"
#include "DAGISelMatcher.h"
#include "llvm/Support/Debug.h"
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/TGTimer.h"
#include "llvm/TableGen/TableGenBackend.h"
using namespace llvm;

#define DEBUG_TYPE "dag-isel-emitter"

namespace {
/// DAGISelEmitter - The top-level class which coordinates construction
/// and emission of the instruction selector.
class DAGISelEmitter {
  const RecordKeeper &Records; // Just so we can get at the timing functions.
  const CodeGenDAGPatterns CGP;

public:
  explicit DAGISelEmitter(const RecordKeeper &R) : Records(R), CGP(R, false) {}
  void run(raw_ostream &OS);
};
} // End anonymous namespace

//===----------------------------------------------------------------------===//
// DAGISelEmitter Helper methods
//

/// Compute the number of instructions for this pattern.
/// This is a temporary hack.  We should really include the instruction
/// latencies in this calculation.
static unsigned getResultPatternCost(const TreePatternNode &P,
                                     const CodeGenDAGPatterns &CGP) {
  if (P.isLeaf())
    return 0;

  unsigned Cost = 0;
  const Record *Op = P.getOperator();
  if (Op->isSubClassOf("Instruction")) {
    Cost++;
    const CodeGenInstruction &II = CGP.getTargetInfo().getInstruction(Op);
    if (II.usesCustomInserter)
      Cost += 10;
  }
  for (const TreePatternNode &Child : P.children())
    Cost += getResultPatternCost(Child, CGP);
  return Cost;
}

/// getResultPatternCodeSize - Compute the code size of instructions for this
/// pattern.
static unsigned getResultPatternSize(const TreePatternNode &P,
                                     const CodeGenDAGPatterns &CGP) {
  if (P.isLeaf())
    return 0;

  unsigned Cost = 0;
  const Record *Op = P.getOperator();
  if (Op->isSubClassOf("Instruction")) {
    Cost += Op->getValueAsInt("CodeSize");
  }
  for (const TreePatternNode &Child : P.children())
    Cost += getResultPatternSize(Child, CGP);
  return Cost;
}

namespace {
// PatternSortingPredicate - return true if we prefer to match LHS before RHS.
// In particular, we want to match maximal patterns first and lowest cost within
// a particular complexity first.
struct PatternSortingPredicate {
  PatternSortingPredicate(const CodeGenDAGPatterns &cgp) : CGP(cgp) {}
  const CodeGenDAGPatterns &CGP;

  bool operator()(const PatternToMatch *LHS, const PatternToMatch *RHS) {
    const TreePatternNode &LT = LHS->getSrcPattern();
    const TreePatternNode &RT = RHS->getSrcPattern();

    bool LHSIsVector = false;
    bool RHSIsVector = false;
    bool LHSIsFP = false;
    bool RHSIsFP = false;

    if (LT.getNumTypes() != 0) {
      for (auto [_, VT] : LT.getType(0)) {
        LHSIsVector |= VT.isVector();
        LHSIsFP |= VT.isFloatingPoint();
      }
    }

    if (RT.getNumTypes() != 0) {
      for (auto [_, VT] : RT.getType(0)) {
        RHSIsVector |= VT.isVector();
        RHSIsFP |= VT.isFloatingPoint();
      }
    }

    if (LHSIsVector != RHSIsVector)
      return RHSIsVector;

    if (LHSIsFP != RHSIsFP)
      return RHSIsFP;

    // Otherwise, if the patterns might both match, sort based on complexity,
    // which means that we prefer to match patterns that cover more nodes in the
    // input over nodes that cover fewer.
    int LHSSize = LHS->getPatternComplexity(CGP);
    int RHSSize = RHS->getPatternComplexity(CGP);
    if (LHSSize > RHSSize)
      return true; // LHS -> bigger -> less cost
    if (LHSSize < RHSSize)
      return false;

    // If the patterns have equal complexity, compare generated instruction cost
    unsigned LHSCost = getResultPatternCost(LHS->getDstPattern(), CGP);
    unsigned RHSCost = getResultPatternCost(RHS->getDstPattern(), CGP);
    if (LHSCost < RHSCost)
      return true;
    if (LHSCost > RHSCost)
      return false;

    unsigned LHSPatSize = getResultPatternSize(LHS->getDstPattern(), CGP);
    unsigned RHSPatSize = getResultPatternSize(RHS->getDstPattern(), CGP);
    if (LHSPatSize < RHSPatSize)
      return true;
    if (LHSPatSize > RHSPatSize)
      return false;

    // Sort based on the UID of the pattern, to reflect source order.
    // Note that this is not guaranteed to be unique, since a single source
    // pattern may have been resolved into multiple match patterns due to
    // alternative fragments.  To ensure deterministic output, always use
    // std::stable_sort with this predicate.
    return LHS->getID() < RHS->getID();
  }
};
} // End anonymous namespace

void DAGISelEmitter::run(raw_ostream &OS) {
  TGTimer &Timer = Records.getTimer();
  Timer.startTimer("Parse patterns");
  emitSourceFileHeader("DAG Instruction Selector for the " +
                           CGP.getTargetInfo().getName().str() + " target",
                       OS);

  OS << "// *** NOTE: This file is #included into the middle of the target\n"
     << "// *** instruction selector class.  These functions are really "
     << "methods.\n\n";

  OS << "// If GET_DAGISEL_DECL is #defined with any value, only function\n"
        "// declarations will be included when this file is included.\n"
        "// If GET_DAGISEL_BODY is #defined, its value should be the name of\n"
        "// the instruction selector class. Function bodies will be emitted\n"
        "// and each function's name will be qualified with the name of the\n"
        "// class.\n"
        "//\n"
        "// When neither of the GET_DAGISEL* macros is defined, the functions\n"
        "// are emitted inline.\n\n";

  LLVM_DEBUG(dbgs() << "\n\nALL PATTERNS TO MATCH:\n\n";
             for (CodeGenDAGPatterns::ptm_iterator I = CGP.ptm_begin(),
                  E = CGP.ptm_end();
                  I != E; ++I) {
               dbgs() << "PATTERN: ";
               I->getSrcPattern().dump();
               dbgs() << "\nRESULT:  ";
               I->getDstPattern().dump();
               dbgs() << "\n";
             });

  // Add all the patterns to a temporary list so we can sort them.
  Timer.startTimer("Sort patterns");
  std::vector<const PatternToMatch *> Patterns;
  for (const PatternToMatch &PTM : CGP.ptms())
    Patterns.push_back(&PTM);

  // We want to process the matches in order of minimal cost.  Sort the patterns
  // so the least cost one is at the start.
  llvm::stable_sort(Patterns, PatternSortingPredicate(CGP));

  // Convert each variant of each pattern into a Matcher.
  Timer.startTimer("Convert to matchers");
  SmallVector<MatcherList, 0> PatternMatchers;
  for (const PatternToMatch *PTM : Patterns) {
    for (unsigned Variant = 0;; ++Variant) {
      MatcherList ML = ConvertPatternToMatcherList(*PTM, Variant, CGP);
      if (ML.empty())
        break;
      PatternMatchers.push_back(std::move(ML));
    }
  }

  MatcherList Matchers;
  Matchers.push_front(new ScopeMatcher(std::move(PatternMatchers)));

  Timer.startTimer("Optimize matchers");
  OptimizeMatcher(Matchers, CGP);

  // Matchers->dump();

  Timer.startTimer("Emit matcher table");
  EmitMatcherTable(Matchers, CGP, OS);
}

static TableGen::Emitter::OptClass<DAGISelEmitter>
    X("gen-dag-isel", "Generate a DAG instruction selector");
