[LCG] Teach the LazyCallGraph to handle visiting the blockaddress

constant expression and to correctly form function reference edges
through them without crashing because one of the operands (the
`BasicBlock` isn't actually a constant despite being an operand of
a constant).

llvm-svn: 290581
This commit is contained in:
Chandler Carruth 2016-12-27 05:00:45 +00:00
parent 70536f4e47
commit 162504578b
2 changed files with 41 additions and 0 deletions

View File

@ -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));

View File

@ -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));
}
}