llvm.org GIT mirror llvm / 55e10a5
[PM] Fix a likely more critical infloop bug in the CGSCC pass manager. This was just a bad oversight on my part. The code in question should never have worked without this fix. But it turns out, there are relatively few places that involve libfunctions that participate in a single SCC, and unless they do, this happens to not matter. The effect of not having this correct is that each time through this routine, the edge from write_wrapper to write was toggled between a call edge and a ref edge. First time through, it becomes a demoted call edge and is turned into a ref edge. Next time it is a promoted call edge from a ref edge. On, and on it goes forever. I've added the asserts which should have always been here to catch silly mistakes like this in the future as well as a test case that will actually infloop without the fix. The other (much scarier) infinite-inlining issue I think didn't actually occur in practice, and I simply misdiagnosed this minor issue as that much more scary issue. The other issue *is* still a real issue, but I'm somewhat relieved that so far it hasn't happened in real-world code yet... git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@310342 91177308-0d34-0410-b5e6-96231b3b80d8 Chandler Carruth 2 years ago
2 changed file(s) with 26 addition(s) and 4 deletion(s). Raw diff Collapse all Expand all
420420 assert(E && "No function transformations should introduce *new* "
421421 "call edges! Any new calls should be modeled as "
422422 "promoted existing ref edges!");
423 RetainedEdges.insert(&CalleeN);
423 bool Inserted = RetainedEdges.insert(&CalleeN).second;
424 (void)Inserted;
425 assert(Inserted && "We should never visit a function twice.");
424426 if (!E->isCall())
425427 PromotedRefTargets.insert(&CalleeN);
426428 }
440442 assert(E && "No function transformations should introduce *new* ref "
441443 "edges! Any new ref edges would require IPO which "
442444 "function passes aren't allowed to do!");
443 RetainedEdges.insert(&RefereeN);
445 bool Inserted = RetainedEdges.insert(&RefereeN).second;
446 (void)Inserted;
447 assert(Inserted && "We should never visit a function twice.");
444448 if (E->isCall())
445449 DemotedCallTargets.insert(&RefereeN);
446450 };
448452
449453 // Include synthetic reference edges to known, defined lib functions.
450454 for (auto *F : G.getLibFunctions())
451 VisitRef(*F);
455 // While the list of lib functions doesn't have repeats, don't re-visit
456 // anything handled above.
457 if (!Visited.count(F))
458 VisitRef(*F);
452459
453460 // First remove all of the edges that are no longer present in this function.
454461 // We have to build a list of dead targets first and then remove them as the
22 ;
33 ; Also check that it can handle inlining *removing* a libcall entirely.
44 ;
5 ; RUN: opt -passes='cgscc(inline,function(instcombine))' -S < %s | FileCheck %s
5 ; Finally, we include some recursive patterns and forced analysis invaliadtion
6 ; that can trigger infinite CGSCC refinement if not handled correctly.
7 ;
8 ; RUN: opt -passes='cgscc(inline,function(instcombine,invalidate))' -S < %s | FileCheck %s
69
710 define i8* @wibble(i8* %arg1, i8* %arg2) {
811 ; CHECK-LABEL: define i8* @wibble(
5861 %shr = and i32 %and2, 65280
5962 ret i32 %shr
6063 }
64
65 define i64 @write(i32 %i, i8* %p, i64 %j) {
66 entry:
67 %val = call i64 @write_wrapper(i32 %i, i8* %p, i64 %j) noinline
68 ret i64 %val
69 }
70
71 define i64 @write_wrapper(i32 %i, i8* %p, i64 %j) {
72 entry:
73 %val = call i64 @write(i32 %i, i8* %p, i64 %j) noinline
74 ret i64 %val
75 }