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