1*2cab237bSDimitry Andric //===- SafeStackColoring.h - SafeStack frame coloring ----------*- C++ -*--===// 23ca95b02SDimitry Andric // 33ca95b02SDimitry Andric // The LLVM Compiler Infrastructure 43ca95b02SDimitry Andric // 53ca95b02SDimitry Andric // This file is distributed under the University of Illinois Open Source 63ca95b02SDimitry Andric // License. See LICENSE.TXT for details. 73ca95b02SDimitry Andric // 83ca95b02SDimitry Andric //===----------------------------------------------------------------------===// 93ca95b02SDimitry Andric 103ca95b02SDimitry Andric #ifndef LLVM_LIB_CODEGEN_SAFESTACKCOLORING_H 113ca95b02SDimitry Andric #define LLVM_LIB_CODEGEN_SAFESTACKCOLORING_H 123ca95b02SDimitry Andric 13*2cab237bSDimitry Andric #include "llvm/ADT/ArrayRef.h" 143ca95b02SDimitry Andric #include "llvm/ADT/BitVector.h" 153ca95b02SDimitry Andric #include "llvm/ADT/DenseMap.h" 163ca95b02SDimitry Andric #include "llvm/ADT/SmallVector.h" 17*2cab237bSDimitry Andric #include "llvm/IR/Instructions.h" 18*2cab237bSDimitry Andric #include "llvm/Support/raw_ostream.h" 19*2cab237bSDimitry Andric #include <cassert> 20*2cab237bSDimitry Andric #include <utility> 213ca95b02SDimitry Andric 223ca95b02SDimitry Andric namespace llvm { 23*2cab237bSDimitry Andric 24*2cab237bSDimitry Andric class BasicBlock; 25*2cab237bSDimitry Andric class Function; 26*2cab237bSDimitry Andric class Instruction; 273ca95b02SDimitry Andric 283ca95b02SDimitry Andric namespace safestack { 29*2cab237bSDimitry Andric 303ca95b02SDimitry Andric /// Compute live ranges of allocas. 313ca95b02SDimitry Andric /// Live ranges are represented as sets of "interesting" instructions, which are 323ca95b02SDimitry Andric /// defined as instructions that may start or end an alloca's lifetime. These 333ca95b02SDimitry Andric /// are: 343ca95b02SDimitry Andric /// * lifetime.start and lifetime.end intrinsics 353ca95b02SDimitry Andric /// * first instruction of any basic block 363ca95b02SDimitry Andric /// Interesting instructions are numbered in the depth-first walk of the CFG, 373ca95b02SDimitry Andric /// and in the program order inside each basic block. 383ca95b02SDimitry Andric class StackColoring { 393ca95b02SDimitry Andric /// A class representing liveness information for a single basic block. 403ca95b02SDimitry Andric /// Each bit in the BitVector represents the liveness property 413ca95b02SDimitry Andric /// for a different stack slot. 423ca95b02SDimitry Andric struct BlockLifetimeInfo { 433ca95b02SDimitry Andric /// Which slots BEGINs in each basic block. 443ca95b02SDimitry Andric BitVector Begin; 45*2cab237bSDimitry Andric 463ca95b02SDimitry Andric /// Which slots ENDs in each basic block. 473ca95b02SDimitry Andric BitVector End; 48*2cab237bSDimitry Andric 493ca95b02SDimitry Andric /// Which slots are marked as LIVE_IN, coming into each basic block. 503ca95b02SDimitry Andric BitVector LiveIn; 51*2cab237bSDimitry Andric 523ca95b02SDimitry Andric /// Which slots are marked as LIVE_OUT, coming out of each basic block. 533ca95b02SDimitry Andric BitVector LiveOut; 543ca95b02SDimitry Andric }; 553ca95b02SDimitry Andric 563ca95b02SDimitry Andric public: 573ca95b02SDimitry Andric /// This class represents a set of interesting instructions where an alloca is 583ca95b02SDimitry Andric /// live. 593ca95b02SDimitry Andric struct LiveRange { 603ca95b02SDimitry Andric BitVector bv; 61*2cab237bSDimitry Andric SetMaximumLiveRange623ca95b02SDimitry Andric void SetMaximum(int size) { bv.resize(size); } AddRangeLiveRange633ca95b02SDimitry Andric void AddRange(unsigned start, unsigned end) { bv.set(start, end); } 64*2cab237bSDimitry Andric OverlapsLiveRange653ca95b02SDimitry Andric bool Overlaps(const LiveRange &Other) const { 663ca95b02SDimitry Andric return bv.anyCommon(Other.bv); 673ca95b02SDimitry Andric } 68*2cab237bSDimitry Andric JoinLiveRange693ca95b02SDimitry Andric void Join(const LiveRange &Other) { bv |= Other.bv; } 703ca95b02SDimitry Andric }; 713ca95b02SDimitry Andric 723ca95b02SDimitry Andric private: 733ca95b02SDimitry Andric Function &F; 743ca95b02SDimitry Andric 753ca95b02SDimitry Andric /// Maps active slots (per bit) for each basic block. 76*2cab237bSDimitry Andric using LivenessMap = DenseMap<BasicBlock *, BlockLifetimeInfo>; 773ca95b02SDimitry Andric LivenessMap BlockLiveness; 783ca95b02SDimitry Andric 793ca95b02SDimitry Andric /// Number of interesting instructions. 80*2cab237bSDimitry Andric int NumInst = -1; 81*2cab237bSDimitry Andric 823ca95b02SDimitry Andric /// Numeric ids for interesting instructions. 833ca95b02SDimitry Andric DenseMap<Instruction *, unsigned> InstructionNumbering; 84*2cab237bSDimitry Andric 853ca95b02SDimitry Andric /// A range [Start, End) of instruction ids for each basic block. 863ca95b02SDimitry Andric /// Instructions inside each BB have monotonic and consecutive ids. 873ca95b02SDimitry Andric DenseMap<const BasicBlock *, std::pair<unsigned, unsigned>> BlockInstRange; 883ca95b02SDimitry Andric 893ca95b02SDimitry Andric ArrayRef<AllocaInst *> Allocas; 903ca95b02SDimitry Andric unsigned NumAllocas; 913ca95b02SDimitry Andric DenseMap<AllocaInst *, unsigned> AllocaNumbering; 92*2cab237bSDimitry Andric 933ca95b02SDimitry Andric /// LiveRange for allocas. 943ca95b02SDimitry Andric SmallVector<LiveRange, 8> LiveRanges; 953ca95b02SDimitry Andric 963ca95b02SDimitry Andric /// The set of allocas that have at least one lifetime.start. All other 973ca95b02SDimitry Andric /// allocas get LiveRange that corresponds to the entire function. 983ca95b02SDimitry Andric BitVector InterestingAllocas; 993ca95b02SDimitry Andric SmallVector<Instruction *, 8> Markers; 1003ca95b02SDimitry Andric 1013ca95b02SDimitry Andric struct Marker { 1023ca95b02SDimitry Andric unsigned AllocaNo; 1033ca95b02SDimitry Andric bool IsStart; 1043ca95b02SDimitry Andric }; 1053ca95b02SDimitry Andric 1063ca95b02SDimitry Andric /// List of {InstNo, {AllocaNo, IsStart}} for each BB, ordered by InstNo. 1073ca95b02SDimitry Andric DenseMap<BasicBlock *, SmallVector<std::pair<unsigned, Marker>, 4>> BBMarkers; 1083ca95b02SDimitry Andric 1093ca95b02SDimitry Andric void dumpAllocas(); 1103ca95b02SDimitry Andric void dumpBlockLiveness(); 1113ca95b02SDimitry Andric void dumpLiveRanges(); 1123ca95b02SDimitry Andric 1133ca95b02SDimitry Andric bool readMarker(Instruction *I, bool *IsStart); 1143ca95b02SDimitry Andric void collectMarkers(); 1153ca95b02SDimitry Andric void calculateLocalLiveness(); 1163ca95b02SDimitry Andric void calculateLiveIntervals(); 1173ca95b02SDimitry Andric 1183ca95b02SDimitry Andric public: StackColoring(Function & F,ArrayRef<AllocaInst * > Allocas)1193ca95b02SDimitry Andric StackColoring(Function &F, ArrayRef<AllocaInst *> Allocas) 120*2cab237bSDimitry Andric : F(F), Allocas(Allocas), NumAllocas(Allocas.size()) {} 1213ca95b02SDimitry Andric 1223ca95b02SDimitry Andric void run(); 1233ca95b02SDimitry Andric void removeAllMarkers(); 1243ca95b02SDimitry Andric 1253ca95b02SDimitry Andric /// Returns a set of "interesting" instructions where the given alloca is 1263ca95b02SDimitry Andric /// live. Not all instructions in a function are interesting: we pick a set 1273ca95b02SDimitry Andric /// that is large enough for LiveRange::Overlaps to be correct. 1283ca95b02SDimitry Andric const LiveRange &getLiveRange(AllocaInst *AI); 1293ca95b02SDimitry Andric 1303ca95b02SDimitry Andric /// Returns a live range that represents an alloca that is live throughout the 1313ca95b02SDimitry Andric /// entire function. getFullLiveRange()1323ca95b02SDimitry Andric LiveRange getFullLiveRange() { 1333ca95b02SDimitry Andric assert(NumInst >= 0); 1343ca95b02SDimitry Andric LiveRange R; 1353ca95b02SDimitry Andric R.SetMaximum(NumInst); 1363ca95b02SDimitry Andric R.AddRange(0, NumInst); 1373ca95b02SDimitry Andric return R; 1383ca95b02SDimitry Andric } 1393ca95b02SDimitry Andric }; 1403ca95b02SDimitry Andric 1413ca95b02SDimitry Andric static inline raw_ostream &operator<<(raw_ostream &OS, const BitVector &V) { 1423ca95b02SDimitry Andric OS << "{"; 1433ca95b02SDimitry Andric int idx = V.find_first(); 1443ca95b02SDimitry Andric bool first = true; 1453ca95b02SDimitry Andric while (idx >= 0) { 1463ca95b02SDimitry Andric if (!first) { 1473ca95b02SDimitry Andric OS << ", "; 1483ca95b02SDimitry Andric } 1493ca95b02SDimitry Andric first = false; 1503ca95b02SDimitry Andric OS << idx; 1513ca95b02SDimitry Andric idx = V.find_next(idx); 1523ca95b02SDimitry Andric } 1533ca95b02SDimitry Andric OS << "}"; 1543ca95b02SDimitry Andric return OS; 1553ca95b02SDimitry Andric } 1563ca95b02SDimitry Andric 1573ca95b02SDimitry Andric static inline raw_ostream &operator<<(raw_ostream &OS, 1583ca95b02SDimitry Andric const StackColoring::LiveRange &R) { 1593ca95b02SDimitry Andric return OS << R.bv; 1603ca95b02SDimitry Andric } 1613ca95b02SDimitry Andric 162*2cab237bSDimitry Andric } // end namespace safestack 163*2cab237bSDimitry Andric 164*2cab237bSDimitry Andric } // end namespace llvm 1653ca95b02SDimitry Andric 1663ca95b02SDimitry Andric #endif // LLVM_LIB_CODEGEN_SAFESTACKCOLORING_H 167