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 
12 #include "llvm/ADT/DepthFirstIterator.h"
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 
27 const StackColoring::LiveRange &StackColoring::getLiveRange(AllocaInst *AI) {
28   return LiveRanges[AllocaNumbering[AI]];
29 }
30 
31 bool StackColoring::readMarker(Instruction *I, bool *IsStart) {
32   auto *II = dyn_cast<IntrinsicInst>(I);
33   if (!II || (II->getIntrinsicID() != Intrinsic::lifetime_start &&
34               II->getIntrinsicID() != Intrinsic::lifetime_end))
35     return false;
36 
37   *IsStart = II->getIntrinsicID() == Intrinsic::lifetime_start;
38   return true;
39 }
40 
41 void StackColoring::removeAllMarkers() {
42   for (auto *I : Markers) {
43     auto *Op = dyn_cast<Instruction>(I->getOperand(1));
44     I->eraseFromParent();
45     // Remove the operand bitcast, too, if it has no more uses left.
46     if (Op && Op->use_empty())
47       Op->eraseFromParent();
48   }
49 }
50 
51 void StackColoring::collectMarkers() {
52   InterestingAllocas.resize(NumAllocas);
53   DenseMap<BasicBlock *, SmallDenseMap<Instruction *, Marker>> BBMarkerSet;
54 
55   // Compute the set of start/end markers per basic block.
56   for (unsigned AllocaNo = 0; AllocaNo < NumAllocas; ++AllocaNo) {
57     AllocaInst *AI = Allocas[AllocaNo];
58     SmallVector<Instruction *, 8> WorkList;
59     WorkList.push_back(AI);
60     while (!WorkList.empty()) {
61       Instruction *I = WorkList.pop_back_val();
62       for (User *U : I->users()) {
63         if (auto *BI = dyn_cast<BitCastInst>(U)) {
64           WorkList.push_back(BI);
65           continue;
66         }
67         auto *UI = dyn_cast<Instruction>(U);
68         if (!UI)
69           continue;
70         bool IsStart;
71         if (!readMarker(UI, &IsStart))
72           continue;
73         if (IsStart)
74           InterestingAllocas.set(AllocaNo);
75         BBMarkerSet[UI->getParent()][UI] = {AllocaNo, IsStart};
76         Markers.push_back(UI);
77       }
78     }
79   }
80 
81   // Compute instruction numbering. Only the following instructions are
82   // considered:
83   // * Basic block entries
84   // * Lifetime markers
85   // For each basic block, compute
86   // * the list of markers in the instruction order
87   // * the sets of allocas whose lifetime starts or ends in this BB
88   DEBUG(dbgs() << "Instructions:\n");
89   unsigned InstNo = 0;
90   for (BasicBlock *BB : depth_first(&F)) {
91     DEBUG(dbgs() << "  " << InstNo << ": BB " << BB->getName() << "\n");
92     unsigned BBStart = InstNo++;
93 
94     BlockLifetimeInfo &BlockInfo = BlockLiveness[BB];
95     BlockInfo.Begin.resize(NumAllocas);
96     BlockInfo.End.resize(NumAllocas);
97     BlockInfo.LiveIn.resize(NumAllocas);
98     BlockInfo.LiveOut.resize(NumAllocas);
99 
100     auto &BlockMarkerSet = BBMarkerSet[BB];
101     if (BlockMarkerSet.empty()) {
102       unsigned BBEnd = InstNo;
103       BlockInstRange[BB] = std::make_pair(BBStart, BBEnd);
104       continue;
105     }
106 
107     auto ProcessMarker = [&](Instruction *I, const Marker &M) {
108       DEBUG(dbgs() << "  " << InstNo << ":  "
109                    << (M.IsStart ? "start " : "end   ") << M.AllocaNo << ", "
110                    << *I << "\n");
111 
112       BBMarkers[BB].push_back({InstNo, M});
113 
114       InstructionNumbering[I] = InstNo++;
115 
116       if (M.IsStart) {
117         if (BlockInfo.End.test(M.AllocaNo))
118           BlockInfo.End.reset(M.AllocaNo);
119         BlockInfo.Begin.set(M.AllocaNo);
120       } else {
121         if (BlockInfo.Begin.test(M.AllocaNo))
122           BlockInfo.Begin.reset(M.AllocaNo);
123         BlockInfo.End.set(M.AllocaNo);
124       }
125     };
126 
127     if (BlockMarkerSet.size() == 1) {
128       ProcessMarker(BlockMarkerSet.begin()->getFirst(),
129                     BlockMarkerSet.begin()->getSecond());
130     } else {
131       // Scan the BB to determine the marker order.
132       for (Instruction &I : *BB) {
133         auto It = BlockMarkerSet.find(&I);
134         if (It == BlockMarkerSet.end())
135           continue;
136         ProcessMarker(&I, It->getSecond());
137       }
138     }
139 
140     unsigned BBEnd = InstNo;
141     BlockInstRange[BB] = std::make_pair(BBStart, BBEnd);
142   }
143   NumInst = InstNo;
144 }
145 
146 void StackColoring::calculateLocalLiveness() {
147   bool changed = true;
148   while (changed) {
149     changed = false;
150 
151     for (BasicBlock *BB : depth_first(&F)) {
152       BlockLifetimeInfo &BlockInfo = BlockLiveness[BB];
153 
154       // Compute LiveIn by unioning together the LiveOut sets of all preds.
155       BitVector LocalLiveIn;
156       for (auto *PredBB : predecessors(BB)) {
157         LivenessMap::const_iterator I = BlockLiveness.find(PredBB);
158         assert(I != BlockLiveness.end() && "Predecessor not found");
159         LocalLiveIn |= I->second.LiveOut;
160       }
161 
162       // Compute LiveOut by subtracting out lifetimes that end in this
163       // block, then adding in lifetimes that begin in this block.  If
164       // we have both BEGIN and END markers in the same basic block
165       // then we know that the BEGIN marker comes after the END,
166       // because we already handle the case where the BEGIN comes
167       // before the END when collecting the markers (and building the
168       // BEGIN/END vectors).
169       BitVector LocalLiveOut = LocalLiveIn;
170       LocalLiveOut.reset(BlockInfo.End);
171       LocalLiveOut |= BlockInfo.Begin;
172 
173       // Update block LiveIn set, noting whether it has changed.
174       if (LocalLiveIn.test(BlockInfo.LiveIn)) {
175         changed = true;
176         BlockInfo.LiveIn |= LocalLiveIn;
177       }
178 
179       // Update block LiveOut set, noting whether it has changed.
180       if (LocalLiveOut.test(BlockInfo.LiveOut)) {
181         changed = true;
182         BlockInfo.LiveOut |= LocalLiveOut;
183       }
184     }
185   } // while changed.
186 }
187 
188 void StackColoring::calculateLiveIntervals() {
189   for (auto IT : BlockLiveness) {
190     BasicBlock *BB = IT.getFirst();
191     BlockLifetimeInfo &BlockInfo = IT.getSecond();
192     unsigned BBStart, BBEnd;
193     std::tie(BBStart, BBEnd) = BlockInstRange[BB];
194 
195     BitVector Started, Ended;
196     Started.resize(NumAllocas);
197     Ended.resize(NumAllocas);
198     SmallVector<unsigned, 8> Start;
199     Start.resize(NumAllocas);
200 
201     // LiveIn ranges start at the first instruction.
202     for (unsigned AllocaNo = 0; AllocaNo < NumAllocas; ++AllocaNo) {
203       if (BlockInfo.LiveIn.test(AllocaNo)) {
204         Started.set(AllocaNo);
205         Start[AllocaNo] = BBStart;
206       }
207     }
208 
209     for (auto &It : BBMarkers[BB]) {
210       unsigned InstNo = It.first;
211       bool IsStart = It.second.IsStart;
212       unsigned AllocaNo = It.second.AllocaNo;
213 
214       if (IsStart) {
215         assert(!Started.test(AllocaNo));
216         Started.set(AllocaNo);
217         Ended.reset(AllocaNo);
218         Start[AllocaNo] = InstNo;
219       } else {
220         assert(!Ended.test(AllocaNo));
221         if (Started.test(AllocaNo)) {
222           LiveRanges[AllocaNo].AddRange(Start[AllocaNo], InstNo);
223           Started.reset(AllocaNo);
224         }
225         Ended.set(AllocaNo);
226       }
227     }
228 
229     for (unsigned AllocaNo = 0; AllocaNo < NumAllocas; ++AllocaNo)
230       if (Started.test(AllocaNo))
231         LiveRanges[AllocaNo].AddRange(Start[AllocaNo], BBEnd);
232   }
233 }
234 
235 LLVM_DUMP_METHOD void StackColoring::dumpAllocas() {
236   dbgs() << "Allocas:\n";
237   for (unsigned AllocaNo = 0; AllocaNo < NumAllocas; ++AllocaNo)
238     dbgs() << "  " << AllocaNo << ": " << *Allocas[AllocaNo] << "\n";
239 }
240 
241 LLVM_DUMP_METHOD void StackColoring::dumpBlockLiveness() {
242   dbgs() << "Block liveness:\n";
243   for (auto IT : BlockLiveness) {
244     BasicBlock *BB = IT.getFirst();
245     BlockLifetimeInfo &BlockInfo = BlockLiveness[BB];
246     auto BlockRange = BlockInstRange[BB];
247     dbgs() << "  BB [" << BlockRange.first << ", " << BlockRange.second
248            << "): begin " << BlockInfo.Begin << ", end " << BlockInfo.End
249            << ", livein " << BlockInfo.LiveIn << ", liveout "
250            << BlockInfo.LiveOut << "\n";
251   }
252 }
253 
254 LLVM_DUMP_METHOD void StackColoring::dumpLiveRanges() {
255   dbgs() << "Alloca liveness:\n";
256   for (unsigned AllocaNo = 0; AllocaNo < NumAllocas; ++AllocaNo) {
257     LiveRange &Range = LiveRanges[AllocaNo];
258     dbgs() << "  " << AllocaNo << ": " << Range << "\n";
259   }
260 }
261 
262 void StackColoring::run() {
263   DEBUG(dumpAllocas());
264 
265   for (unsigned I = 0; I < NumAllocas; ++I)
266     AllocaNumbering[Allocas[I]] = I;
267   LiveRanges.resize(NumAllocas);
268 
269   collectMarkers();
270 
271   if (!ClColoring) {
272     for (auto &R : LiveRanges) {
273       R.SetMaximum(1);
274       R.AddRange(0, 1);
275     }
276     return;
277   }
278 
279   for (auto &R : LiveRanges)
280     R.SetMaximum(NumInst);
281   for (unsigned I = 0; I < NumAllocas; ++I)
282     if (!InterestingAllocas.test(I))
283       LiveRanges[I] = getFullLiveRange();
284 
285   calculateLocalLiveness();
286   DEBUG(dumpBlockLiveness());
287   calculateLiveIntervals();
288   DEBUG(dumpLiveRanges());
289 }
290