diff options
-rw-r--r-- | llvm/include/llvm/Analysis/LazyCallGraph.h | 10 | ||||
-rw-r--r-- | llvm/unittests/Analysis/LazyCallGraphTest.cpp | 31 |
2 files changed, 41 insertions, 0 deletions
diff --git a/llvm/include/llvm/Analysis/LazyCallGraph.h b/llvm/include/llvm/Analysis/LazyCallGraph.h index 58e32097bcd..8364465c3dc 100644 --- a/llvm/include/llvm/Analysis/LazyCallGraph.h +++ b/llvm/include/llvm/Analysis/LazyCallGraph.h @@ -44,6 +44,7 @@ #include "llvm/ADT/iterator.h" #include "llvm/ADT/iterator_range.h" #include "llvm/IR/BasicBlock.h" +#include "llvm/IR/Constants.h" #include "llvm/IR/Function.h" #include "llvm/IR/Module.h" #include "llvm/IR/PassManager.h" @@ -973,6 +974,15 @@ public: continue; } + if (BlockAddress *BA = dyn_cast<BlockAddress>(C)) { + // The blockaddress constant expression is a weird special case, we + // can't generically walk its operands the way we do for all other + // constants. + if (Visited.insert(BA->getFunction()).second) + Worklist.push_back(BA->getFunction()); + continue; + } + for (Value *Op : C->operand_values()) if (Visited.insert(cast<Constant>(Op)).second) Worklist.push_back(cast<Constant>(Op)); diff --git a/llvm/unittests/Analysis/LazyCallGraphTest.cpp b/llvm/unittests/Analysis/LazyCallGraphTest.cpp index d3022519f16..45c24eedf7e 100644 --- a/llvm/unittests/Analysis/LazyCallGraphTest.cpp +++ b/llvm/unittests/Analysis/LazyCallGraphTest.cpp @@ -2016,4 +2016,35 @@ TEST(LazyCallGraphTest, InternalRefEdgeToCallBothPartitionAndMerge) { EXPECT_EQ(&AC, &RC[4]); } +// Test for IR containing constants using blockaddress constant expressions. +// These are truly unique constructs: constant expressions with non-constant +// operands. +TEST(LazyCallGraphTest, HandleBlockAddress) { + LLVMContext Context; + std::unique_ptr<Module> M = + parseAssembly(Context, "define void @f() {\n" + "entry:\n" + " ret void\n" + "bb:\n" + " unreachable\n" + "}\n" + "define void @g(i8** %ptr) {\n" + "entry:\n" + " store i8* blockaddress(@f, %bb), i8** %ptr\n" + " ret void\n" + "}\n"); + LazyCallGraph CG(*M); + + auto I = CG.postorder_ref_scc_begin(); + LazyCallGraph::RefSCC &FRC = *I++; + LazyCallGraph::RefSCC &GRC = *I++; + EXPECT_EQ(CG.postorder_ref_scc_end(), I); + + LazyCallGraph::Node &F = *CG.lookup(lookupFunction(*M, "f")); + LazyCallGraph::Node &G = *CG.lookup(lookupFunction(*M, "g")); + EXPECT_EQ(&FRC, CG.lookupRefSCC(F)); + EXPECT_EQ(&GRC, CG.lookupRefSCC(G)); + EXPECT_TRUE(GRC.isParentOf(FRC)); +} + } |