//===--- HexagonBranchRelaxation.cpp - Identify and relax long jumps ------===//
//
// 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
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "hexagon-brelax"

#include "Hexagon.h"
#include "HexagonInstrInfo.h"
#include "HexagonSubtarget.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/Pass.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>
#include <cstdint>
#include <cstdlib>
#include <iterator>

using namespace llvm;

// Since we have no exact knowledge of code layout, allow some safety buffer
// for jump target. This is measured in bytes.
static cl::opt<uint32_t> BranchRelaxSafetyBuffer("branch-relax-safety-buffer",
  cl::init(200), cl::Hidden, cl::ZeroOrMore, cl::desc("safety buffer size"));

namespace llvm {

  FunctionPass *createHexagonBranchRelaxation();
  void initializeHexagonBranchRelaxationPass(PassRegistry&);

} // end namespace llvm

namespace {

  struct HexagonBranchRelaxation : public MachineFunctionPass {
  public:
    static char ID;

    HexagonBranchRelaxation() : MachineFunctionPass(ID) {
      initializeHexagonBranchRelaxationPass(*PassRegistry::getPassRegistry());
    }

    bool runOnMachineFunction(MachineFunction &MF) override;

    StringRef getPassName() const override {
      return "Hexagon Branch Relaxation";
    }

    void getAnalysisUsage(AnalysisUsage &AU) const override {
      AU.setPreservesCFG();
      MachineFunctionPass::getAnalysisUsage(AU);
    }

  private:
    const HexagonInstrInfo *HII;
    const HexagonRegisterInfo *HRI;

    bool relaxBranches(MachineFunction &MF);
    void computeOffset(MachineFunction &MF,
          DenseMap<MachineBasicBlock*, unsigned> &BlockToInstOffset);
    bool reGenerateBranch(MachineFunction &MF,
          DenseMap<MachineBasicBlock*, unsigned> &BlockToInstOffset);
    bool isJumpOutOfRange(MachineInstr &MI,
          DenseMap<MachineBasicBlock*, unsigned> &BlockToInstOffset);
  };

  char HexagonBranchRelaxation::ID = 0;

} // end anonymous namespace

INITIALIZE_PASS(HexagonBranchRelaxation, "hexagon-brelax",
                "Hexagon Branch Relaxation", false, false)

FunctionPass *llvm::createHexagonBranchRelaxation() {
  return new HexagonBranchRelaxation();
}

bool HexagonBranchRelaxation::runOnMachineFunction(MachineFunction &MF) {
  LLVM_DEBUG(dbgs() << "****** Hexagon Branch Relaxation ******\n");

  auto &HST = MF.getSubtarget<HexagonSubtarget>();
  HII = HST.getInstrInfo();
  HRI = HST.getRegisterInfo();

  bool Changed = false;
  Changed = relaxBranches(MF);
  return Changed;
}

void HexagonBranchRelaxation::computeOffset(MachineFunction &MF,
      DenseMap<MachineBasicBlock*, unsigned> &OffsetMap) {
  // offset of the current instruction from the start.
  unsigned InstOffset = 0;
  for (auto &B : MF) {
    if (B.getAlignment() != Align::None()) {
      // Although we don't know the exact layout of the final code, we need
      // to account for alignment padding somehow. This heuristic pads each
      // aligned basic block according to the alignment value.
      InstOffset = alignTo(InstOffset, B.getAlignment());
    }
    OffsetMap[&B] = InstOffset;
    for (auto &MI : B.instrs()) {
      InstOffset += HII->getSize(MI);
      // Assume that all extendable branches will be extended.
      if (MI.isBranch() && HII->isExtendable(MI))
        InstOffset += HEXAGON_INSTR_SIZE;
    }
  }
}

/// relaxBranches - For Hexagon, if the jump target/loop label is too far from
/// the jump/loop instruction then, we need to make sure that we have constant
/// extenders set for jumps and loops.

/// There are six iterations in this phase. It's self explanatory below.
bool HexagonBranchRelaxation::relaxBranches(MachineFunction &MF) {
  // Compute the offset of each basic block
  // offset of the current instruction from the start.
  // map for each instruction to the beginning of the function
  DenseMap<MachineBasicBlock*, unsigned> BlockToInstOffset;
  computeOffset(MF, BlockToInstOffset);

  return reGenerateBranch(MF, BlockToInstOffset);
}

/// Check if a given instruction is:
/// - a jump to a distant target
/// - that exceeds its immediate range
/// If both conditions are true, it requires constant extension.
bool HexagonBranchRelaxation::isJumpOutOfRange(MachineInstr &MI,
      DenseMap<MachineBasicBlock*, unsigned> &BlockToInstOffset) {
  MachineBasicBlock &B = *MI.getParent();
  auto FirstTerm = B.getFirstInstrTerminator();
  if (FirstTerm == B.instr_end())
    return false;

  if (HII->isExtended(MI))
    return false;

  unsigned InstOffset = BlockToInstOffset[&B];
  unsigned Distance = 0;

  // To save time, estimate exact position of a branch instruction
  // as one at the end of the MBB.
  // Number of instructions times typical instruction size.
  InstOffset += HII->nonDbgBBSize(&B) * HEXAGON_INSTR_SIZE;

  MachineBasicBlock *TBB = nullptr, *FBB = nullptr;
  SmallVector<MachineOperand, 4> Cond;

  // Try to analyze this branch.
  if (HII->analyzeBranch(B, TBB, FBB, Cond, false)) {
    // Could not analyze it. See if this is something we can recognize.
    // If it is a NVJ, it should always have its target in
    // a fixed location.
    if (HII->isNewValueJump(*FirstTerm))
      TBB = FirstTerm->getOperand(HII->getCExtOpNum(*FirstTerm)).getMBB();
  }
  if (TBB && &MI == &*FirstTerm) {
    Distance = std::abs((long long)InstOffset - BlockToInstOffset[TBB])
                + BranchRelaxSafetyBuffer;
    return !HII->isJumpWithinBranchRange(*FirstTerm, Distance);
  }
  if (FBB) {
    // Look for second terminator.
    auto SecondTerm = std::next(FirstTerm);
    assert(SecondTerm != B.instr_end() &&
          (SecondTerm->isBranch() || SecondTerm->isCall()) &&
          "Bad second terminator");
    if (&MI != &*SecondTerm)
      return false;
    // Analyze the second branch in the BB.
    Distance = std::abs((long long)InstOffset - BlockToInstOffset[FBB])
                + BranchRelaxSafetyBuffer;
    return !HII->isJumpWithinBranchRange(*SecondTerm, Distance);
  }
  return false;
}

bool HexagonBranchRelaxation::reGenerateBranch(MachineFunction &MF,
      DenseMap<MachineBasicBlock*, unsigned> &BlockToInstOffset) {
  bool Changed = false;

  for (auto &B : MF) {
    for (auto &MI : B) {
      if (!MI.isBranch() || !isJumpOutOfRange(MI, BlockToInstOffset))
        continue;
      LLVM_DEBUG(dbgs() << "Long distance jump. isExtendable("
                        << HII->isExtendable(MI) << ") isConstExtended("
                        << HII->isConstExtended(MI) << ") " << MI);

      // Since we have not merged HW loops relaxation into
      // this code (yet), soften our approach for the moment.
      if (!HII->isExtendable(MI) && !HII->isExtended(MI)) {
        LLVM_DEBUG(dbgs() << "\tUnderimplemented relax branch instruction.\n");
      } else {
        // Find which operand is expandable.
        int ExtOpNum = HII->getCExtOpNum(MI);
        MachineOperand &MO = MI.getOperand(ExtOpNum);
        // This need to be something we understand. So far we assume all
        // branches have only MBB address as expandable field.
        // If it changes, this will need to be expanded.
        assert(MO.isMBB() && "Branch with unknown expandable field type");
        // Mark given operand as extended.
        MO.addTargetFlag(HexagonII::HMOTF_ConstExtended);
        Changed = true;
      }
    }
  }
  return Changed;
}
