#ifndef LLVM_ANALYSIS_STACKLIFETIME_H
#define LLVM_ANALYSIS_STACKLIFETIME_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/IR/PassManager.h"
#include "llvm/Support/raw_ostream.h"
#include <utility>
namespace llvm {
class AllocaInst;
class BasicBlock;
class Function;
class Instruction;
class IntrinsicInst;
class StackLifetime {
struct BlockLifetimeInfo {
explicit BlockLifetimeInfo(unsigned Size)
: Begin(Size), End(Size), LiveIn(Size), LiveOut(Size) {}
BitVector Begin;
BitVector End;
BitVector LiveIn;
BitVector LiveOut;
};
public:
class LifetimeAnnotationWriter;
class LiveRange {
BitVector Bits;
friend raw_ostream &operator<<(raw_ostream &OS,
const StackLifetime::LiveRange &R);
public:
LiveRange(unsigned Size, bool Set = false) : Bits(Size, Set) {}
void addRange(unsigned Start, unsigned End) { Bits.set(Start, End); }
bool overlaps(const LiveRange &Other) const {
return Bits.anyCommon(Other.Bits);
}
void join(const LiveRange &Other) { Bits |= Other.Bits; }
bool test(unsigned Idx) const { return Bits.test(Idx); }
};
enum class LivenessType {
May, Must, };
private:
const Function &F;
LivenessType Type;
using LivenessMap = DenseMap<const BasicBlock *, BlockLifetimeInfo>;
LivenessMap BlockLiveness;
SmallVector<const IntrinsicInst *, 64> Instructions;
DenseMap<const BasicBlock *, std::pair<unsigned, unsigned>> BlockInstRange;
ArrayRef<const AllocaInst *> Allocas;
unsigned NumAllocas;
DenseMap<const AllocaInst *, unsigned> AllocaNumbering;
SmallVector<LiveRange, 8> LiveRanges;
BitVector InterestingAllocas;
struct Marker {
unsigned AllocaNo;
bool IsStart;
};
DenseMap<const BasicBlock *, SmallVector<std::pair<unsigned, Marker>, 4>>
BBMarkers;
bool HasUnknownLifetimeStartOrEnd = false;
void dumpAllocas() const;
void dumpBlockLiveness() const;
void dumpLiveRanges() const;
void collectMarkers();
void calculateLocalLiveness();
void calculateLiveIntervals();
public:
StackLifetime(const Function &F, ArrayRef<const AllocaInst *> Allocas,
LivenessType Type);
void run();
iterator_range<
filter_iterator<ArrayRef<const IntrinsicInst *>::const_iterator,
std::function<bool(const IntrinsicInst *)>>>
getMarkers() const {
std::function<bool(const IntrinsicInst *)> NotNull(
[](const IntrinsicInst *I) -> bool { return I; });
return make_filter_range(Instructions, NotNull);
}
const LiveRange &getLiveRange(const AllocaInst *AI) const;
bool isReachable(const Instruction *I) const;
bool isAliveAfter(const AllocaInst *AI, const Instruction *I) const;
LiveRange getFullLiveRange() const {
return LiveRange(Instructions.size(), true);
}
void print(raw_ostream &O);
};
static inline raw_ostream &operator<<(raw_ostream &OS, const BitVector &V) {
OS << "{";
ListSeparator LS;
for (int Idx = V.find_first(); Idx >= 0; Idx = V.find_next(Idx))
OS << LS << Idx;
OS << "}";
return OS;
}
inline raw_ostream &operator<<(raw_ostream &OS,
const StackLifetime::LiveRange &R) {
return OS << R.Bits;
}
class StackLifetimePrinterPass
: public PassInfoMixin<StackLifetimePrinterPass> {
StackLifetime::LivenessType Type;
raw_ostream &OS;
public:
StackLifetimePrinterPass(raw_ostream &OS, StackLifetime::LivenessType Type)
: Type(Type), OS(OS) {}
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
void printPipeline(raw_ostream &OS,
function_ref<StringRef(StringRef)> MapClassName2PassName);
};
}
#endif