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