llvm.org GIT mirror llvm / d9e6eec
Merging r323034: ------------------------------------------------------------------------ r323034 | dmgreen | 2018-01-20 11:29:37 +0100 (Sat, 20 Jan 2018) | 9 lines [Dominators] Fix some edge cases for PostDomTree updating These fix some odd cfg cases where batch-updating the post dom tree fails. Usually around infinite loops and roots ending up being different. Differential Revision: https://reviews.llvm.org/D42247 ------------------------------------------------------------------------ git-svn-id: https://llvm.org/svn/llvm-project/llvm/branches/release_60@323121 91177308-0d34-0410-b5e6-96231b3b80d8 Hans Wennborg 2 years ago
5 changed file(s) with 216 addition(s) and 60 deletion(s). Raw diff Collapse all Expand all
176176 unsigned IACol);
177177
178178 /// Retreive the function info if this is a valid function id, or nullptr.
179 MCCVFunctionInfo *getCVFunctionInfo(unsigned FuncId) {
180 if (FuncId >= Functions.size())
181 return nullptr;
182 if (Functions[FuncId].isUnallocatedFunctionInfo())
183 return nullptr;
184 return &Functions[FuncId];
185 }
179 MCCVFunctionInfo *getCVFunctionInfo(unsigned FuncId);
186180
187181 /// Saves the information from the currently parsed .cv_loc directive
188182 /// and sets CVLocSeen. When the next instruction is assembled an entry
198192 CurrentCVLoc.setIsStmt(IsStmt);
199193 CVLocSeen = true;
200194 }
195
196 bool getCVLocSeen() { return CVLocSeen; }
201197 void clearCVLocSeen() { CVLocSeen = false; }
202198
203 bool getCVLocSeen() { return CVLocSeen; }
204199 const MCCVLoc &getCurrentCVLoc() { return CurrentCVLoc; }
205200
206201 bool isValidCVFileNumber(unsigned FileNumber);
207202
208203 /// \brief Add a line entry.
209 void addLineEntry(const MCCVLineEntry &LineEntry) {
210 size_t Offset = MCCVLines.size();
211 auto I = MCCVLineStartStop.insert(
212 {LineEntry.getFunctionId(), {Offset, Offset + 1}});
213 if (!I.second)
214 I.first->second.second = Offset + 1;
215 MCCVLines.push_back(LineEntry);
216 }
217
218 std::vector getFunctionLineEntries(unsigned FuncId) {
219 std::vector FilteredLines;
220
221 auto I = MCCVLineStartStop.find(FuncId);
222 if (I != MCCVLineStartStop.end())
223 for (size_t Idx = I->second.first, End = I->second.second; Idx != End;
224 ++Idx)
225 if (MCCVLines[Idx].getFunctionId() == FuncId)
226 FilteredLines.push_back(MCCVLines[Idx]);
227 return FilteredLines;
228 }
229
230 std::pair getLineExtent(unsigned FuncId) {
231 auto I = MCCVLineStartStop.find(FuncId);
232 // Return an empty extent if there are no cv_locs for this function id.
233 if (I == MCCVLineStartStop.end())
234 return {~0ULL, 0};
235 return I->second;
236 }
237
238 ArrayRef getLinesForExtent(size_t L, size_t R) {
239 if (R <= L)
240 return None;
241 if (L >= MCCVLines.size())
242 return None;
243 return makeArrayRef(&MCCVLines[L], R - L);
244 }
204 void addLineEntry(const MCCVLineEntry &LineEntry);
205
206 std::vector getFunctionLineEntries(unsigned FuncId);
207
208 std::pair getLineExtent(unsigned FuncId);
209
210 ArrayRef getLinesForExtent(size_t L, size_t R);
245211
246212 /// Emits a line table substream.
247213 void emitLineTableForFunction(MCObjectStreamer &OS, unsigned FuncId,
705705 // algorithm does not really know or use the set of roots and can make a
706706 // different (implicit) decision about which nodes within an infinite loop
707707 // becomes a root.
708 if (DT.isVirtualRoot(TN->getIDom())) {
708 if (TN && !DT.isVirtualRoot(TN->getIDom())) {
709709 DEBUG(dbgs() << "Root " << BlockNamePrinter(R)
710710 << " is not virtual root's child\n"
711711 << "The entire tree needs to be rebuilt\n");
939939 const NodePtr NCDBlock = DT.findNearestCommonDominator(From, To);
940940 const TreeNodePtr NCD = DT.getNode(NCDBlock);
941941
942 // To dominates From -- nothing to do.
943 if (ToTN == NCD) return;
944
945 DT.DFSInfoValid = false;
946
947 const TreeNodePtr ToIDom = ToTN->getIDom();
948 DEBUG(dbgs() << "\tNCD " << BlockNamePrinter(NCD) << ", ToIDom "
949 << BlockNamePrinter(ToIDom) << "\n");
950
951 // To remains reachable after deletion.
952 // (Based on the caption under Figure 4. from the second paper.)
953 if (FromTN != ToIDom || HasProperSupport(DT, BUI, ToTN))
954 DeleteReachable(DT, BUI, FromTN, ToTN);
955 else
956 DeleteUnreachable(DT, BUI, ToTN);
942 // If To dominates From -- nothing to do.
943 if (ToTN != NCD) {
944 DT.DFSInfoValid = false;
945
946 const TreeNodePtr ToIDom = ToTN->getIDom();
947 DEBUG(dbgs() << "\tNCD " << BlockNamePrinter(NCD) << ", ToIDom "
948 << BlockNamePrinter(ToIDom) << "\n");
949
950 // To remains reachable after deletion.
951 // (Based on the caption under Figure 4. from the second paper.)
952 if (FromTN != ToIDom || HasProperSupport(DT, BUI, ToTN))
953 DeleteReachable(DT, BUI, FromTN, ToTN);
954 else
955 DeleteUnreachable(DT, BUI, ToTN);
956 }
957957
958958 if (IsPostDom) UpdateRootsAfterUpdate(DT, BUI);
959959 }
7373 Files[Idx].ChecksumKind = ChecksumKind;
7474
7575 return true;
76 }
77
78 MCCVFunctionInfo *CodeViewContext::getCVFunctionInfo(unsigned FuncId) {
79 if (FuncId >= Functions.size())
80 return nullptr;
81 if (Functions[FuncId].isUnallocatedFunctionInfo())
82 return nullptr;
83 return &Functions[FuncId];
7684 }
7785
7886 bool CodeViewContext::recordFunctionId(unsigned FuncId) {
244252 MCSymbolRefExpr::create(Files[Idx].ChecksumTableOffset, OS.getContext());
245253
246254 OS.EmitValueImpl(SRE, 4);
255 }
256
257 void CodeViewContext::addLineEntry(const MCCVLineEntry &LineEntry) {
258 size_t Offset = MCCVLines.size();
259 auto I = MCCVLineStartStop.insert(
260 {LineEntry.getFunctionId(), {Offset, Offset + 1}});
261 if (!I.second)
262 I.first->second.second = Offset + 1;
263 MCCVLines.push_back(LineEntry);
264 }
265
266 std::vector
267 CodeViewContext::getFunctionLineEntries(unsigned FuncId) {
268 std::vector FilteredLines;
269 auto I = MCCVLineStartStop.find(FuncId);
270 if (I != MCCVLineStartStop.end()) {
271 MCCVFunctionInfo *SiteInfo = getCVFunctionInfo(FuncId);
272 for (size_t Idx = I->second.first, End = I->second.second; Idx != End;
273 ++Idx) {
274 unsigned LocationFuncId = MCCVLines[Idx].getFunctionId();
275 if (LocationFuncId == FuncId) {
276 // This was a .cv_loc directly for FuncId, so record it.
277 FilteredLines.push_back(MCCVLines[Idx]);
278 } else {
279 // Check if the current location is inlined in this function. If it is,
280 // synthesize a statement .cv_loc at the original inlined call site.
281 auto I = SiteInfo->InlinedAtMap.find(LocationFuncId);
282 if (I != SiteInfo->InlinedAtMap.end()) {
283 MCCVFunctionInfo::LineInfo &IA = I->second;
284 // Only add the location if it differs from the previous location.
285 // Large inlined calls will have many .cv_loc entries and we only need
286 // one line table entry in the parent function.
287 if (FilteredLines.empty() ||
288 FilteredLines.back().getFileNum() != IA.File ||
289 FilteredLines.back().getLine() != IA.Line ||
290 FilteredLines.back().getColumn() != IA.Col) {
291 FilteredLines.push_back(MCCVLineEntry(
292 MCCVLines[Idx].getLabel(),
293 MCCVLoc(FuncId, IA.File, IA.Line, IA.Col, false, false)));
294 }
295 }
296 }
297 }
298 }
299 return FilteredLines;
300 }
301
302 std::pair CodeViewContext::getLineExtent(unsigned FuncId) {
303 auto I = MCCVLineStartStop.find(FuncId);
304 // Return an empty extent if there are no cv_locs for this function id.
305 if (I == MCCVLineStartStop.end())
306 return {~0ULL, 0};
307 return I->second;
308 }
309
310 ArrayRef CodeViewContext::getLinesForExtent(size_t L, size_t R) {
311 if (R <= L)
312 return None;
313 if (L >= MCCVLines.size())
314 return None;
315 return makeArrayRef(&MCCVLines[L], R - L);
247316 }
248317
249318 void CodeViewContext::emitLineTableForFunction(MCObjectStreamer &OS,
134134 .cv_filechecksums # File index to string table offset subsection
135135 .cv_stringtable # String table
136136
137 # CHECK-LABEL: FunctionLineTable [
138 # CHECK: LinkageName: ?baz@@YAXXZ
139 # CHECK: Flags: 0x1
140 # CHECK: CodeSize: 0x3D
141 # CHECK: FilenameSegment [
142 # CHECK: Filename: D:\src\llvm\build\t.cpp (0x0)
143 # CHECK: +0x0 [
144 # CHECK: LineNumberStart: 13
145 # CHECK: ]
146 # CHECK: +0x1 [
147 # CHECK: LineNumberStart: 14
148 # CHECK: ]
149 # CHECK: +0x8 [
150 # CHECK: LineNumberStart: 15
151 # CHECK: ]
152 # There shouldn't be any other line number entries because all the other
153 # .cv_locs are on line 15 where the top-level inline call site is.
154 # CHECK-NOT: LineNumberStart
155 # CHECK: +0x34 [
156 # CHECK: LineNumberStart: 16
157 # CHECK: ]
158 # CHECK: +0x3B [
159 # CHECK: LineNumberStart: 17
160 # CHECK: ]
161 # CHECK: ]
162 # CHECK: ]
257257 EXPECT_TRUE(PDT.verify());
258258 }
259259 }
260
261 // These are some odd flowgraphs, usually generated from csmith cases,
262 // which are difficult on post dom trees.
263 TEST(DominatorTreeBatchUpdates, InfiniteLoop) {
264 std::vector Arcs = {
265 {"1", "2"},
266 {"2", "3"},
267 {"3", "6"}, {"3", "5"},
268 {"4", "5"},
269 {"5", "2"},
270 {"6", "3"}, {"6", "4"}};
271
272 // SplitBlock on 3 -> 5
273 std::vector Updates = {
274 {CFGInsert, {"N", "5"}}, {CFGInsert, {"3", "N"}}, {CFGDelete, {"3", "5"}}};
275
276 CFGHolder Holder;
277 CFGBuilder B(Holder.F, Arcs, Updates);
278 DominatorTree DT(*Holder.F);
279 EXPECT_TRUE(DT.verify());
280 PostDomTree PDT(*Holder.F);
281 EXPECT_TRUE(PDT.verify());
282
283 while (B.applyUpdate())
284 ;
285
286 auto DomUpdates = ToDomUpdates(B, Updates);
287 DT.applyUpdates(DomUpdates);
288 EXPECT_TRUE(DT.verify());
289 PDT.applyUpdates(DomUpdates);
290 EXPECT_TRUE(PDT.verify());
291 }
292
293 TEST(DominatorTreeBatchUpdates, DeadBlocks) {
294 std::vector Arcs = {
295 {"1", "2"},
296 {"2", "3"},
297 {"3", "4"}, {"3", "7"},
298 {"4", "4"},
299 {"5", "6"}, {"5", "7"},
300 {"6", "7"},
301 {"7", "2"}, {"7", "8"}};
302
303 // Remove dead 5 and 7,
304 // plus SplitBlock on 7 -> 8
305 std::vector Updates = {
306 {CFGDelete, {"6", "7"}}, {CFGDelete, {"5", "7"}}, {CFGDelete, {"5", "6"}},
307 {CFGInsert, {"N", "8"}}, {CFGInsert, {"7", "N"}}, {CFGDelete, {"7", "8"}}};
308
309 CFGHolder Holder;
310 CFGBuilder B(Holder.F, Arcs, Updates);
311 DominatorTree DT(*Holder.F);
312 EXPECT_TRUE(DT.verify());
313 PostDomTree PDT(*Holder.F);
314 EXPECT_TRUE(PDT.verify());
315
316 while (B.applyUpdate())
317 ;
318
319 auto DomUpdates = ToDomUpdates(B, Updates);
320 DT.applyUpdates(DomUpdates);
321 EXPECT_TRUE(DT.verify());
322 PDT.applyUpdates(DomUpdates);
323 EXPECT_TRUE(PDT.verify());
324 }
325
326 TEST(DominatorTreeBatchUpdates, InfiniteLoop2) {
327 std::vector Arcs = {
328 {"1", "2"},
329 {"2", "6"}, {"2", "3"},
330 {"3", "4"},
331 {"4", "5"}, {"4", "6"},
332 {"5", "4"},
333 {"6", "2"}};
334
335 // SplitBlock on 4 -> 6
336 std::vector Updates = {
337 {CFGInsert, {"N", "6"}}, {CFGInsert, {"4", "N"}}, {CFGDelete, {"4", "6"}}};
338
339 CFGHolder Holder;
340 CFGBuilder B(Holder.F, Arcs, Updates);
341 DominatorTree DT(*Holder.F);
342 EXPECT_TRUE(DT.verify());
343 PostDomTree PDT(*Holder.F);
344 EXPECT_TRUE(PDT.verify());
345
346 while (B.applyUpdate())
347 ;
348
349 auto DomUpdates = ToDomUpdates(B, Updates);
350 DT.applyUpdates(DomUpdates);
351 EXPECT_TRUE(DT.verify());
352 PDT.applyUpdates(DomUpdates);
353 EXPECT_TRUE(PDT.verify());
354 }