//===-- 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/TargetSubtargetInfo.h"
#include "llvm/InitializePasses.h"
#include "llvm/Pass.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 = nullptr;
  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;

  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) {
  LLVM_DEBUG(dbgs() << "********** COMPUTING STACKMAP LIVENESS: "
                    << MF.getName() << " **********\n");
  bool HasChanged = false;
  // For all basic blocks in the function.
  for (auto &MBB : MF) {
    LLVM_DEBUG(dbgs() << "****** BB " << MBB.getName() << " ******\n");
    LiveRegs.init(*TRI);
    LiveRegs.addLiveOuts(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;
}
