12cab237bSDimitry Andric //===- SafeStackColoring.cpp - SafeStack frame coloring -------------------===//
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 #include "SafeStackColoring.h"
112cab237bSDimitry Andric #include "llvm/ADT/BitVector.h"
122cab237bSDimitry Andric #include "llvm/ADT/DenseMap.h"
133ca95b02SDimitry Andric #include "llvm/ADT/DepthFirstIterator.h"
142cab237bSDimitry Andric #include "llvm/ADT/SmallVector.h"
154ba319b5SDimitry Andric #include "llvm/Config/llvm-config.h"
162cab237bSDimitry Andric #include "llvm/IR/BasicBlock.h"
173ca95b02SDimitry Andric #include "llvm/IR/CFG.h"
182cab237bSDimitry Andric #include "llvm/IR/Instruction.h"
193ca95b02SDimitry Andric #include "llvm/IR/Instructions.h"
203ca95b02SDimitry Andric #include "llvm/IR/IntrinsicInst.h"
212cab237bSDimitry Andric #include "llvm/IR/Intrinsics.h"
222cab237bSDimitry Andric #include "llvm/IR/User.h"
232cab237bSDimitry Andric #include "llvm/Support/Casting.h"
242cab237bSDimitry Andric #include "llvm/Support/CommandLine.h"
252cab237bSDimitry Andric #include "llvm/Support/Compiler.h"
263ca95b02SDimitry Andric #include "llvm/Support/Debug.h"
272cab237bSDimitry Andric #include "llvm/Support/raw_ostream.h"
282cab237bSDimitry Andric #include <cassert>
292cab237bSDimitry Andric #include <tuple>
302cab237bSDimitry Andric #include <utility>
313ca95b02SDimitry Andric
323ca95b02SDimitry Andric using namespace llvm;
333ca95b02SDimitry Andric using namespace llvm::safestack;
343ca95b02SDimitry Andric
353ca95b02SDimitry Andric #define DEBUG_TYPE "safestackcoloring"
363ca95b02SDimitry Andric
37d8866befSDimitry Andric // Disabled by default due to PR32143.
383ca95b02SDimitry Andric static cl::opt<bool> ClColoring("safe-stack-coloring",
393ca95b02SDimitry Andric cl::desc("enable safe stack coloring"),
40d8866befSDimitry Andric cl::Hidden, cl::init(false));
413ca95b02SDimitry Andric
getLiveRange(AllocaInst * AI)423ca95b02SDimitry Andric const StackColoring::LiveRange &StackColoring::getLiveRange(AllocaInst *AI) {
436c4bc1bdSDimitry Andric const auto IT = AllocaNumbering.find(AI);
446c4bc1bdSDimitry Andric assert(IT != AllocaNumbering.end());
456c4bc1bdSDimitry Andric return LiveRanges[IT->second];
463ca95b02SDimitry Andric }
473ca95b02SDimitry Andric
readMarker(Instruction * I,bool * IsStart)483ca95b02SDimitry Andric bool StackColoring::readMarker(Instruction *I, bool *IsStart) {
49*b5893f02SDimitry Andric if (!I->isLifetimeStartOrEnd())
503ca95b02SDimitry Andric return false;
513ca95b02SDimitry Andric
52*b5893f02SDimitry Andric auto *II = cast<IntrinsicInst>(I);
533ca95b02SDimitry Andric *IsStart = II->getIntrinsicID() == Intrinsic::lifetime_start;
543ca95b02SDimitry Andric return true;
553ca95b02SDimitry Andric }
563ca95b02SDimitry Andric
removeAllMarkers()573ca95b02SDimitry Andric void StackColoring::removeAllMarkers() {
583ca95b02SDimitry Andric for (auto *I : Markers) {
593ca95b02SDimitry Andric auto *Op = dyn_cast<Instruction>(I->getOperand(1));
603ca95b02SDimitry Andric I->eraseFromParent();
613ca95b02SDimitry Andric // Remove the operand bitcast, too, if it has no more uses left.
623ca95b02SDimitry Andric if (Op && Op->use_empty())
633ca95b02SDimitry Andric Op->eraseFromParent();
643ca95b02SDimitry Andric }
653ca95b02SDimitry Andric }
663ca95b02SDimitry Andric
collectMarkers()673ca95b02SDimitry Andric void StackColoring::collectMarkers() {
683ca95b02SDimitry Andric InterestingAllocas.resize(NumAllocas);
693ca95b02SDimitry Andric DenseMap<BasicBlock *, SmallDenseMap<Instruction *, Marker>> BBMarkerSet;
703ca95b02SDimitry Andric
713ca95b02SDimitry Andric // Compute the set of start/end markers per basic block.
723ca95b02SDimitry Andric for (unsigned AllocaNo = 0; AllocaNo < NumAllocas; ++AllocaNo) {
733ca95b02SDimitry Andric AllocaInst *AI = Allocas[AllocaNo];
743ca95b02SDimitry Andric SmallVector<Instruction *, 8> WorkList;
753ca95b02SDimitry Andric WorkList.push_back(AI);
763ca95b02SDimitry Andric while (!WorkList.empty()) {
773ca95b02SDimitry Andric Instruction *I = WorkList.pop_back_val();
783ca95b02SDimitry Andric for (User *U : I->users()) {
793ca95b02SDimitry Andric if (auto *BI = dyn_cast<BitCastInst>(U)) {
803ca95b02SDimitry Andric WorkList.push_back(BI);
813ca95b02SDimitry Andric continue;
823ca95b02SDimitry Andric }
833ca95b02SDimitry Andric auto *UI = dyn_cast<Instruction>(U);
843ca95b02SDimitry Andric if (!UI)
853ca95b02SDimitry Andric continue;
863ca95b02SDimitry Andric bool IsStart;
873ca95b02SDimitry Andric if (!readMarker(UI, &IsStart))
883ca95b02SDimitry Andric continue;
893ca95b02SDimitry Andric if (IsStart)
903ca95b02SDimitry Andric InterestingAllocas.set(AllocaNo);
913ca95b02SDimitry Andric BBMarkerSet[UI->getParent()][UI] = {AllocaNo, IsStart};
923ca95b02SDimitry Andric Markers.push_back(UI);
933ca95b02SDimitry Andric }
943ca95b02SDimitry Andric }
953ca95b02SDimitry Andric }
963ca95b02SDimitry Andric
973ca95b02SDimitry Andric // Compute instruction numbering. Only the following instructions are
983ca95b02SDimitry Andric // considered:
993ca95b02SDimitry Andric // * Basic block entries
1003ca95b02SDimitry Andric // * Lifetime markers
1013ca95b02SDimitry Andric // For each basic block, compute
1023ca95b02SDimitry Andric // * the list of markers in the instruction order
1033ca95b02SDimitry Andric // * the sets of allocas whose lifetime starts or ends in this BB
1044ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << "Instructions:\n");
1053ca95b02SDimitry Andric unsigned InstNo = 0;
1063ca95b02SDimitry Andric for (BasicBlock *BB : depth_first(&F)) {
1074ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << " " << InstNo << ": BB " << BB->getName() << "\n");
1083ca95b02SDimitry Andric unsigned BBStart = InstNo++;
1093ca95b02SDimitry Andric
1103ca95b02SDimitry Andric BlockLifetimeInfo &BlockInfo = BlockLiveness[BB];
1113ca95b02SDimitry Andric BlockInfo.Begin.resize(NumAllocas);
1123ca95b02SDimitry Andric BlockInfo.End.resize(NumAllocas);
1133ca95b02SDimitry Andric BlockInfo.LiveIn.resize(NumAllocas);
1143ca95b02SDimitry Andric BlockInfo.LiveOut.resize(NumAllocas);
1153ca95b02SDimitry Andric
1163ca95b02SDimitry Andric auto &BlockMarkerSet = BBMarkerSet[BB];
1173ca95b02SDimitry Andric if (BlockMarkerSet.empty()) {
1183ca95b02SDimitry Andric unsigned BBEnd = InstNo;
1193ca95b02SDimitry Andric BlockInstRange[BB] = std::make_pair(BBStart, BBEnd);
1203ca95b02SDimitry Andric continue;
1213ca95b02SDimitry Andric }
1223ca95b02SDimitry Andric
1233ca95b02SDimitry Andric auto ProcessMarker = [&](Instruction *I, const Marker &M) {
1244ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << " " << InstNo << ": "
1254ba319b5SDimitry Andric << (M.IsStart ? "start " : "end ") << M.AllocaNo
1264ba319b5SDimitry Andric << ", " << *I << "\n");
1273ca95b02SDimitry Andric
1283ca95b02SDimitry Andric BBMarkers[BB].push_back({InstNo, M});
1293ca95b02SDimitry Andric
1303ca95b02SDimitry Andric InstructionNumbering[I] = InstNo++;
1313ca95b02SDimitry Andric
1323ca95b02SDimitry Andric if (M.IsStart) {
1333ca95b02SDimitry Andric if (BlockInfo.End.test(M.AllocaNo))
1343ca95b02SDimitry Andric BlockInfo.End.reset(M.AllocaNo);
1353ca95b02SDimitry Andric BlockInfo.Begin.set(M.AllocaNo);
1363ca95b02SDimitry Andric } else {
1373ca95b02SDimitry Andric if (BlockInfo.Begin.test(M.AllocaNo))
1383ca95b02SDimitry Andric BlockInfo.Begin.reset(M.AllocaNo);
1393ca95b02SDimitry Andric BlockInfo.End.set(M.AllocaNo);
1403ca95b02SDimitry Andric }
1413ca95b02SDimitry Andric };
1423ca95b02SDimitry Andric
1433ca95b02SDimitry Andric if (BlockMarkerSet.size() == 1) {
1443ca95b02SDimitry Andric ProcessMarker(BlockMarkerSet.begin()->getFirst(),
1453ca95b02SDimitry Andric BlockMarkerSet.begin()->getSecond());
1463ca95b02SDimitry Andric } else {
1473ca95b02SDimitry Andric // Scan the BB to determine the marker order.
1483ca95b02SDimitry Andric for (Instruction &I : *BB) {
1493ca95b02SDimitry Andric auto It = BlockMarkerSet.find(&I);
1503ca95b02SDimitry Andric if (It == BlockMarkerSet.end())
1513ca95b02SDimitry Andric continue;
1523ca95b02SDimitry Andric ProcessMarker(&I, It->getSecond());
1533ca95b02SDimitry Andric }
1543ca95b02SDimitry Andric }
1553ca95b02SDimitry Andric
1563ca95b02SDimitry Andric unsigned BBEnd = InstNo;
1573ca95b02SDimitry Andric BlockInstRange[BB] = std::make_pair(BBStart, BBEnd);
1583ca95b02SDimitry Andric }
1593ca95b02SDimitry Andric NumInst = InstNo;
1603ca95b02SDimitry Andric }
1613ca95b02SDimitry Andric
calculateLocalLiveness()1623ca95b02SDimitry Andric void StackColoring::calculateLocalLiveness() {
1633ca95b02SDimitry Andric bool changed = true;
1643ca95b02SDimitry Andric while (changed) {
1653ca95b02SDimitry Andric changed = false;
1663ca95b02SDimitry Andric
1673ca95b02SDimitry Andric for (BasicBlock *BB : depth_first(&F)) {
1683ca95b02SDimitry Andric BlockLifetimeInfo &BlockInfo = BlockLiveness[BB];
1693ca95b02SDimitry Andric
1703ca95b02SDimitry Andric // Compute LiveIn by unioning together the LiveOut sets of all preds.
1713ca95b02SDimitry Andric BitVector LocalLiveIn;
1723ca95b02SDimitry Andric for (auto *PredBB : predecessors(BB)) {
1733ca95b02SDimitry Andric LivenessMap::const_iterator I = BlockLiveness.find(PredBB);
174*b5893f02SDimitry Andric // If a predecessor is unreachable, ignore it.
175*b5893f02SDimitry Andric if (I == BlockLiveness.end())
176*b5893f02SDimitry Andric continue;
1773ca95b02SDimitry Andric LocalLiveIn |= I->second.LiveOut;
1783ca95b02SDimitry Andric }
1793ca95b02SDimitry Andric
1803ca95b02SDimitry Andric // Compute LiveOut by subtracting out lifetimes that end in this
1813ca95b02SDimitry Andric // block, then adding in lifetimes that begin in this block. If
1823ca95b02SDimitry Andric // we have both BEGIN and END markers in the same basic block
1833ca95b02SDimitry Andric // then we know that the BEGIN marker comes after the END,
1843ca95b02SDimitry Andric // because we already handle the case where the BEGIN comes
1853ca95b02SDimitry Andric // before the END when collecting the markers (and building the
1863ca95b02SDimitry Andric // BEGIN/END vectors).
1873ca95b02SDimitry Andric BitVector LocalLiveOut = LocalLiveIn;
1883ca95b02SDimitry Andric LocalLiveOut.reset(BlockInfo.End);
1893ca95b02SDimitry Andric LocalLiveOut |= BlockInfo.Begin;
1903ca95b02SDimitry Andric
1913ca95b02SDimitry Andric // Update block LiveIn set, noting whether it has changed.
1923ca95b02SDimitry Andric if (LocalLiveIn.test(BlockInfo.LiveIn)) {
1933ca95b02SDimitry Andric changed = true;
1943ca95b02SDimitry Andric BlockInfo.LiveIn |= LocalLiveIn;
1953ca95b02SDimitry Andric }
1963ca95b02SDimitry Andric
1973ca95b02SDimitry Andric // Update block LiveOut set, noting whether it has changed.
1983ca95b02SDimitry Andric if (LocalLiveOut.test(BlockInfo.LiveOut)) {
1993ca95b02SDimitry Andric changed = true;
2003ca95b02SDimitry Andric BlockInfo.LiveOut |= LocalLiveOut;
2013ca95b02SDimitry Andric }
2023ca95b02SDimitry Andric }
2033ca95b02SDimitry Andric } // while changed.
2043ca95b02SDimitry Andric }
2053ca95b02SDimitry Andric
calculateLiveIntervals()2063ca95b02SDimitry Andric void StackColoring::calculateLiveIntervals() {
2073ca95b02SDimitry Andric for (auto IT : BlockLiveness) {
2083ca95b02SDimitry Andric BasicBlock *BB = IT.getFirst();
2093ca95b02SDimitry Andric BlockLifetimeInfo &BlockInfo = IT.getSecond();
2103ca95b02SDimitry Andric unsigned BBStart, BBEnd;
2113ca95b02SDimitry Andric std::tie(BBStart, BBEnd) = BlockInstRange[BB];
2123ca95b02SDimitry Andric
2133ca95b02SDimitry Andric BitVector Started, Ended;
2143ca95b02SDimitry Andric Started.resize(NumAllocas);
2153ca95b02SDimitry Andric Ended.resize(NumAllocas);
2163ca95b02SDimitry Andric SmallVector<unsigned, 8> Start;
2173ca95b02SDimitry Andric Start.resize(NumAllocas);
2183ca95b02SDimitry Andric
2193ca95b02SDimitry Andric // LiveIn ranges start at the first instruction.
2203ca95b02SDimitry Andric for (unsigned AllocaNo = 0; AllocaNo < NumAllocas; ++AllocaNo) {
2213ca95b02SDimitry Andric if (BlockInfo.LiveIn.test(AllocaNo)) {
2223ca95b02SDimitry Andric Started.set(AllocaNo);
2233ca95b02SDimitry Andric Start[AllocaNo] = BBStart;
2243ca95b02SDimitry Andric }
2253ca95b02SDimitry Andric }
2263ca95b02SDimitry Andric
2273ca95b02SDimitry Andric for (auto &It : BBMarkers[BB]) {
2283ca95b02SDimitry Andric unsigned InstNo = It.first;
2293ca95b02SDimitry Andric bool IsStart = It.second.IsStart;
2303ca95b02SDimitry Andric unsigned AllocaNo = It.second.AllocaNo;
2313ca95b02SDimitry Andric
2323ca95b02SDimitry Andric if (IsStart) {
233d88c1a5aSDimitry Andric assert(!Started.test(AllocaNo) || Start[AllocaNo] == BBStart);
234d88c1a5aSDimitry Andric if (!Started.test(AllocaNo)) {
2353ca95b02SDimitry Andric Started.set(AllocaNo);
2363ca95b02SDimitry Andric Ended.reset(AllocaNo);
2373ca95b02SDimitry Andric Start[AllocaNo] = InstNo;
238d88c1a5aSDimitry Andric }
2393ca95b02SDimitry Andric } else {
2403ca95b02SDimitry Andric assert(!Ended.test(AllocaNo));
2413ca95b02SDimitry Andric if (Started.test(AllocaNo)) {
2423ca95b02SDimitry Andric LiveRanges[AllocaNo].AddRange(Start[AllocaNo], InstNo);
2433ca95b02SDimitry Andric Started.reset(AllocaNo);
2443ca95b02SDimitry Andric }
2453ca95b02SDimitry Andric Ended.set(AllocaNo);
2463ca95b02SDimitry Andric }
2473ca95b02SDimitry Andric }
2483ca95b02SDimitry Andric
2493ca95b02SDimitry Andric for (unsigned AllocaNo = 0; AllocaNo < NumAllocas; ++AllocaNo)
2503ca95b02SDimitry Andric if (Started.test(AllocaNo))
2513ca95b02SDimitry Andric LiveRanges[AllocaNo].AddRange(Start[AllocaNo], BBEnd);
2523ca95b02SDimitry Andric }
2533ca95b02SDimitry Andric }
2543ca95b02SDimitry Andric
2557a7e6055SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dumpAllocas()2563ca95b02SDimitry Andric LLVM_DUMP_METHOD void StackColoring::dumpAllocas() {
2573ca95b02SDimitry Andric dbgs() << "Allocas:\n";
2583ca95b02SDimitry Andric for (unsigned AllocaNo = 0; AllocaNo < NumAllocas; ++AllocaNo)
2593ca95b02SDimitry Andric dbgs() << " " << AllocaNo << ": " << *Allocas[AllocaNo] << "\n";
2603ca95b02SDimitry Andric }
2613ca95b02SDimitry Andric
dumpBlockLiveness()2623ca95b02SDimitry Andric LLVM_DUMP_METHOD void StackColoring::dumpBlockLiveness() {
2633ca95b02SDimitry Andric dbgs() << "Block liveness:\n";
2643ca95b02SDimitry Andric for (auto IT : BlockLiveness) {
2653ca95b02SDimitry Andric BasicBlock *BB = IT.getFirst();
2663ca95b02SDimitry Andric BlockLifetimeInfo &BlockInfo = BlockLiveness[BB];
2673ca95b02SDimitry Andric auto BlockRange = BlockInstRange[BB];
2683ca95b02SDimitry Andric dbgs() << " BB [" << BlockRange.first << ", " << BlockRange.second
2693ca95b02SDimitry Andric << "): begin " << BlockInfo.Begin << ", end " << BlockInfo.End
2703ca95b02SDimitry Andric << ", livein " << BlockInfo.LiveIn << ", liveout "
2713ca95b02SDimitry Andric << BlockInfo.LiveOut << "\n";
2723ca95b02SDimitry Andric }
2733ca95b02SDimitry Andric }
2743ca95b02SDimitry Andric
dumpLiveRanges()2753ca95b02SDimitry Andric LLVM_DUMP_METHOD void StackColoring::dumpLiveRanges() {
2763ca95b02SDimitry Andric dbgs() << "Alloca liveness:\n";
2773ca95b02SDimitry Andric for (unsigned AllocaNo = 0; AllocaNo < NumAllocas; ++AllocaNo) {
2783ca95b02SDimitry Andric LiveRange &Range = LiveRanges[AllocaNo];
2793ca95b02SDimitry Andric dbgs() << " " << AllocaNo << ": " << Range << "\n";
2803ca95b02SDimitry Andric }
2813ca95b02SDimitry Andric }
2827a7e6055SDimitry Andric #endif
2833ca95b02SDimitry Andric
run()2843ca95b02SDimitry Andric void StackColoring::run() {
2854ba319b5SDimitry Andric LLVM_DEBUG(dumpAllocas());
2863ca95b02SDimitry Andric
2873ca95b02SDimitry Andric for (unsigned I = 0; I < NumAllocas; ++I)
2883ca95b02SDimitry Andric AllocaNumbering[Allocas[I]] = I;
2893ca95b02SDimitry Andric LiveRanges.resize(NumAllocas);
2903ca95b02SDimitry Andric
2913ca95b02SDimitry Andric collectMarkers();
2923ca95b02SDimitry Andric
2933ca95b02SDimitry Andric if (!ClColoring) {
2943ca95b02SDimitry Andric for (auto &R : LiveRanges) {
2953ca95b02SDimitry Andric R.SetMaximum(1);
2963ca95b02SDimitry Andric R.AddRange(0, 1);
2973ca95b02SDimitry Andric }
2983ca95b02SDimitry Andric return;
2993ca95b02SDimitry Andric }
3003ca95b02SDimitry Andric
3013ca95b02SDimitry Andric for (auto &R : LiveRanges)
3023ca95b02SDimitry Andric R.SetMaximum(NumInst);
3033ca95b02SDimitry Andric for (unsigned I = 0; I < NumAllocas; ++I)
3043ca95b02SDimitry Andric if (!InterestingAllocas.test(I))
3053ca95b02SDimitry Andric LiveRanges[I] = getFullLiveRange();
3063ca95b02SDimitry Andric
3073ca95b02SDimitry Andric calculateLocalLiveness();
3084ba319b5SDimitry Andric LLVM_DEBUG(dumpBlockLiveness());
3093ca95b02SDimitry Andric calculateLiveIntervals();
3104ba319b5SDimitry Andric LLVM_DEBUG(dumpLiveRanges());
3113ca95b02SDimitry Andric }
312