19 using namespace llvm::safestack;
21 #define DEBUG_TYPE "safestackcoloring"
24 cl::desc(
"enable safe stack coloring"),
28 const auto IT = AllocaNumbering.find(AI);
30 return LiveRanges[
IT->second];
33 bool StackColoring::readMarker(
Instruction *
I,
bool *IsStart) {
35 if (!II || (II->getIntrinsicID() != Intrinsic::lifetime_start &&
36 II->getIntrinsicID() != Intrinsic::lifetime_end))
39 *IsStart = II->getIntrinsicID() == Intrinsic::lifetime_start;
44 for (
auto *I : Markers) {
48 if (
Op &&
Op->use_empty())
49 Op->eraseFromParent();
53 void StackColoring::collectMarkers() {
54 InterestingAllocas.
resize(NumAllocas);
58 for (
unsigned AllocaNo = 0; AllocaNo < NumAllocas; ++AllocaNo) {
62 while (!WorkList.
empty()) {
65 if (
auto *BI = dyn_cast<BitCastInst>(U)) {
73 if (!readMarker(UI, &IsStart))
76 InterestingAllocas.
set(AllocaNo);
77 BBMarkerSet[UI->getParent()][UI] = {AllocaNo, IsStart};
78 Markers.push_back(UI);
93 DEBUG(
dbgs() <<
" " << InstNo <<
": BB " << BB->getName() <<
"\n");
94 unsigned BBStart = InstNo++;
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);
102 auto &BlockMarkerSet = BBMarkerSet[BB];
103 if (BlockMarkerSet.empty()) {
104 unsigned BBEnd = InstNo;
105 BlockInstRange[BB] = std::make_pair(BBStart, BBEnd);
109 auto ProcessMarker = [&](
Instruction *
I,
const Marker &M) {
111 << (M.IsStart ?
"start " :
"end ") << M.AllocaNo <<
", "
114 BBMarkers[BB].push_back({InstNo, M});
116 InstructionNumbering[
I] = InstNo++;
119 if (BlockInfo.End.test(M.AllocaNo))
120 BlockInfo.End.reset(M.AllocaNo);
121 BlockInfo.Begin.set(M.AllocaNo);
123 if (BlockInfo.Begin.test(M.AllocaNo))
124 BlockInfo.Begin.reset(M.AllocaNo);
125 BlockInfo.End.set(M.AllocaNo);
129 if (BlockMarkerSet.size() == 1) {
130 ProcessMarker(BlockMarkerSet.begin()->getFirst(),
131 BlockMarkerSet.begin()->getSecond());
135 auto It = BlockMarkerSet.find(&I);
136 if (It == BlockMarkerSet.end())
138 ProcessMarker(&I, It->getSecond());
142 unsigned BBEnd = InstNo;
143 BlockInstRange[BB] = std::make_pair(BBStart, BBEnd);
148 void StackColoring::calculateLocalLiveness() {
154 BlockLifetimeInfo &BlockInfo = BlockLiveness[BB];
160 assert(I != BlockLiveness.
end() &&
"Predecessor not found");
161 LocalLiveIn |= I->second.LiveOut;
172 LocalLiveOut.
reset(BlockInfo.End);
173 LocalLiveOut |= BlockInfo.Begin;
176 if (LocalLiveIn.
test(BlockInfo.LiveIn)) {
178 BlockInfo.LiveIn |= LocalLiveIn;
182 if (LocalLiveOut.
test(BlockInfo.LiveOut)) {
184 BlockInfo.LiveOut |= LocalLiveOut;
190 void StackColoring::calculateLiveIntervals() {
191 for (
auto IT : BlockLiveness) {
193 BlockLifetimeInfo &BlockInfo =
IT.getSecond();
194 unsigned BBStart, BBEnd;
195 std::tie(BBStart, BBEnd) = BlockInstRange[BB];
198 Started.
resize(NumAllocas);
204 for (
unsigned AllocaNo = 0; AllocaNo < NumAllocas; ++AllocaNo) {
205 if (BlockInfo.LiveIn.test(AllocaNo)) {
206 Started.
set(AllocaNo);
207 Start[AllocaNo] = BBStart;
211 for (
auto &It : BBMarkers[BB]) {
212 unsigned InstNo = It.first;
213 bool IsStart = It.second.IsStart;
214 unsigned AllocaNo = It.second.AllocaNo;
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;
225 if (Started.
test(AllocaNo)) {
226 LiveRanges[AllocaNo].AddRange(Start[AllocaNo], InstNo);
227 Started.
reset(AllocaNo);
233 for (
unsigned AllocaNo = 0; AllocaNo < NumAllocas; ++AllocaNo)
234 if (Started.
test(AllocaNo))
235 LiveRanges[AllocaNo].AddRange(Start[AllocaNo], BBEnd);
240 dbgs() <<
"Allocas:\n";
241 for (
unsigned AllocaNo = 0; AllocaNo < NumAllocas; ++AllocaNo)
242 dbgs() <<
" " << AllocaNo <<
": " << *Allocas[AllocaNo] <<
"\n";
246 dbgs() <<
"Block liveness:\n";
247 for (
auto IT : BlockLiveness) {
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";
259 dbgs() <<
"Alloca liveness:\n";
260 for (
unsigned AllocaNo = 0; AllocaNo < NumAllocas; ++AllocaNo) {
262 dbgs() <<
" " << AllocaNo <<
": " << Range <<
"\n";
267 DEBUG(dumpAllocas());
269 for (
unsigned I = 0; I < NumAllocas; ++
I)
270 AllocaNumbering[Allocas[I]] = I;
271 LiveRanges.resize(NumAllocas);
276 for (
auto &R : LiveRanges) {
283 for (
auto &R : LiveRanges)
284 R.SetMaximum(NumInst);
285 for (
unsigned I = 0; I < NumAllocas; ++
I)
286 if (!InterestingAllocas.
test(I))
289 calculateLocalLiveness();
290 DEBUG(dumpBlockLiveness());
291 calculateLiveIntervals();
292 DEBUG(dumpLiveRanges());
void resize(unsigned N, bool t=false)
resize - Grow or shrink the bitvector.
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.
void push_back(const T &Elt)
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...
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.
LLVM_NODISCARD bool empty() const
LiveRange getFullLiveRange()
Returns a live range that represents an alloca that is live throughout the entire function...
initializer< Ty > init(const Ty &Val)
LLVM Basic Block Representation.
Value * getOperand(unsigned i) const
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
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
bool test(unsigned Idx) const
LLVM_NODISCARD T pop_back_val()
pred_range predecessors(BasicBlock *BB)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
iterator_range< user_iterator > users()
iterator find(const KeyT &Val)
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
iterator_range< df_iterator< T > > depth_first(const T &G)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
A wrapper class for inspecting calls to intrinsic functions.
an instruction to allocate memory on the stack