summaryrefslogtreecommitdiffstats
path: root/unittests
diff options
context:
space:
mode:
authorChandler Carruth <chandlerc@gmail.com>2017-07-15 08:08:19 +0000
committerChandler Carruth <chandlerc@gmail.com>2017-07-15 08:08:19 +0000
commited504111e8930fedf8ccd6d48dae87d55d8abd43 (patch)
treee27afb9141844a8ce326dc1fe68536f65998c85a /unittests
parentb51511924409bfbbcdbdf6c9b875b2affcb8bdc8 (diff)
[PM/LCG] Teach the LazyCallGraph to maintain reference edges from every
function to every defined function known to LLVM as a library function. LLVM can introduce calls to these functions either by replacing other library calls or by recognizing patterns (such as memset_pattern or vector math patterns) and replacing those with calls. When these library functions are actually defined in the module, we need to have reference edges to them initially so that we visit them during the CGSCC walk in the right order and can effectively rebuild the call graph afterward. This was discovered when building code with Fortify enabled as that is a common case of both inline definitions of library calls and simplifications of code into calling them. This can in extreme cases of LTO-ing with libc introduce *many* more reference edges. I discussed a bunch of different options with folks but all of them are unsatisfying. They either make the graph operations substantially more complex even when there are *no* defined libfuncs, or they introduce some other complexity into the callgraph. So this patch goes with the simplest possible solution of actual synthetic reference edges. If this proves to be a memory problem, I'm happy to implement one of the clever techniques to save memory here. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@308088 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'unittests')
-rw-r--r--unittests/Analysis/CGSCCPassManagerTest.cpp2
-rw-r--r--unittests/Analysis/LazyCallGraphTest.cpp47
2 files changed, 29 insertions, 20 deletions
diff --git a/unittests/Analysis/CGSCCPassManagerTest.cpp b/unittests/Analysis/CGSCCPassManagerTest.cpp
index d46d9535fa4b..e24818265975 100644
--- a/unittests/Analysis/CGSCCPassManagerTest.cpp
+++ b/unittests/Analysis/CGSCCPassManagerTest.cpp
@@ -9,6 +9,7 @@
#include "llvm/Analysis/CGSCCPassManager.h"
#include "llvm/Analysis/LazyCallGraph.h"
+#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/AsmParser/Parser.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/InstIterator.h"
@@ -227,6 +228,7 @@ public:
"entry:\n"
" ret void\n"
"}\n")) {
+ MAM.registerPass([&] { return TargetLibraryAnalysis(); });
MAM.registerPass([&] { return LazyCallGraphAnalysis(); });
MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); });
MAM.registerPass([&] { return CGSCCAnalysisManagerModuleProxy(CGAM); });
diff --git a/unittests/Analysis/LazyCallGraphTest.cpp b/unittests/Analysis/LazyCallGraphTest.cpp
index 65730486cd75..9e7e128bcfb3 100644
--- a/unittests/Analysis/LazyCallGraphTest.cpp
+++ b/unittests/Analysis/LazyCallGraphTest.cpp
@@ -216,10 +216,17 @@ static const char DiamondOfTrianglesRefGraph[] =
" ret void\n"
"}\n";
+static LazyCallGraph buildCG(Module &M) {
+ TargetLibraryInfoImpl TLII(Triple(M.getTargetTriple()));
+ TargetLibraryInfo TLI(TLII);
+ LazyCallGraph CG(M, TLI);
+ return CG;
+}
+
TEST(LazyCallGraphTest, BasicGraphFormation) {
LLVMContext Context;
std::unique_ptr<Module> M = parseAssembly(Context, DiamondOfTriangles);
- LazyCallGraph CG(*M);
+ LazyCallGraph CG = buildCG(*M);
// The order of the entry nodes should be stable w.r.t. the source order of
// the IR, and everything in our module is an entry node, so just directly
@@ -407,7 +414,7 @@ TEST(LazyCallGraphTest, BasicGraphMutation) {
"entry:\n"
" ret void\n"
"}\n");
- LazyCallGraph CG(*M);
+ LazyCallGraph CG = buildCG(*M);
LazyCallGraph::Node &A = CG.get(lookupFunction(*M, "a"));
LazyCallGraph::Node &B = CG.get(lookupFunction(*M, "b"));
@@ -445,7 +452,7 @@ TEST(LazyCallGraphTest, BasicGraphMutation) {
TEST(LazyCallGraphTest, InnerSCCFormation) {
LLVMContext Context;
std::unique_ptr<Module> M = parseAssembly(Context, DiamondOfTriangles);
- LazyCallGraph CG(*M);
+ LazyCallGraph CG = buildCG(*M);
// Now mutate the graph to connect every node into a single RefSCC to ensure
// that our inner SCC formation handles the rest.
@@ -542,7 +549,7 @@ TEST(LazyCallGraphTest, MultiArmSCC) {
" call void @f1()\n"
" ret void\n"
"}\n");
- LazyCallGraph CG(*M);
+ LazyCallGraph CG = buildCG(*M);
// Force the graph to be fully expanded.
CG.buildRefSCCs();
@@ -593,7 +600,7 @@ TEST(LazyCallGraphTest, OutgoingEdgeMutation) {
"entry:\n"
" ret void\n"
"}\n");
- LazyCallGraph CG(*M);
+ LazyCallGraph CG = buildCG(*M);
// Force the graph to be fully expanded.
CG.buildRefSCCs();
@@ -739,7 +746,7 @@ TEST(LazyCallGraphTest, IncomingEdgeInsertion) {
// a3--a2 |
//
std::unique_ptr<Module> M = parseAssembly(Context, DiamondOfTriangles);
- LazyCallGraph CG(*M);
+ LazyCallGraph CG = buildCG(*M);
// Force the graph to be fully expanded.
CG.buildRefSCCs();
@@ -831,7 +838,7 @@ TEST(LazyCallGraphTest, IncomingEdgeInsertionRefGraph) {
// references rather than calls.
std::unique_ptr<Module> M =
parseAssembly(Context, DiamondOfTrianglesRefGraph);
- LazyCallGraph CG(*M);
+ LazyCallGraph CG = buildCG(*M);
// Force the graph to be fully expanded.
CG.buildRefSCCs();
@@ -938,7 +945,7 @@ TEST(LazyCallGraphTest, IncomingEdgeInsertionLargeCallCycle) {
"entry:\n"
" ret void\n"
"}\n");
- LazyCallGraph CG(*M);
+ LazyCallGraph CG = buildCG(*M);
// Force the graph to be fully expanded.
CG.buildRefSCCs();
@@ -1015,7 +1022,7 @@ TEST(LazyCallGraphTest, IncomingEdgeInsertionLargeRefCycle) {
"entry:\n"
" ret void\n"
"}\n");
- LazyCallGraph CG(*M);
+ LazyCallGraph CG = buildCG(*M);
// Force the graph to be fully expanded.
CG.buildRefSCCs();
@@ -1077,7 +1084,7 @@ TEST(LazyCallGraphTest, InlineAndDeleteFunction) {
// a3--a2 |
//
std::unique_ptr<Module> M = parseAssembly(Context, DiamondOfTriangles);
- LazyCallGraph CG(*M);
+ LazyCallGraph CG = buildCG(*M);
// Force the graph to be fully expanded.
CG.buildRefSCCs();
@@ -1221,7 +1228,7 @@ TEST(LazyCallGraphTest, InternalEdgeMutation) {
" call void @a()\n"
" ret void\n"
"}\n");
- LazyCallGraph CG(*M);
+ LazyCallGraph CG = buildCG(*M);
// Force the graph to be fully expanded.
CG.buildRefSCCs();
@@ -1315,7 +1322,7 @@ TEST(LazyCallGraphTest, InternalEdgeRemoval) {
" store i8* bitcast (void(i8**)* @c to i8*), i8** %ptr\n"
" ret void\n"
"}\n");
- LazyCallGraph CG(*M);
+ LazyCallGraph CG = buildCG(*M);
// Force the graph to be fully expanded.
CG.buildRefSCCs();
@@ -1390,7 +1397,7 @@ TEST(LazyCallGraphTest, InternalNoOpEdgeRemoval) {
" store i8* bitcast (void(i8**)* @b to i8*), i8** %ptr\n"
" ret void\n"
"}\n");
- LazyCallGraph CG(*M);
+ LazyCallGraph CG = buildCG(*M);
// Force the graph to be fully expanded.
CG.buildRefSCCs();
@@ -1467,7 +1474,7 @@ TEST(LazyCallGraphTest, InternalCallEdgeToRef) {
" call void @c()\n"
" ret void\n"
"}\n");
- LazyCallGraph CG(*M);
+ LazyCallGraph CG = buildCG(*M);
// Force the graph to be fully expanded.
CG.buildRefSCCs();
@@ -1560,7 +1567,7 @@ TEST(LazyCallGraphTest, InternalRefEdgeToCall) {
" store void()* @a, void()** undef\n"
" ret void\n"
"}\n");
- LazyCallGraph CG(*M);
+ LazyCallGraph CG = buildCG(*M);
// Force the graph to be fully expanded.
CG.buildRefSCCs();
@@ -1672,7 +1679,7 @@ TEST(LazyCallGraphTest, InternalRefEdgeToCallNoCycleInterleaved) {
" store void()* @a, void()** undef\n"
" ret void\n"
"}\n");
- LazyCallGraph CG(*M);
+ LazyCallGraph CG = buildCG(*M);
// Force the graph to be fully expanded.
CG.buildRefSCCs();
@@ -1802,7 +1809,7 @@ TEST(LazyCallGraphTest, InternalRefEdgeToCallBothPartitionAndMerge) {
" store void()* @a, void()** undef\n"
" ret void\n"
"}\n");
- LazyCallGraph CG(*M);
+ LazyCallGraph CG = buildCG(*M);
// Force the graph to be fully expanded.
CG.buildRefSCCs();
@@ -1885,7 +1892,7 @@ TEST(LazyCallGraphTest, HandleBlockAddress) {
" store i8* blockaddress(@f, %bb), i8** %ptr\n"
" ret void\n"
"}\n");
- LazyCallGraph CG(*M);
+ LazyCallGraph CG = buildCG(*M);
CG.buildRefSCCs();
auto I = CG.postorder_ref_scc_begin();
@@ -1933,7 +1940,7 @@ TEST(LazyCallGraphTest, ReplaceNodeFunction) {
" store i8* bitcast (void(i8**)* @d to i8*), i8** %ptr\n"
" ret void\n"
"}\n");
- LazyCallGraph CG(*M);
+ LazyCallGraph CG = buildCG(*M);
// Force the graph to be fully expanded.
CG.buildRefSCCs();
@@ -2011,7 +2018,7 @@ TEST(LazyCallGraphTest, RemoveFunctionWithSpurriousRef) {
"entry:\n"
" ret void\n"
"}\n");
- LazyCallGraph CG(*M);
+ LazyCallGraph CG = buildCG(*M);
// Insert spurious ref edges.
LazyCallGraph::Node &AN = CG.get(lookupFunction(*M, "a"));