//===- StackLifetime.cpp - Alloca Lifetime 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
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/StackLifetime.h"
#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/IR/AssemblyAnnotationWriter.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/CFG.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Value.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/FormattedStream.h"
#include <algorithm>
#include <tuple>

using namespace llvm;

#define DEBUG_TYPE "stack-lifetime"

const StackLifetime::LiveRange &
StackLifetime::getLiveRange(const AllocaInst *AI) const {
  const auto IT = AllocaNumbering.find(AI);
  assert(IT != AllocaNumbering.end());
  return LiveRanges[IT->second];
}

bool StackLifetime::isReachable(const Instruction *I) const {
  return BlockInstRange.contains(I->getParent());
}

bool StackLifetime::isAliveAfter(const AllocaInst *AI,
                                 const Instruction *I) const {
  const BasicBlock *BB = I->getParent();
  auto ItBB = BlockInstRange.find(BB);
  assert(ItBB != BlockInstRange.end() && "Unreachable is not expected");

  // Search the block for the first instruction following 'I'.
  auto It = std::upper_bound(Instructions.begin() + ItBB->getSecond().first + 1,
                             Instructions.begin() + ItBB->getSecond().second, I,
                             [](const Instruction *L, const Instruction *R) {
                               return L->comesBefore(R);
                             });
  --It;
  unsigned InstNum = It - Instructions.begin();
  return getLiveRange(AI).test(InstNum);
}

// Returns unique alloca annotated by lifetime marker only if
// markers has the same size and points to the alloca start.
static const AllocaInst *findMatchingAlloca(const IntrinsicInst &II,
                                            const DataLayout &DL) {
  const AllocaInst *AI = findAllocaForValue(II.getArgOperand(1), true);
  if (!AI)
    return nullptr;

  auto AllocaSize = AI->getAllocationSize(DL);
  if (!AllocaSize)
    return nullptr;

  auto *Size = dyn_cast<ConstantInt>(II.getArgOperand(0));
  if (!Size)
    return nullptr;
  int64_t LifetimeSize = Size->getSExtValue();

  if (LifetimeSize != -1 && uint64_t(LifetimeSize) != *AllocaSize)
    return nullptr;

  return AI;
}

void StackLifetime::collectMarkers() {
  InterestingAllocas.resize(NumAllocas);
  DenseMap<const BasicBlock *, SmallDenseMap<const IntrinsicInst *, Marker>>
      BBMarkerSet;

  const DataLayout &DL = F.getParent()->getDataLayout();

  // Compute the set of start/end markers per basic block.
  for (const BasicBlock *BB : depth_first(&F)) {
    for (const Instruction &I : *BB) {
      const IntrinsicInst *II = dyn_cast<IntrinsicInst>(&I);
      if (!II || !II->isLifetimeStartOrEnd())
        continue;
      const AllocaInst *AI = findMatchingAlloca(*II, DL);
      if (!AI) {
        HasUnknownLifetimeStartOrEnd = true;
        continue;
      }
      auto It = AllocaNumbering.find(AI);
      if (It == AllocaNumbering.end())
        continue;
      auto AllocaNo = It->second;
      bool IsStart = II->getIntrinsicID() == Intrinsic::lifetime_start;
      if (IsStart)
        InterestingAllocas.set(AllocaNo);
      BBMarkerSet[BB][II] = {AllocaNo, IsStart};
    }
  }

  // Compute instruction numbering. Only the following instructions are
  // considered:
  // * Basic block entries
  // * Lifetime markers
  // For each basic block, compute
  // * the list of markers in the instruction order
  // * the sets of allocas whose lifetime starts or ends in this BB
  LLVM_DEBUG(dbgs() << "Instructions:\n");
  for (const BasicBlock *BB : depth_first(&F)) {
    LLVM_DEBUG(dbgs() << "  " << Instructions.size() << ": BB " << BB->getName()
                      << "\n");
    auto BBStart = Instructions.size();
    Instructions.push_back(nullptr);

    BlockLifetimeInfo &BlockInfo =
        BlockLiveness.try_emplace(BB, NumAllocas).first->getSecond();

    auto &BlockMarkerSet = BBMarkerSet[BB];
    if (BlockMarkerSet.empty()) {
      BlockInstRange[BB] = std::make_pair(BBStart, Instructions.size());
      continue;
    }

    auto ProcessMarker = [&](const IntrinsicInst *I, const Marker &M) {
      LLVM_DEBUG(dbgs() << "  " << Instructions.size() << ":  "
                        << (M.IsStart ? "start " : "end   ") << M.AllocaNo
                        << ", " << *I << "\n");

      BBMarkers[BB].push_back({Instructions.size(), M});
      Instructions.push_back(I);

      if (M.IsStart) {
        BlockInfo.End.reset(M.AllocaNo);
        BlockInfo.Begin.set(M.AllocaNo);
      } else {
        BlockInfo.Begin.reset(M.AllocaNo);
        BlockInfo.End.set(M.AllocaNo);
      }
    };

    if (BlockMarkerSet.size() == 1) {
      ProcessMarker(BlockMarkerSet.begin()->getFirst(),
                    BlockMarkerSet.begin()->getSecond());
    } else {
      // Scan the BB to determine the marker order.
      for (const Instruction &I : *BB) {
        const IntrinsicInst *II = dyn_cast<IntrinsicInst>(&I);
        if (!II)
          continue;
        auto It = BlockMarkerSet.find(II);
        if (It == BlockMarkerSet.end())
          continue;
        ProcessMarker(II, It->getSecond());
      }
    }

    BlockInstRange[BB] = std::make_pair(BBStart, Instructions.size());
  }
}

void StackLifetime::calculateLocalLiveness() {
  bool Changed = true;

  // LiveIn, LiveOut and BitsIn have a different meaning deppends on type.
  // ::Maybe true bits represent "may be alive" allocas, ::Must true bits
  // represent "may be dead". After the loop we will convert ::Must bits from
  // "may be dead" to "must be alive".
  while (Changed) {
    // TODO: Consider switching to worklist instead of traversing entire graph.
    Changed = false;

    for (const BasicBlock *BB : depth_first(&F)) {
      BlockLifetimeInfo &BlockInfo = BlockLiveness.find(BB)->getSecond();

      // Compute BitsIn by unioning together the LiveOut sets of all preds.
      BitVector BitsIn;
      for (const auto *PredBB : predecessors(BB)) {
        LivenessMap::const_iterator I = BlockLiveness.find(PredBB);
        // If a predecessor is unreachable, ignore it.
        if (I == BlockLiveness.end())
          continue;
        BitsIn |= I->second.LiveOut;
      }

      // Everything is "may be dead" for entry without predecessors.
      if (Type == LivenessType::Must && BitsIn.empty())
        BitsIn.resize(NumAllocas, true);

      // Update block LiveIn set, noting whether it has changed.
      if (BitsIn.test(BlockInfo.LiveIn)) {
        BlockInfo.LiveIn |= BitsIn;
      }

      // Compute LiveOut by subtracting out lifetimes that end in this
      // block, then adding in lifetimes that begin in this block.  If
      // we have both BEGIN and END markers in the same basic block
      // then we know that the BEGIN marker comes after the END,
      // because we already handle the case where the BEGIN comes
      // before the END when collecting the markers (and building the
      // BEGIN/END vectors).
      switch (Type) {
      case LivenessType::May:
        BitsIn.reset(BlockInfo.End);
        // "may be alive" is set by lifetime start.
        BitsIn |= BlockInfo.Begin;
        break;
      case LivenessType::Must:
        BitsIn.reset(BlockInfo.Begin);
        // "may be dead" is set by lifetime end.
        BitsIn |= BlockInfo.End;
        break;
      }

      // Update block LiveOut set, noting whether it has changed.
      if (BitsIn.test(BlockInfo.LiveOut)) {
        Changed = true;
        BlockInfo.LiveOut |= BitsIn;
      }
    }
  } // while changed.

  if (Type == LivenessType::Must) {
    // Convert from "may be dead" to "must be alive".
    for (auto &[BB, BlockInfo] : BlockLiveness) {
      BlockInfo.LiveIn.flip();
      BlockInfo.LiveOut.flip();
    }
  }
}

void StackLifetime::calculateLiveIntervals() {
  for (auto IT : BlockLiveness) {
    const BasicBlock *BB = IT.getFirst();
    BlockLifetimeInfo &BlockInfo = IT.getSecond();
    unsigned BBStart, BBEnd;
    std::tie(BBStart, BBEnd) = BlockInstRange[BB];

    BitVector Started, Ended;
    Started.resize(NumAllocas);
    Ended.resize(NumAllocas);
    SmallVector<unsigned, 8> Start;
    Start.resize(NumAllocas);

    // LiveIn ranges start at the first instruction.
    for (unsigned AllocaNo = 0; AllocaNo < NumAllocas; ++AllocaNo) {
      if (BlockInfo.LiveIn.test(AllocaNo)) {
        Started.set(AllocaNo);
        Start[AllocaNo] = BBStart;
      }
    }

    for (auto &It : BBMarkers[BB]) {
      unsigned InstNo = It.first;
      bool IsStart = It.second.IsStart;
      unsigned AllocaNo = It.second.AllocaNo;

      if (IsStart) {
        if (!Started.test(AllocaNo)) {
          Started.set(AllocaNo);
          Ended.reset(AllocaNo);
          Start[AllocaNo] = InstNo;
        }
      } else {
        if (Started.test(AllocaNo)) {
          LiveRanges[AllocaNo].addRange(Start[AllocaNo], InstNo);
          Started.reset(AllocaNo);
        }
        Ended.set(AllocaNo);
      }
    }

    for (unsigned AllocaNo = 0; AllocaNo < NumAllocas; ++AllocaNo)
      if (Started.test(AllocaNo))
        LiveRanges[AllocaNo].addRange(Start[AllocaNo], BBEnd);
  }
}

#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
LLVM_DUMP_METHOD void StackLifetime::dumpAllocas() const {
  dbgs() << "Allocas:\n";
  for (unsigned AllocaNo = 0; AllocaNo < NumAllocas; ++AllocaNo)
    dbgs() << "  " << AllocaNo << ": " << *Allocas[AllocaNo] << "\n";
}

LLVM_DUMP_METHOD void StackLifetime::dumpBlockLiveness() const {
  dbgs() << "Block liveness:\n";
  for (auto IT : BlockLiveness) {
    const BasicBlock *BB = IT.getFirst();
    const BlockLifetimeInfo &BlockInfo = BlockLiveness.find(BB)->getSecond();
    auto BlockRange = BlockInstRange.find(BB)->getSecond();
    dbgs() << "  BB (" << BB->getName() << ") [" << BlockRange.first << ", " << BlockRange.second
           << "): begin " << BlockInfo.Begin << ", end " << BlockInfo.End
           << ", livein " << BlockInfo.LiveIn << ", liveout "
           << BlockInfo.LiveOut << "\n";
  }
}

LLVM_DUMP_METHOD void StackLifetime::dumpLiveRanges() const {
  dbgs() << "Alloca liveness:\n";
  for (unsigned AllocaNo = 0; AllocaNo < NumAllocas; ++AllocaNo)
    dbgs() << "  " << AllocaNo << ": " << LiveRanges[AllocaNo] << "\n";
}
#endif

StackLifetime::StackLifetime(const Function &F,
                             ArrayRef<const AllocaInst *> Allocas,
                             LivenessType Type)
    : F(F), Type(Type), Allocas(Allocas), NumAllocas(Allocas.size()) {
  LLVM_DEBUG(dumpAllocas());

  for (unsigned I = 0; I < NumAllocas; ++I)
    AllocaNumbering[Allocas[I]] = I;

  collectMarkers();
}

void StackLifetime::run() {
  if (HasUnknownLifetimeStartOrEnd) {
    // There is marker which we can't assign to a specific alloca, so we
    // fallback to the most conservative results for the type.
    switch (Type) {
    case LivenessType::May:
      LiveRanges.resize(NumAllocas, getFullLiveRange());
      break;
    case LivenessType::Must:
      LiveRanges.resize(NumAllocas, LiveRange(Instructions.size()));
      break;
    }
    return;
  }

  LiveRanges.resize(NumAllocas, LiveRange(Instructions.size()));
  for (unsigned I = 0; I < NumAllocas; ++I)
    if (!InterestingAllocas.test(I))
      LiveRanges[I] = getFullLiveRange();

  calculateLocalLiveness();
  LLVM_DEBUG(dumpBlockLiveness());
  calculateLiveIntervals();
  LLVM_DEBUG(dumpLiveRanges());
}

class StackLifetime::LifetimeAnnotationWriter
    : public AssemblyAnnotationWriter {
  const StackLifetime &SL;

  void printInstrAlive(unsigned InstrNo, formatted_raw_ostream &OS) {
    SmallVector<StringRef, 16> Names;
    for (const auto &KV : SL.AllocaNumbering) {
      if (SL.LiveRanges[KV.getSecond()].test(InstrNo))
        Names.push_back(KV.getFirst()->getName());
    }
    llvm::sort(Names);
    OS << "  ; Alive: <" << llvm::join(Names, " ") << ">\n";
  }

  void emitBasicBlockStartAnnot(const BasicBlock *BB,
                                formatted_raw_ostream &OS) override {
    auto ItBB = SL.BlockInstRange.find(BB);
    if (ItBB == SL.BlockInstRange.end())
      return; // Unreachable.
    printInstrAlive(ItBB->getSecond().first, OS);
  }

  void printInfoComment(const Value &V, formatted_raw_ostream &OS) override {
    const Instruction *Instr = dyn_cast<Instruction>(&V);
    if (!Instr || !SL.isReachable(Instr))
      return;

    SmallVector<StringRef, 16> Names;
    for (const auto &KV : SL.AllocaNumbering) {
      if (SL.isAliveAfter(KV.getFirst(), Instr))
        Names.push_back(KV.getFirst()->getName());
    }
    llvm::sort(Names);
    OS << "\n  ; Alive: <" << llvm::join(Names, " ") << ">\n";
  }

public:
  LifetimeAnnotationWriter(const StackLifetime &SL) : SL(SL) {}
};

void StackLifetime::print(raw_ostream &OS) {
  LifetimeAnnotationWriter AAW(*this);
  F.print(OS, &AAW);
}

PreservedAnalyses StackLifetimePrinterPass::run(Function &F,
                                                FunctionAnalysisManager &AM) {
  SmallVector<const AllocaInst *, 8> Allocas;
  for (auto &I : instructions(F))
    if (const AllocaInst *AI = dyn_cast<AllocaInst>(&I))
      Allocas.push_back(AI);
  StackLifetime SL(F, Allocas, Type);
  SL.run();
  SL.print(OS);
  return PreservedAnalyses::all();
}

void StackLifetimePrinterPass::printPipeline(
    raw_ostream &OS, function_ref<StringRef(StringRef)> MapClassName2PassName) {
  static_cast<PassInfoMixin<StackLifetimePrinterPass> *>(this)->printPipeline(
      OS, MapClassName2PassName);
  OS << '<';
  switch (Type) {
  case StackLifetime::LivenessType::May:
    OS << "may";
    break;
  case StackLifetime::LivenessType::Must:
    OS << "must";
    break;
  }
  OS << '>';
}
