LLVM  4.0.0
SafeStackColoring.cpp
Go to the documentation of this file.
1 //===-- SafeStackColoring.cpp - SafeStack frame coloring -------*- C++ -*--===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "SafeStackColoring.h"
11 
13 #include "llvm/IR/CFG.h"
14 #include "llvm/IR/Instructions.h"
15 #include "llvm/IR/IntrinsicInst.h"
16 #include "llvm/Support/Debug.h"
17 
18 using namespace llvm;
19 using namespace llvm::safestack;
20 
21 #define DEBUG_TYPE "safestackcoloring"
22 
23 static cl::opt<bool> ClColoring("safe-stack-coloring",
24  cl::desc("enable safe stack coloring"),
25  cl::Hidden, cl::init(true));
26 
28  const auto IT = AllocaNumbering.find(AI);
29  assert(IT != AllocaNumbering.end());
30  return LiveRanges[IT->second];
31 }
32 
33 bool StackColoring::readMarker(Instruction *I, bool *IsStart) {
34  auto *II = dyn_cast<IntrinsicInst>(I);
35  if (!II || (II->getIntrinsicID() != Intrinsic::lifetime_start &&
36  II->getIntrinsicID() != Intrinsic::lifetime_end))
37  return false;
38 
39  *IsStart = II->getIntrinsicID() == Intrinsic::lifetime_start;
40  return true;
41 }
42 
44  for (auto *I : Markers) {
45  auto *Op = dyn_cast<Instruction>(I->getOperand(1));
46  I->eraseFromParent();
47  // Remove the operand bitcast, too, if it has no more uses left.
48  if (Op && Op->use_empty())
49  Op->eraseFromParent();
50  }
51 }
52 
53 void StackColoring::collectMarkers() {
54  InterestingAllocas.resize(NumAllocas);
56 
57  // Compute the set of start/end markers per basic block.
58  for (unsigned AllocaNo = 0; AllocaNo < NumAllocas; ++AllocaNo) {
59  AllocaInst *AI = Allocas[AllocaNo];
61  WorkList.push_back(AI);
62  while (!WorkList.empty()) {
63  Instruction *I = WorkList.pop_back_val();
64  for (User *U : I->users()) {
65  if (auto *BI = dyn_cast<BitCastInst>(U)) {
66  WorkList.push_back(BI);
67  continue;
68  }
69  auto *UI = dyn_cast<Instruction>(U);
70  if (!UI)
71  continue;
72  bool IsStart;
73  if (!readMarker(UI, &IsStart))
74  continue;
75  if (IsStart)
76  InterestingAllocas.set(AllocaNo);
77  BBMarkerSet[UI->getParent()][UI] = {AllocaNo, IsStart};
78  Markers.push_back(UI);
79  }
80  }
81  }
82 
83  // Compute instruction numbering. Only the following instructions are
84  // considered:
85  // * Basic block entries
86  // * Lifetime markers
87  // For each basic block, compute
88  // * the list of markers in the instruction order
89  // * the sets of allocas whose lifetime starts or ends in this BB
90  DEBUG(dbgs() << "Instructions:\n");
91  unsigned InstNo = 0;
92  for (BasicBlock *BB : depth_first(&F)) {
93  DEBUG(dbgs() << " " << InstNo << ": BB " << BB->getName() << "\n");
94  unsigned BBStart = InstNo++;
95 
96  BlockLifetimeInfo &BlockInfo = BlockLiveness[BB];
97  BlockInfo.Begin.resize(NumAllocas);
98  BlockInfo.End.resize(NumAllocas);
99  BlockInfo.LiveIn.resize(NumAllocas);
100  BlockInfo.LiveOut.resize(NumAllocas);
101 
102  auto &BlockMarkerSet = BBMarkerSet[BB];
103  if (BlockMarkerSet.empty()) {
104  unsigned BBEnd = InstNo;
105  BlockInstRange[BB] = std::make_pair(BBStart, BBEnd);
106  continue;
107  }
108 
109  auto ProcessMarker = [&](Instruction *I, const Marker &M) {
110  DEBUG(dbgs() << " " << InstNo << ": "
111  << (M.IsStart ? "start " : "end ") << M.AllocaNo << ", "
112  << *I << "\n");
113 
114  BBMarkers[BB].push_back({InstNo, M});
115 
116  InstructionNumbering[I] = InstNo++;
117 
118  if (M.IsStart) {
119  if (BlockInfo.End.test(M.AllocaNo))
120  BlockInfo.End.reset(M.AllocaNo);
121  BlockInfo.Begin.set(M.AllocaNo);
122  } else {
123  if (BlockInfo.Begin.test(M.AllocaNo))
124  BlockInfo.Begin.reset(M.AllocaNo);
125  BlockInfo.End.set(M.AllocaNo);
126  }
127  };
128 
129  if (BlockMarkerSet.size() == 1) {
130  ProcessMarker(BlockMarkerSet.begin()->getFirst(),
131  BlockMarkerSet.begin()->getSecond());
132  } else {
133  // Scan the BB to determine the marker order.
134  for (Instruction &I : *BB) {
135  auto It = BlockMarkerSet.find(&I);
136  if (It == BlockMarkerSet.end())
137  continue;
138  ProcessMarker(&I, It->getSecond());
139  }
140  }
141 
142  unsigned BBEnd = InstNo;
143  BlockInstRange[BB] = std::make_pair(BBStart, BBEnd);
144  }
145  NumInst = InstNo;
146 }
147 
148 void StackColoring::calculateLocalLiveness() {
149  bool changed = true;
150  while (changed) {
151  changed = false;
152 
153  for (BasicBlock *BB : depth_first(&F)) {
154  BlockLifetimeInfo &BlockInfo = BlockLiveness[BB];
155 
156  // Compute LiveIn by unioning together the LiveOut sets of all preds.
157  BitVector LocalLiveIn;
158  for (auto *PredBB : predecessors(BB)) {
159  LivenessMap::const_iterator I = BlockLiveness.find(PredBB);
160  assert(I != BlockLiveness.end() && "Predecessor not found");
161  LocalLiveIn |= I->second.LiveOut;
162  }
163 
164  // Compute LiveOut by subtracting out lifetimes that end in this
165  // block, then adding in lifetimes that begin in this block. If
166  // we have both BEGIN and END markers in the same basic block
167  // then we know that the BEGIN marker comes after the END,
168  // because we already handle the case where the BEGIN comes
169  // before the END when collecting the markers (and building the
170  // BEGIN/END vectors).
171  BitVector LocalLiveOut = LocalLiveIn;
172  LocalLiveOut.reset(BlockInfo.End);
173  LocalLiveOut |= BlockInfo.Begin;
174 
175  // Update block LiveIn set, noting whether it has changed.
176  if (LocalLiveIn.test(BlockInfo.LiveIn)) {
177  changed = true;
178  BlockInfo.LiveIn |= LocalLiveIn;
179  }
180 
181  // Update block LiveOut set, noting whether it has changed.
182  if (LocalLiveOut.test(BlockInfo.LiveOut)) {
183  changed = true;
184  BlockInfo.LiveOut |= LocalLiveOut;
185  }
186  }
187  } // while changed.
188 }
189 
190 void StackColoring::calculateLiveIntervals() {
191  for (auto IT : BlockLiveness) {
192  BasicBlock *BB = IT.getFirst();
193  BlockLifetimeInfo &BlockInfo = IT.getSecond();
194  unsigned BBStart, BBEnd;
195  std::tie(BBStart, BBEnd) = BlockInstRange[BB];
196 
197  BitVector Started, Ended;
198  Started.resize(NumAllocas);
199  Ended.resize(NumAllocas);
201  Start.resize(NumAllocas);
202 
203  // LiveIn ranges start at the first instruction.
204  for (unsigned AllocaNo = 0; AllocaNo < NumAllocas; ++AllocaNo) {
205  if (BlockInfo.LiveIn.test(AllocaNo)) {
206  Started.set(AllocaNo);
207  Start[AllocaNo] = BBStart;
208  }
209  }
210 
211  for (auto &It : BBMarkers[BB]) {
212  unsigned InstNo = It.first;
213  bool IsStart = It.second.IsStart;
214  unsigned AllocaNo = It.second.AllocaNo;
215 
216  if (IsStart) {
217  assert(!Started.test(AllocaNo) || Start[AllocaNo] == BBStart);
218  if (!Started.test(AllocaNo)) {
219  Started.set(AllocaNo);
220  Ended.reset(AllocaNo);
221  Start[AllocaNo] = InstNo;
222  }
223  } else {
224  assert(!Ended.test(AllocaNo));
225  if (Started.test(AllocaNo)) {
226  LiveRanges[AllocaNo].AddRange(Start[AllocaNo], InstNo);
227  Started.reset(AllocaNo);
228  }
229  Ended.set(AllocaNo);
230  }
231  }
232 
233  for (unsigned AllocaNo = 0; AllocaNo < NumAllocas; ++AllocaNo)
234  if (Started.test(AllocaNo))
235  LiveRanges[AllocaNo].AddRange(Start[AllocaNo], BBEnd);
236  }
237 }
238 
239 LLVM_DUMP_METHOD void StackColoring::dumpAllocas() {
240  dbgs() << "Allocas:\n";
241  for (unsigned AllocaNo = 0; AllocaNo < NumAllocas; ++AllocaNo)
242  dbgs() << " " << AllocaNo << ": " << *Allocas[AllocaNo] << "\n";
243 }
244 
245 LLVM_DUMP_METHOD void StackColoring::dumpBlockLiveness() {
246  dbgs() << "Block liveness:\n";
247  for (auto IT : BlockLiveness) {
248  BasicBlock *BB = IT.getFirst();
249  BlockLifetimeInfo &BlockInfo = BlockLiveness[BB];
250  auto BlockRange = BlockInstRange[BB];
251  dbgs() << " BB [" << BlockRange.first << ", " << BlockRange.second
252  << "): begin " << BlockInfo.Begin << ", end " << BlockInfo.End
253  << ", livein " << BlockInfo.LiveIn << ", liveout "
254  << BlockInfo.LiveOut << "\n";
255  }
256 }
257 
258 LLVM_DUMP_METHOD void StackColoring::dumpLiveRanges() {
259  dbgs() << "Alloca liveness:\n";
260  for (unsigned AllocaNo = 0; AllocaNo < NumAllocas; ++AllocaNo) {
261  LiveRange &Range = LiveRanges[AllocaNo];
262  dbgs() << " " << AllocaNo << ": " << Range << "\n";
263  }
264 }
265 
267  DEBUG(dumpAllocas());
268 
269  for (unsigned I = 0; I < NumAllocas; ++I)
270  AllocaNumbering[Allocas[I]] = I;
271  LiveRanges.resize(NumAllocas);
272 
273  collectMarkers();
274 
275  if (!ClColoring) {
276  for (auto &R : LiveRanges) {
277  R.SetMaximum(1);
278  R.AddRange(0, 1);
279  }
280  return;
281  }
282 
283  for (auto &R : LiveRanges)
284  R.SetMaximum(NumInst);
285  for (unsigned I = 0; I < NumAllocas; ++I)
286  if (!InterestingAllocas.test(I))
287  LiveRanges[I] = getFullLiveRange();
288 
289  calculateLocalLiveness();
290  DEBUG(dumpBlockLiveness());
291  calculateLiveIntervals();
292  DEBUG(dumpLiveRanges());
293 }
void resize(unsigned N, bool t=false)
resize - Grow or shrink the bitvector.
Definition: BitVector.h:193
static cl::opt< ITMode > IT(cl::desc("IT block support"), cl::Hidden, cl::init(DefaultIT), cl::ZeroOrMore, cl::values(clEnumValN(DefaultIT,"arm-default-it","Generate IT block based on arch"), clEnumValN(RestrictedIT,"arm-restrict-it","Disallow deprecated IT based on ARMv8"), clEnumValN(NoRestrictedIT,"arm-no-restrict-it","Allow IT blocks based on ARMv7")))
SymbolTableList< Instruction >::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
Definition: Instruction.cpp:76
BitVector & set()
Definition: BitVector.h:219
This class represents a set of interesting instructions where an alloca is live.
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds...
Definition: Compiler.h:450
const LiveRange & getLiveRange(AllocaInst *AI)
Returns a set of "interesting" instructions where the given alloca is live.
This class represents the liveness of a register, stack slot, etc.
Definition: LiveInterval.h:153
LLVM_NODISCARD bool empty() const
Definition: SmallVector.h:60
LiveRange getFullLiveRange()
Returns a live range that represents an alloca that is live throughout the entire function...
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:395
LLVM Basic Block Representation.
Definition: BasicBlock.h:51
BitVector & reset()
Definition: BitVector.h:260
Value * getOperand(unsigned i) const
Definition: User.h:145
static cl::opt< bool > ClColoring("safe-stack-coloring", cl::desc("enable safe stack coloring"), cl::Hidden, cl::init(true))
DenseMapIterator< KeyT, ValueT, KeyInfoT, BucketT, true > const_iterator
Definition: DenseMap.h:64
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:843
bool test(unsigned Idx) const
Definition: BitVector.h:323
LLVM_NODISCARD T pop_back_val()
Definition: SmallVector.h:382
pred_range predecessors(BasicBlock *BB)
Definition: IR/CFG.h:110
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:132
iterator_range< user_iterator > users()
Definition: Value.h:370
#define I(x, y, z)
Definition: MD5.cpp:54
iterator end()
Definition: DenseMap.h:69
iterator find(const KeyT &Val)
Definition: DenseMap.h:127
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
Definition: Casting.h:287
iterator_range< df_iterator< T > > depth_first(const T &G)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
#define DEBUG(X)
Definition: Debug.h:100
A wrapper class for inspecting calls to intrinsic functions.
Definition: IntrinsicInst.h:44
an instruction to allocate memory on the stack
Definition: Instructions.h:60
void resize(size_type N)
Definition: SmallVector.h:352