File indexing completed on 2026-05-10 08:43:17
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef LLVM_ANALYSIS_STACKLIFETIME_H
0010 #define LLVM_ANALYSIS_STACKLIFETIME_H
0011
0012 #include "llvm/ADT/ArrayRef.h"
0013 #include "llvm/ADT/BitVector.h"
0014 #include "llvm/ADT/DenseMap.h"
0015 #include "llvm/ADT/SmallVector.h"
0016 #include "llvm/ADT/StringExtras.h"
0017 #include "llvm/IR/PassManager.h"
0018 #include "llvm/Support/raw_ostream.h"
0019 #include <utility>
0020
0021 namespace llvm {
0022
0023 class AllocaInst;
0024 class BasicBlock;
0025 class Function;
0026 class Instruction;
0027 class IntrinsicInst;
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037 class StackLifetime {
0038
0039
0040
0041 struct BlockLifetimeInfo {
0042 explicit BlockLifetimeInfo(unsigned Size)
0043 : Begin(Size), End(Size), LiveIn(Size), LiveOut(Size) {}
0044
0045
0046 BitVector Begin;
0047
0048
0049 BitVector End;
0050
0051
0052 BitVector LiveIn;
0053
0054
0055 BitVector LiveOut;
0056 };
0057
0058 public:
0059 class LifetimeAnnotationWriter;
0060
0061
0062
0063 class LiveRange {
0064 BitVector Bits;
0065 friend raw_ostream &operator<<(raw_ostream &OS,
0066 const StackLifetime::LiveRange &R);
0067
0068 public:
0069 LiveRange(unsigned Size, bool Set = false) : Bits(Size, Set) {}
0070 void addRange(unsigned Start, unsigned End) { Bits.set(Start, End); }
0071
0072 bool overlaps(const LiveRange &Other) const {
0073 return Bits.anyCommon(Other.Bits);
0074 }
0075
0076 void join(const LiveRange &Other) { Bits |= Other.Bits; }
0077
0078 bool test(unsigned Idx) const { return Bits.test(Idx); }
0079 };
0080
0081
0082
0083 enum class LivenessType {
0084 May,
0085 Must,
0086 };
0087
0088 private:
0089 const Function &F;
0090 LivenessType Type;
0091
0092
0093 using LivenessMap = DenseMap<const BasicBlock *, BlockLifetimeInfo>;
0094 LivenessMap BlockLiveness;
0095
0096
0097
0098 SmallVector<const IntrinsicInst *, 64> Instructions;
0099
0100
0101
0102 DenseMap<const BasicBlock *, std::pair<unsigned, unsigned>> BlockInstRange;
0103
0104 ArrayRef<const AllocaInst *> Allocas;
0105 unsigned NumAllocas;
0106 DenseMap<const AllocaInst *, unsigned> AllocaNumbering;
0107
0108
0109 SmallVector<LiveRange, 8> LiveRanges;
0110
0111
0112
0113 BitVector InterestingAllocas;
0114
0115 struct Marker {
0116 unsigned AllocaNo;
0117 bool IsStart;
0118 };
0119
0120
0121 DenseMap<const BasicBlock *, SmallVector<std::pair<unsigned, Marker>, 4>>
0122 BBMarkers;
0123
0124 bool HasUnknownLifetimeStartOrEnd = false;
0125
0126 void dumpAllocas() const;
0127 void dumpBlockLiveness() const;
0128 void dumpLiveRanges() const;
0129
0130 void collectMarkers();
0131 void calculateLocalLiveness();
0132 void calculateLiveIntervals();
0133
0134 public:
0135 StackLifetime(const Function &F, ArrayRef<const AllocaInst *> Allocas,
0136 LivenessType Type);
0137
0138 void run();
0139
0140 iterator_range<
0141 filter_iterator<ArrayRef<const IntrinsicInst *>::const_iterator,
0142 std::function<bool(const IntrinsicInst *)>>>
0143 getMarkers() const {
0144 std::function<bool(const IntrinsicInst *)> NotNull(
0145 [](const IntrinsicInst *I) -> bool { return I; });
0146 return make_filter_range(Instructions, NotNull);
0147 }
0148
0149
0150
0151
0152 const LiveRange &getLiveRange(const AllocaInst *AI) const;
0153
0154
0155 bool isReachable(const Instruction *I) const;
0156
0157
0158 bool isAliveAfter(const AllocaInst *AI, const Instruction *I) const;
0159
0160
0161
0162 LiveRange getFullLiveRange() const {
0163 return LiveRange(Instructions.size(), true);
0164 }
0165
0166 void print(raw_ostream &O);
0167 };
0168
0169 static inline raw_ostream &operator<<(raw_ostream &OS, const BitVector &V) {
0170 OS << "{";
0171 ListSeparator LS;
0172 for (int Idx = V.find_first(); Idx >= 0; Idx = V.find_next(Idx))
0173 OS << LS << Idx;
0174 OS << "}";
0175 return OS;
0176 }
0177
0178 inline raw_ostream &operator<<(raw_ostream &OS,
0179 const StackLifetime::LiveRange &R) {
0180 return OS << R.Bits;
0181 }
0182
0183
0184 class StackLifetimePrinterPass
0185 : public PassInfoMixin<StackLifetimePrinterPass> {
0186 StackLifetime::LivenessType Type;
0187 raw_ostream &OS;
0188
0189 public:
0190 StackLifetimePrinterPass(raw_ostream &OS, StackLifetime::LivenessType Type)
0191 : Type(Type), OS(OS) {}
0192 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
0193 static bool isRequired() { return true; }
0194 void printPipeline(raw_ostream &OS,
0195 function_ref<StringRef(StringRef)> MapClassName2PassName);
0196 };
0197
0198 }
0199
0200 #endif