summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Analysis/LazyCallGraph.cpp
Commit message (Collapse)AuthorAgeFilesLines
...
* [PM] Improve the debugging and logging facilities of the CGSCC bits ofChandler Carruth2016-06-271-0/+53
| | | | | | | | | | | | | the new pass manager. This adds operator<< overloads for the various bits of the LazyCallGraph, dump methods for use from the debugger, and debug logging using them to the CGSCC pass manager. Having this was essential for debugging the call graph update patch, and I've extracted what I could from that patch here to minimize the delta. llvm-svn: 273961
* Add a super basic LazyCallGraph DOT printer.Sean Silva2016-06-181-0/+32
| | | | | | | | | Access it through -passes=print-lcg-dot Let me know any suggestions for changing the rendering; I'm not particularly attached to what is implemented here. llvm-svn: 273082
* [PM] Make the AnalysisManager parameter to run methods a reference.Chandler Carruth2016-03-111-2/+2
| | | | | | | | | | | | This was originally a pointer to support pass managers which didn't use AnalysisManagers. However, that doesn't realistically come up much and the complexity of supporting it doesn't really make sense. In fact, *many* parts of the pass manager were just assuming the pointer was never null already. This at least makes it much more explicit and clear. llvm-svn: 263219
* [PM] Implement the final conclusion as to how the analysis IDs shouldChandler Carruth2016-03-111-1/+1
| | | | | | | | | | | | | | | | | | | | work in the face of the limitations of DLLs and templated static variables. This requires passes that use the AnalysisBase mixin provide a static variable themselves. So as to keep their APIs clean, I've made these private and befriended the CRTP base class (which is the common practice). I've added documentation to AnalysisBase for why this is necessary and at what point we can go back to the much simpler system. This is clearly a better pattern than the extern template as it caught *numerous* places where the template magic hadn't been applied and things were "just working" but would eventually have broken mysteriously. llvm-svn: 263216
* [PM] Appease mingw32's auto-import DLL build with minimal tweaks, with fix ↵NAKAMURA Takumi2016-02-281-0/+2
| | | | | | | | for clang. char AnalysisBase::ID should be declared as extern and defined in one module. llvm-svn: 262188
* Revert r262185, "[PM] Appease mingw32's auto-import DLL build with minimal ↵NAKAMURA Takumi2016-02-281-2/+0
| | | | | | | | tweaks." I'll rework soon. llvm-svn: 262186
* [PM] Appease mingw32's auto-import DLL build with minimal tweaks.NAKAMURA Takumi2016-02-281-0/+2
| | | | | | char AnalysisBase::ID should be declared as extern and defined in one module. llvm-svn: 262185
* [PM] Introduce CRTP mixin base classes to help define passes andChandler Carruth2016-02-261-2/+0
| | | | | | | | | | | | | | | | | analyses in the new pass manager. These just handle really basic stuff: turning a type name into a string statically that is nice to print in logs, and getting a static unique ID for each analysis. Sadly, the format of passes in anonymous namespaces makes using their names in tests really annoying so I've customized the names of the no-op passes to keep tests sane to read. This is the first of a few simplifying refactorings for the new pass manager that should reduce boilerplate and confusion. llvm-svn: 262004
* [LCG] Construct an actual call graph with call-edge SCCs nested insideChandler Carruth2016-02-171-388/+1181
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | reference-edge SCCs. This essentially builds a more normal call graph as a subgraph of the "reference graph" that was the old model. This allows both to exist and the different use cases to use the aspect which addresses their needs. Specifically, the pass manager and other *ordering* constrained logic can use the reference graph to achieve conservative order of visit, while analyses reasoning about attributes and other properties derived from reachability can reason about the direct call graph. Note that this isn't necessarily complete: it doesn't model edges to declarations or indirect calls. Those can be found by scanning the instructions of the function if desirable, and in fact every user currently does this in order to handle things like calls to instrinsics. If useful, we could consider caching this information in the call graph to save the instruction scans, but currently that doesn't seem to be important. An important realization for why the representation chosen here works is that the call graph is a formal subset of the reference graph and thus both can live within the same data structure. All SCCs of the call graph are necessarily contained within an SCC of the reference graph, etc. The design is to build 'RefSCC's to model SCCs of the reference graph, and then within them more literal SCCs for the call graph. The formation of actual call edge SCCs is not done lazily, unlike reference edge 'RefSCC's. Instead, once a reference SCC is formed, it directly builds the call SCCs within it and stores them in a post-order sequence. This is used to provide a consistent platform for mutation and update of the graph. The post-order also allows for very efficient updates in common cases by bounding the number of nodes (and thus edges) considered. There is considerable common code that I'm still looking for the best way to factor out between the various DFS implementations here. So far, my attempts have made the code harder to read and understand despite reducing the duplication, which seems a poor tradeoff. I've not given up on figuring out the right way to do this, but I wanted to wait until I at least had the system working and tested to continue attempting to factor it differently. This also requires introducing several new algorithms in order to handle all of the incremental update scenarios for the more complex structure involving two edge colorings. I've tried to comment the algorithms sufficiently to make it clear how this is expected to work, but they may still need more extensive documentation. I know that there are some changes which are not strictly necessarily coupled here. The process of developing this started out with a very focused set of changes for the new structure of the graph and algorithms, but subsequent changes to bring the APIs and code into consistent and understandable patterns also ended up touching on other aspects. There was no good way to separate these out without causing *massive* merge conflicts. Ultimately, to a large degree this is a rewrite of most of the core algorithms in the LCG class and so I don't think it really matters much. Many thanks to the careful review by Sanjoy Das! Differential Revision: http://reviews.llvm.org/D16802 llvm-svn: 261040
* [LCG] Build an edge abstraction for the LazyCallGraph and use it toChandler Carruth2016-02-021-133/+160
| | | | | | | | | | | | | | | | | | | | | differentiate between indirect references to functions an direct calls. This doesn't do a whole lot yet other than change the print out produced by the analysis, but it lays the groundwork for a very major change I'm working on next: teaching the call graph to actually be a call graph, modeling *both* the indirect reference graph and the call graph simultaneously. More details on that in the next patch though. The rest of this is essentially a bunch of over-engineering that won't be interesting until the next patch. But this also isolates essentially all of the churn necessary to introduce the edge abstraction from the very important behavior change necessary in order to separately model the two graphs. So it should make review of the subsequent patch a bit easier at the cost of making this patch seem poorly motivated. ;] Differential Revision: http://reviews.llvm.org/D16038 llvm-svn: 259463
* [lcg] Fix a few more formatting goofs found by clang-format. NFC.Chandler Carruth2015-12-281-4/+4
| | | | llvm-svn: 256480
* Revert r225854: [PM] Move the LazyCallGraph printing functionality toChandler Carruth2015-01-141-38/+36
| | | | | | | | | | | | | | | a print method. This was formulated on a bad idea, but sadly I didn't uncover how bad this was until I got further down the path. I had hoped that we could provide a low boilerplate way of printing analyses, but it just doesn't seem like this really fits the needs of the analyses. Not all analyses really want to do printing, and those that do don't all use the same interface. Instead, with the new pass manager let's just take advantage of the fact that creating an explicit printer pass like the LCG has is pretty low boilerplate already and rely on that for testing. llvm-svn: 225861
* [PM] Move the LazyCallGraph printing functionality to a print method.Chandler Carruth2015-01-131-36/+38
| | | | | | | | I'm adding generic analysis printing utility pass support which will require such a method (or a specialization) so this will let the existing printing logic satisfy that. llvm-svn: 225854
* [PM] Switch the new pass manager to use a reference-based API for IRChandler Carruth2015-01-051-3/+2
| | | | | | | | | | | | | | | | | | | | | units. This was debated back and forth a bunch, but using references is now clearly cleaner. Of all the code written using pointers thus far, in only one place did it really make more sense to have a pointer. In most cases, this just removes immediate dereferencing from the code. I think it is much better to get errors on null IR units earlier, potentially at compile time, than to delay it. Most notably, the legacy pass manager uses references for its routines and so as more and more code works with both, the use of pointers was likely to become really annoying. I noticed this when I ported the domtree analysis over and wrote the entire thing with references only to have it fail to compile. =/ It seemed better to switch now than to delay. We can, of course, revisit this is we learn that references are really problematic in the API. llvm-svn: 225145
* Update SetVector to rely on the underlying set's insert to return a ↵David Blaikie2014-11-191-5/+5
| | | | | | | | | | | | | pair<iterator, bool> This is to be consistent with StringSet and ultimately with the standard library's associative container insert function. This lead to updating SmallSet::insert to return pair<iterator, bool>, and then to update SmallPtrSet::insert to return pair<iterator, bool>, and then to update all the existing users of those functions... llvm-svn: 222334
* Fix typosAlp Toker2014-05-151-2/+2
| | | | llvm-svn: 208839
* [LCG] Add the last (and most complex) of the edge insertion mutationChandler Carruth2014-05-041-0/+119
| | | | | | | | | | | | | operations on the call graph. This one forms a cycle, and while not as complex as removing an internal edge from an SCC, it involves a reasonable amount of work to find all of the nodes newly connected in a cycle. Also somewhat alarming is the worst case complexity here: it might have to walk roughly the entire SCC inverse DAG to insert a single edge. This is carefully documented in the API (I hope). llvm-svn: 207935
* [LCG] Add the other simple edge insertion API to the call graph. ThisChandler Carruth2014-05-011-0/+15
| | | | | | | | | just connects an SCC to one of its descendants directly. Not much of an impact. The last one is the hard one -- connecting an SCC to one of its ancestors, and thereby forming a cycle such that we have to merge all the SCCs participating in the cycle. llvm-svn: 207751
* [LCG] Don't lookup the child SCC twice. Spotted this by inspection, andChandler Carruth2014-05-011-2/+2
| | | | | | no functionality changed. llvm-svn: 207750
* [LCG] Add some basic methods for querying the parent/child relationshipsChandler Carruth2014-05-011-0/+15
| | | | | | | | of SCCs in the SCC DAG. Exercise them in the big graph test case. These will be especially useful for establishing invariants in insertion logic. llvm-svn: 207749
* [LCG] Add the really, *really* boring edge insertion case: adding anChandler Carruth2014-04-301-4/+19
| | | | | | | | | | edge entirely within an existing SCC. Shockingly, making the connected component more connected is ... a total snooze fest. =] Anyways, its wired up, and I even added a test case to make sure it pretty much sorta works. =D llvm-svn: 207631
* [LCG] Actually test the *basic* edge removal bits (IE, the non-SCCChandler Carruth2014-04-301-4/+8
| | | | | | | | | | | | | | | | | | | | | | | | | | bits), and discover that it's totally broken. Yay tests. Boo bug. Fix the basic edge removal so that it works by nulling out the removed edges rather than actually removing them. This leaves the indices valid in the map from callee to index, and preserves some of the locality for iterating over edges. The iterator is made bidirectional to reflect that it now has to skip over null entries, and the skipping logic is layered onto it. As future work, I would like to track essentially the "load factor" of the edge list, and when it falls below a threshold do a compaction. An alternative I considered (and continue to consider) is storing the callees in a doubly linked list where each element of the list is in a set (which is essentially the classical linked-hash-table datastructure). The problem with that approach is that either you need to heap allocate the linked list nodes and use pointers to them, or use a bucket hash table (with even *more* linked list pointer overhead!), etc. It's pretty easy to get 5x overhead for values that are just pointers. So far, I think punching holes in the vector, and periodic compaction is likely to be much more efficient overall in the space/time tradeoff. llvm-svn: 207619
* [LCG] Add the most basic of edge insertion to the lazy call graph. ThisChandler Carruth2014-04-281-0/+15
| | | | | | | just handles the pre-DFS case. Also add some test cases for this case to make sure it works. llvm-svn: 207411
* [LCG] Make the return of the IntraSCC removal method actually match itsChandler Carruth2014-04-281-5/+3
| | | | | | | | contract (and be much more useful). It now provides exactly the post-order traversal a caller might need to perform on newly formed SCCs. llvm-svn: 207410
* [LCG] Re-organize the methods for mutating a call graph to make theirChandler Carruth2014-04-271-76/+78
| | | | | | | | | | | | | | | | | | | | | | | | | | | | API requirements much more obvious. The key here is that there are two totally different use cases for mutating the graph. Prior to doing any SCC formation, it is very easy to mutate the graph. There may be users that want to do small tweaks here, and then use the already-built graph for their SCC-based operations. This method remains on the graph itself and is documented carefully as being cheap but unavailable once SCCs are formed. Once SCCs are formed, and there is some in-flight DFS building them, we have to be much more careful in how we mutate the graph. These mutation operations are sunk onto the SCCs themselves, which both simplifies things (the code was already there!) and helps make it obvious that these interfaces are only applicable within that context. The other primary constraint is that the edge being mutated is actually related to the SCC on which we call the method. This helps make it obvious that you cannot arbitrarily mutate some other SCC. I've tried to write much more complete documentation for the interesting mutation API -- intra-SCC edge removal. Currently one aspect of this documentation is a lie (the result list of SCCs) but we also don't even have tests for that API. =[ I'm going to add tests and fix it to match the documentation next. llvm-svn: 207339
* [LCG] Rather than removing nodes from the SCC entry set when we processChandler Carruth2014-04-261-6/+7
| | | | | | | | | | them, just skip over any DFS-numbered nodes when finding the next root of a DFS. This allows the entry set to just be a vector as we populate it from a uniqued source. It also removes the possibility for a linear scan of the entry set to actually do the removal which can make things go quadratic if we get unlucky. llvm-svn: 207312
* [LCG] Rotate the full SCC finding algorithm to avoid round-trips throughChandler Carruth2014-04-261-21/+23
| | | | | | | | | | | | | | | the DFS stack for leaves in the call graph. As mentioned in my previous commit, this is particularly interesting for graphs which have high fan out but low connectivity resulting in many leaves. For such graphs, this can remove a large % of the DFS stack traffic even though it doesn't make the stack much smaller. It's a bit easier to formulate this for the full algorithm because that one stops completely for each SCC. For example, I was able to directly eliminate the "Recurse" boolean used to continue an outer loop from the inner loop. llvm-svn: 207311
* [LCG] Hoist the main DFS loop out of the edge removal function. ThisChandler Carruth2014-04-261-74/+70
| | | | | | | | | makes working through the worklist much cleaner, and makes it possible to avoid the 'bool-to-continue-the-outer-loop' hack. Not a huge difference, but I think this is approaching as polished as I can make it. llvm-svn: 207310
* [LCG] In the incremental SCC re-formation, lift the node currently beingChandler Carruth2014-04-261-30/+38
| | | | | | | | | | | | | | | | | | | processed in the DFS out of the stack completely. Keep it exclusively in a variable. Re-shuffle some code structure to make this easier. This can have a very dramatic effect in some cases because call graphs tend to look like a high fan-out spanning tree. As a consequence, there are a large number of leaf nodes in the graph, and this technique causes leaf nodes to never even go into the stack. While this only reduces the max depth by 1, it may cause the total number of round trips through the stack to drop by a lot. Now, most of this isn't really relevant for the incremental version. =] But I wanted to prototype it first here as this variant is in ways more complex. As long as I can get the code factored well here, I'll next make the primary walk look the same. There are several refactorings this exposes I think. llvm-svn: 207306
* [LCG] Special case the removal of self edges. These don't impact the SCCChandler Carruth2014-04-261-0/+6
| | | | | | | | graph in any way because we don't track edges in the SCC graph, just nodes. This also lets us add a nice assert about the invariant that we're working on at least a certain number of nodes within the SCC. llvm-svn: 207305
* [LCG] Refactor the duplicated code I added in my last commit here intoChandler Carruth2014-04-261-23/+14
| | | | | | | a helper function. Also factor the other two places where we did the same thing into the helper function. =] Much cleaner this way. NFC. llvm-svn: 207300
* [LCG] During the incremental update of an SCC, switch to using theChandler Carruth2014-04-251-26/+26
| | | | | | | | | | | | | | | | | | SCCMap to test for nodes that have been re-added to the root SCC rather than a set vector. We already have done the SCCMap lookup, we juts need to test it in two different ways. In turn, do most of the processing of these nodes as they go into the root SCC rather than lazily. This simplifies the final loop to just stitch the root SCC into its children's parent sets. No functionlatiy changed. However, this makes a few things painfully obvious, which was my intent. =] There is tons of repeated code introduced here and elsewhere. I'm splitting the refactoring of that code into helpers from this change so its clear that this is the change which switches the datastructures used around, and the other is a pure factoring & deduplication of code change. llvm-svn: 207217
* [LCG] During the incremental re-build of an SCC after removing an edge,Chandler Carruth2014-04-251-4/+5
| | | | | | | | | | | | | | | | | | remove the nodes in the SCC from the SCC map entirely prior to the DFS walk. This allows the SCC map to represent both the state of not-yet-re-added-to-an-SCC and added-back-to-this-SCC independently. The first is being missing from the SCC map, the second is mapping back to 'this'. In a subsequent commit, I'm going to use this property to simplify the new node list for this SCC. In theory, I think this also makes the contract for orphaning a node from the graph slightly less confusing. Now it is also orphaned from the SCC graph. Still, this isn't quite right either, and so I'm not adding test cases here. I'll add test cases for the behavior of orphaning nodes when the code *actually* supports it. The change here is mostly incidental, my goal is simplifying the algorithm. llvm-svn: 207213
* [LCG] Rather than doing a linear time SmallSetVector removal of eachChandler Carruth2014-04-251-6/+7
| | | | | | | | | child from the worklist, wait until we actually need to pop another element off of the worklist and skip over any that were already visited by the DFS. This also enables swapping the nodes of the SCC into the worklist. No functionality changed. llvm-svn: 207212
* [LCG] Remove a completely unnecessary loop. It wasn't even doing anyChandler Carruth2014-04-251-60/+54
| | | | | | | | | thing, just mucking up the code. I feel bad that I even wrote this loop. Very sorry. The diff is huge because of the indent change, but I promise all this is doing is realizing that the outer two loops were actually the exact same loops, and we didn't need two of them. llvm-svn: 207202
* [LCG] Now that the loop structure of the core SCC finding routine isChandler Carruth2014-04-251-1/+8
| | | | | | | | | factored into a more reasonable form, replace the tail call with a simple outer-loop continuation. It's sad that C++ makes this so awkward to write, but it seems more direct and clear than the tail call at this point. llvm-svn: 207201
* [LCG] Switch a weird do/while loop that actually couldn't fail itsChandler Carruth2014-04-241-5/+4
| | | | | | | condition into an obviously infinite loop with an assert about the degenerate condition. No functionality changed. llvm-svn: 207147
* [LCG] Incorporate the core trick of improvements on the naive Tarjan'sChandler Carruth2014-04-241-41/+61
| | | | | | | | | | | | | | | | | | | | | | | | | | | algorithm here: http://dl.acm.org/citation.cfm?id=177301. The idea of isolating the roots has even more relevance when using the stack not just to implement the DFS but also to implement the recursive step. Because we use it for the recursive step, to isolate the roots we need to maintain two stacks: one for our recursive DFS walk, and another of the nodes that have been walked. The nice thing is that the latter will be half the size. It also fixes a complete hack where we scanned backwards over the stack to find the next potential-root to continue processing. Now that is always the top of the DFS stack. While this is a really nice improvement already (IMO) it further opens the door for two important simplifications: 1) De-duplicating some of the code across the two different walks. I've actually made the duplication a bit worse in some senses with this patch because the two are starting to converge. 2) Dramatically simplifying the loop structures of both walks. I wanted to do those separately as they'll be essentially *just* CFG restructuring. This patch on the other hand actually uses different datastructures to implement the algorithm itself. llvm-svn: 207098
* [LCG] Rotate logic applied to the top of the DFSStack to instead beChandler Carruth2014-04-241-25/+24
| | | | | | | | | | | | | applied prior to pushing a node onto the DFSStack. This is the first step toward avoiding the stack entirely for leaf nodes. It also simplifies things a bit and I think is pointing the way toward factoring some more of the shared logic out of the two implementations. It is also making it more obvious how to restructure the loops themselves to be a bit easier to read (although no different in terms of functionality). llvm-svn: 207095
* [LCG] Switch the parent SCC tracking from a SmallSetVector toChandler Carruth2014-04-241-2/+2
| | | | | | | | | | | | | | | | a SmallPtrSet. Currently, there is no need for stable iteration in this dimension, and I now thing there won't need to be going forward. If this is ever re-introduced in any form, it needs to not be a SetVector based solution because removal cannot be linear. There will be many SCCs with large numbers of parents. When encountering these, the incremental SCC update for intra-SCC edge removal was quadratic due to linear removal (kind of). I'm really hoping we can avoid having an ordering property here at all though... llvm-svn: 207091
* [LCG] We don't actually need a set in each SCC to track the nodes. WeChandler Carruth2014-04-241-7/+1
| | | | | | | can use the node -> SCC mapping in the top-level graph to test this on the rare occasions we need it. llvm-svn: 207090
* [LCG] Normalize the post-order SCC iterator to just iterate over the SCCChandler Carruth2014-04-231-2/+2
| | | | | | values rather than having pointers in weird places. llvm-svn: 207053
* [LCG] Switch the primary node iterator to be a *much* more normal C++Chandler Carruth2014-04-231-39/+33
| | | | | | iterator, returning a Node by reference on dereference. llvm-svn: 207048
* [LCG] Make the insertion and query paths into the LCG which cannot failChandler Carruth2014-04-231-4/+4
| | | | | | | | return references to better model this property. No functionality changed. llvm-svn: 207047
* [LCG] Switch the SCC lookup to be in terms of call graph nodes ratherChandler Carruth2014-04-231-8/+8
| | | | | | | | | | than functions. So far, this access pattern is *much* more common. It seems likely that any user of this interface is going to have nodes at the point that they are querying the SCCs. No functionality changed. llvm-svn: 207045
* [LCG] Switch the primary SCC building code to use the negative low-linkChandler Carruth2014-04-231-2/+4
| | | | | | | | | | | | | | | values rather than an expensive dense map query to test whether children have already been popped into an SCC. This matches the incremental SCC building code. I've also included the assert that I put there but updated both of their text. No functionality changed here. I still don't have any great ideas for sharing the code between the two implementations, but I may try a brute-force approach to factoring it at some point. llvm-svn: 207042
* [LCG] Add the first round of mutation support to the lazy call graph.Chandler Carruth2014-04-231-0/+233
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | This implements the core functionality necessary to remove an edge from the call graph and correctly update both the basic graph and the SCC structure. As part of that it has to run a tiny (in number of nodes) Tarjan-style DFS walk of an SCC being mutated to compute newly formed SCCs, etc. This is *very rough* and a WIP. I have a bunch of FIXMEs for code cleanup that will reduce the boilerplate in this change substantially. I also have a bunch of simplifications to various parts of both algorithms that I want to make, but first I'd like to have a more holistic picture. Ideally, I'd also like more testing. I'll probably add quite a few more unit tests as I go here to cover the various different aspects and corner cases of removing edges from the graph. Still, this is, so far, successfully updating the SCC graph in-place without disrupting the identity established for the existing SCCs even when we do challenging things like delete the critical edge that made an SCC cycle at all and have to reform things as a tree of smaller SCCs. Getting this to work is really critical for the new pass manager as it is going to associate significant state with the SCC instance and needs it to be stable. That is also the motivation behind the return of the newly formed SCCs. Eventually, I'll wire this all the way up to the public API so that the pass manager can use it to correctly re-enqueue newly formed SCCs into a fresh postorder traversal. llvm-svn: 206968
* [LCG] Implement Tarjan's algorithm correctly this time. We have to walkChandler Carruth2014-04-231-34/+42
| | | | | | | | | | | | up the stack finishing the exploration of each entries children before we're finished in addition to accounting for their low-links. Added a unittest that really hammers home the need for this with interlocking cycles that would each appear distinct otherwise and crash or compute the wrong result. As part of this, nuke a stale fixme and bring the rest of the implementation still more closely in line with the original algorithm. llvm-svn: 206966
* [LCG] Add a unittest for the LazyCallGraph. I had a weak moment andChandler Carruth2014-04-231-0/+2
| | | | | | | | | | | | | | | | | | | | | | | | resisted this for too long. Just with the basic testing here I was able to exercise the analysis in more detail and sift out both type signature bugs in the API and a bug in the DFS numbering. All of these are fixed here as well. The unittests will be much more important for the mutation support where it is necessary to craft minimal mutations and then inspect the state of the graph. There is just no way to do that with a standard FileCheck test. However, unittesting these kinds of analyses is really quite easy, especially as they're designed with the new pass manager where there is essentially no infrastructure required to rig up the core logic and exercise it at an API level. As a minor aside about the DFS numbering bug, the DFS numbering used in LCG is a bit unusual. Rather than numbering from 0, we number from 1, and use 0 as the sentinel "unvisited" state. Other implementations often use '-1' for this, but I find it easier to deal with 0 and it shouldn't make any real difference provided someone doesn't write silly bugs like forgetting to actually initialize the DFS numbering. Oops. ;] llvm-svn: 206954
* [LCG] Hoist the logic for forming a new SCC from the top of the DFSStackChandler Carruth2014-04-231-41/+47
| | | | | | | into a helper function. I plan to re-use it for doing incremental DFS-based updates to the SCCs when we mutate the call graph. llvm-svn: 206948
OpenPOWER on IntegriCloud