//===-- StackMapLivenessAnalysis.cpp - StackMap live Out Analysis ----------===//
//
// 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 implements the StackMap Liveness analysis pass. The pass calculates
// the liveness for each basic block in a function and attaches the register
// live-out information to a stackmap or patchpoint intrinsic if present.
//
//===----------------------------------------------------------------------===//

#include "llvm/ADT/Statistic.h"
#include "llvm/CodeGen/LivePhysRegs.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/InitializePasses.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"

using namespace llvm;

#define DEBUG_TYPE "stackmaps"

static cl::opt<bool> EnablePatchPointLiveness(
    "enable-patchpoint-liveness", cl::Hidden, cl::init(true),
    cl::desc("Enable PatchPoint Liveness Analysis Pass"));

STATISTIC(NumStackMapFuncVisited, "Number of functions visited");
STATISTIC(NumStackMapFuncSkipped, "Number of functions skipped");
STATISTIC(NumBBsVisited,          "Number of basic blocks visited");
STATISTIC(NumBBsHaveNoStackmap,   "Number of basic blocks with no stackmap");
STATISTIC(NumStackMaps,           "Number of StackMaps visited");

namespace {
/// This pass calculates the liveness information for each basic block in
/// a function and attaches the register live-out information to a patchpoint
/// intrinsic if present.
///
/// This pass can be disabled via the -enable-patchpoint-liveness=false flag.
/// The pass skips functions that don't have any patchpoint intrinsics. The
/// information provided by this pass is optional and not required by the
/// aformentioned intrinsic to function.
class StackMapLiveness : public MachineFunctionPass {
  const TargetRegisterInfo *TRI;
  LivePhysRegs LiveRegs;

public:
  static char ID;

  /// Default construct and initialize the pass.
  StackMapLiveness();

  /// Tell the pass manager which passes we depend on and what
  /// information we preserve.
  void getAnalysisUsage(AnalysisUsage &AU) const override;

  MachineFunctionProperties getRequiredProperties() const override {
    return MachineFunctionProperties().set(
        MachineFunctionProperties::Property::NoVRegs);
  }

  /// Calculate the liveness information for the given machine function.
  bool runOnMachineFunction(MachineFunction &MF) override;

private:
  /// Performs the actual liveness calculation for the function.
  bool calculateLiveness(MachineFunction &MF);

  /// Add the current register live set to the instruction.
  void addLiveOutSetToMI(MachineFunction &MF, MachineInstr &MI);

  /// Create a register mask and initialize it with the registers from
  /// the register live set.
  uint32_t *createRegisterMask(MachineFunction &MF) const;
};
} // namespace

char StackMapLiveness::ID = 0;
char &llvm::StackMapLivenessID = StackMapLiveness::ID;
INITIALIZE_PASS(StackMapLiveness, "stackmap-liveness",
                "StackMap Liveness Analysis", false, false)

/// Default construct and initialize the pass.
StackMapLiveness::StackMapLiveness() : MachineFunctionPass(ID) {
  initializeStackMapLivenessPass(*PassRegistry::getPassRegistry());
}

/// Tell the pass manager which passes we depend on and what information we
/// preserve.
void StackMapLiveness::getAnalysisUsage(AnalysisUsage &AU) const {
  // We preserve all information.
  AU.setPreservesAll();
  AU.setPreservesCFG();
  MachineFunctionPass::getAnalysisUsage(AU);
}

/// Calculate the liveness information for the given machine function.
bool StackMapLiveness::runOnMachineFunction(MachineFunction &MF) {
  if (!EnablePatchPointLiveness)
    return false;

  LLVM_DEBUG(dbgs() << "********** COMPUTING STACKMAP LIVENESS: "
                    << MF.getName() << " **********\n");
  TRI = MF.getSubtarget().getRegisterInfo();
  ++NumStackMapFuncVisited;

  // Skip this function if there are no patchpoints to process.
  if (!MF.getFrameInfo().hasPatchPoint()) {
    ++NumStackMapFuncSkipped;
    return false;
  }
  return calculateLiveness(MF);
}

/// Performs the actual liveness calculation for the function.
bool StackMapLiveness::calculateLiveness(MachineFunction &MF) {
  bool HasChanged = false;
  // For all basic blocks in the function.
  for (auto &MBB : MF) {
    LLVM_DEBUG(dbgs() << "****** BB " << MBB.getName() << " ******\n");
    LiveRegs.init(*TRI);
    // FIXME: This should probably be addLiveOuts().
    LiveRegs.addLiveOutsNoPristines(MBB);
    bool HasStackMap = false;
    // Reverse iterate over all instructions and add the current live register
    // set to an instruction if we encounter a patchpoint instruction.
    for (MachineInstr &MI : llvm::reverse(MBB)) {
      if (MI.getOpcode() == TargetOpcode::PATCHPOINT) {
        addLiveOutSetToMI(MF, MI);
        HasChanged = true;
        HasStackMap = true;
        ++NumStackMaps;
      }
      LLVM_DEBUG(dbgs() << "   " << LiveRegs << "   " << MI);
      LiveRegs.stepBackward(MI);
    }
    ++NumBBsVisited;
    if (!HasStackMap)
      ++NumBBsHaveNoStackmap;
  }
  return HasChanged;
}

/// Add the current register live set to the instruction.
void StackMapLiveness::addLiveOutSetToMI(MachineFunction &MF,
                                         MachineInstr &MI) {
  uint32_t *Mask = createRegisterMask(MF);
  MachineOperand MO = MachineOperand::CreateRegLiveOut(Mask);
  MI.addOperand(MF, MO);
}

/// Create a register mask and initialize it with the registers from the
/// register live set.
uint32_t *StackMapLiveness::createRegisterMask(MachineFunction &MF) const {
  // The mask is owned and cleaned up by the Machine Function.
  uint32_t *Mask = MF.allocateRegMask();
  for (auto Reg : LiveRegs)
    Mask[Reg / 32] |= 1U << (Reg % 32);

  // Give the target a chance to adjust the mask.
  TRI->adjustStackMapLiveOutMask(Mask);

  return Mask;
}
