1 //===- SafeStackColoring.cpp - SafeStack frame coloring -------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "SafeStackColoring.h"
11 #include "llvm/ADT/BitVector.h"
12 #include "llvm/ADT/DenseMap.h"
13 #include "llvm/ADT/DepthFirstIterator.h"
14 #include "llvm/ADT/SmallVector.h"
15 #include "llvm/Config/llvm-config.h"
16 #include "llvm/IR/BasicBlock.h"
17 #include "llvm/IR/CFG.h"
18 #include "llvm/IR/Instruction.h"
19 #include "llvm/IR/Instructions.h"
20 #include "llvm/IR/IntrinsicInst.h"
21 #include "llvm/IR/Intrinsics.h"
22 #include "llvm/IR/User.h"
23 #include "llvm/Support/Casting.h"
24 #include "llvm/Support/CommandLine.h"
25 #include "llvm/Support/Compiler.h"
26 #include "llvm/Support/Debug.h"
27 #include "llvm/Support/raw_ostream.h"
33 using namespace llvm::safestack
;
35 #define DEBUG_TYPE "safestackcoloring"
37 // Disabled by default due to PR32143.
38 static cl::opt
<bool> ClColoring("safe-stack-coloring",
39 cl::desc("enable safe stack coloring"),
40 cl::Hidden
, cl::init(false));
42 const StackColoring::LiveRange
&StackColoring::getLiveRange(AllocaInst
*AI
) {
43 const auto IT
= AllocaNumbering
.find(AI
);
44 assert(IT
!= AllocaNumbering
.end());
45 return LiveRanges
[IT
->second
];
48 bool StackColoring::readMarker(Instruction
*I
, bool *IsStart
) {
49 auto *II
= dyn_cast
<IntrinsicInst
>(I
);
50 if (!II
|| (II
->getIntrinsicID() != Intrinsic::lifetime_start
&&
51 II
->getIntrinsicID() != Intrinsic::lifetime_end
))
54 *IsStart
= II
->getIntrinsicID() == Intrinsic::lifetime_start
;
58 void StackColoring::removeAllMarkers() {
59 for (auto *I
: Markers
) {
60 auto *Op
= dyn_cast
<Instruction
>(I
->getOperand(1));
62 // Remove the operand bitcast, too, if it has no more uses left.
63 if (Op
&& Op
->use_empty())
64 Op
->eraseFromParent();
68 void StackColoring::collectMarkers() {
69 InterestingAllocas
.resize(NumAllocas
);
70 DenseMap
<BasicBlock
*, SmallDenseMap
<Instruction
*, Marker
>> BBMarkerSet
;
72 // Compute the set of start/end markers per basic block.
73 for (unsigned AllocaNo
= 0; AllocaNo
< NumAllocas
; ++AllocaNo
) {
74 AllocaInst
*AI
= Allocas
[AllocaNo
];
75 SmallVector
<Instruction
*, 8> WorkList
;
76 WorkList
.push_back(AI
);
77 while (!WorkList
.empty()) {
78 Instruction
*I
= WorkList
.pop_back_val();
79 for (User
*U
: I
->users()) {
80 if (auto *BI
= dyn_cast
<BitCastInst
>(U
)) {
81 WorkList
.push_back(BI
);
84 auto *UI
= dyn_cast
<Instruction
>(U
);
88 if (!readMarker(UI
, &IsStart
))
91 InterestingAllocas
.set(AllocaNo
);
92 BBMarkerSet
[UI
->getParent()][UI
] = {AllocaNo
, IsStart
};
93 Markers
.push_back(UI
);
98 // Compute instruction numbering. Only the following instructions are
100 // * Basic block entries
101 // * Lifetime markers
102 // For each basic block, compute
103 // * the list of markers in the instruction order
104 // * the sets of allocas whose lifetime starts or ends in this BB
105 LLVM_DEBUG(dbgs() << "Instructions:\n");
107 for (BasicBlock
*BB
: depth_first(&F
)) {
108 LLVM_DEBUG(dbgs() << " " << InstNo
<< ": BB " << BB
->getName() << "\n");
109 unsigned BBStart
= InstNo
++;
111 BlockLifetimeInfo
&BlockInfo
= BlockLiveness
[BB
];
112 BlockInfo
.Begin
.resize(NumAllocas
);
113 BlockInfo
.End
.resize(NumAllocas
);
114 BlockInfo
.LiveIn
.resize(NumAllocas
);
115 BlockInfo
.LiveOut
.resize(NumAllocas
);
117 auto &BlockMarkerSet
= BBMarkerSet
[BB
];
118 if (BlockMarkerSet
.empty()) {
119 unsigned BBEnd
= InstNo
;
120 BlockInstRange
[BB
] = std::make_pair(BBStart
, BBEnd
);
124 auto ProcessMarker
= [&](Instruction
*I
, const Marker
&M
) {
125 LLVM_DEBUG(dbgs() << " " << InstNo
<< ": "
126 << (M
.IsStart
? "start " : "end ") << M
.AllocaNo
127 << ", " << *I
<< "\n");
129 BBMarkers
[BB
].push_back({InstNo
, M
});
131 InstructionNumbering
[I
] = InstNo
++;
134 if (BlockInfo
.End
.test(M
.AllocaNo
))
135 BlockInfo
.End
.reset(M
.AllocaNo
);
136 BlockInfo
.Begin
.set(M
.AllocaNo
);
138 if (BlockInfo
.Begin
.test(M
.AllocaNo
))
139 BlockInfo
.Begin
.reset(M
.AllocaNo
);
140 BlockInfo
.End
.set(M
.AllocaNo
);
144 if (BlockMarkerSet
.size() == 1) {
145 ProcessMarker(BlockMarkerSet
.begin()->getFirst(),
146 BlockMarkerSet
.begin()->getSecond());
148 // Scan the BB to determine the marker order.
149 for (Instruction
&I
: *BB
) {
150 auto It
= BlockMarkerSet
.find(&I
);
151 if (It
== BlockMarkerSet
.end())
153 ProcessMarker(&I
, It
->getSecond());
157 unsigned BBEnd
= InstNo
;
158 BlockInstRange
[BB
] = std::make_pair(BBStart
, BBEnd
);
163 void StackColoring::calculateLocalLiveness() {
168 for (BasicBlock
*BB
: depth_first(&F
)) {
169 BlockLifetimeInfo
&BlockInfo
= BlockLiveness
[BB
];
171 // Compute LiveIn by unioning together the LiveOut sets of all preds.
172 BitVector LocalLiveIn
;
173 for (auto *PredBB
: predecessors(BB
)) {
174 LivenessMap::const_iterator I
= BlockLiveness
.find(PredBB
);
175 // If a predecessor is unreachable, ignore it.
176 if (I
== BlockLiveness
.end())
178 LocalLiveIn
|= I
->second
.LiveOut
;
181 // Compute LiveOut by subtracting out lifetimes that end in this
182 // block, then adding in lifetimes that begin in this block. If
183 // we have both BEGIN and END markers in the same basic block
184 // then we know that the BEGIN marker comes after the END,
185 // because we already handle the case where the BEGIN comes
186 // before the END when collecting the markers (and building the
187 // BEGIN/END vectors).
188 BitVector LocalLiveOut
= LocalLiveIn
;
189 LocalLiveOut
.reset(BlockInfo
.End
);
190 LocalLiveOut
|= BlockInfo
.Begin
;
192 // Update block LiveIn set, noting whether it has changed.
193 if (LocalLiveIn
.test(BlockInfo
.LiveIn
)) {
195 BlockInfo
.LiveIn
|= LocalLiveIn
;
198 // Update block LiveOut set, noting whether it has changed.
199 if (LocalLiveOut
.test(BlockInfo
.LiveOut
)) {
201 BlockInfo
.LiveOut
|= LocalLiveOut
;
207 void StackColoring::calculateLiveIntervals() {
208 for (auto IT
: BlockLiveness
) {
209 BasicBlock
*BB
= IT
.getFirst();
210 BlockLifetimeInfo
&BlockInfo
= IT
.getSecond();
211 unsigned BBStart
, BBEnd
;
212 std::tie(BBStart
, BBEnd
) = BlockInstRange
[BB
];
214 BitVector Started
, Ended
;
215 Started
.resize(NumAllocas
);
216 Ended
.resize(NumAllocas
);
217 SmallVector
<unsigned, 8> Start
;
218 Start
.resize(NumAllocas
);
220 // LiveIn ranges start at the first instruction.
221 for (unsigned AllocaNo
= 0; AllocaNo
< NumAllocas
; ++AllocaNo
) {
222 if (BlockInfo
.LiveIn
.test(AllocaNo
)) {
223 Started
.set(AllocaNo
);
224 Start
[AllocaNo
] = BBStart
;
228 for (auto &It
: BBMarkers
[BB
]) {
229 unsigned InstNo
= It
.first
;
230 bool IsStart
= It
.second
.IsStart
;
231 unsigned AllocaNo
= It
.second
.AllocaNo
;
234 assert(!Started
.test(AllocaNo
) || Start
[AllocaNo
] == BBStart
);
235 if (!Started
.test(AllocaNo
)) {
236 Started
.set(AllocaNo
);
237 Ended
.reset(AllocaNo
);
238 Start
[AllocaNo
] = InstNo
;
241 assert(!Ended
.test(AllocaNo
));
242 if (Started
.test(AllocaNo
)) {
243 LiveRanges
[AllocaNo
].AddRange(Start
[AllocaNo
], InstNo
);
244 Started
.reset(AllocaNo
);
250 for (unsigned AllocaNo
= 0; AllocaNo
< NumAllocas
; ++AllocaNo
)
251 if (Started
.test(AllocaNo
))
252 LiveRanges
[AllocaNo
].AddRange(Start
[AllocaNo
], BBEnd
);
256 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
257 LLVM_DUMP_METHOD
void StackColoring::dumpAllocas() {
258 dbgs() << "Allocas:\n";
259 for (unsigned AllocaNo
= 0; AllocaNo
< NumAllocas
; ++AllocaNo
)
260 dbgs() << " " << AllocaNo
<< ": " << *Allocas
[AllocaNo
] << "\n";
263 LLVM_DUMP_METHOD
void StackColoring::dumpBlockLiveness() {
264 dbgs() << "Block liveness:\n";
265 for (auto IT
: BlockLiveness
) {
266 BasicBlock
*BB
= IT
.getFirst();
267 BlockLifetimeInfo
&BlockInfo
= BlockLiveness
[BB
];
268 auto BlockRange
= BlockInstRange
[BB
];
269 dbgs() << " BB [" << BlockRange
.first
<< ", " << BlockRange
.second
270 << "): begin " << BlockInfo
.Begin
<< ", end " << BlockInfo
.End
271 << ", livein " << BlockInfo
.LiveIn
<< ", liveout "
272 << BlockInfo
.LiveOut
<< "\n";
276 LLVM_DUMP_METHOD
void StackColoring::dumpLiveRanges() {
277 dbgs() << "Alloca liveness:\n";
278 for (unsigned AllocaNo
= 0; AllocaNo
< NumAllocas
; ++AllocaNo
) {
279 LiveRange
&Range
= LiveRanges
[AllocaNo
];
280 dbgs() << " " << AllocaNo
<< ": " << Range
<< "\n";
285 void StackColoring::run() {
286 LLVM_DEBUG(dumpAllocas());
288 for (unsigned I
= 0; I
< NumAllocas
; ++I
)
289 AllocaNumbering
[Allocas
[I
]] = I
;
290 LiveRanges
.resize(NumAllocas
);
295 for (auto &R
: LiveRanges
) {
302 for (auto &R
: LiveRanges
)
303 R
.SetMaximum(NumInst
);
304 for (unsigned I
= 0; I
< NumAllocas
; ++I
)
305 if (!InterestingAllocas
.test(I
))
306 LiveRanges
[I
] = getFullLiveRange();
308 calculateLocalLiveness();
309 LLVM_DEBUG(dumpBlockLiveness());
310 calculateLiveIntervals();
311 LLVM_DEBUG(dumpLiveRanges());