1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 20:51:52 +01:00

Improve handling of blockaddresses in bugpoint when splitting a module. Patch by Daniel Reynaud.

llvm-svn: 151115
This commit is contained in:
Eli Friedman 2012-02-22 01:43:47 +00:00
parent a6003dae39
commit 87b4f40d41

View File

@ -47,7 +47,39 @@ namespace {
cl::opt<bool, true> cl::opt<bool, true>
NoSCFG("disable-simplifycfg", cl::location(DisableSimplifyCFG), NoSCFG("disable-simplifycfg", cl::location(DisableSimplifyCFG),
cl::desc("Do not use the -simplifycfg pass to reduce testcases")); cl::desc("Do not use the -simplifycfg pass to reduce testcases"));
}
Function* globalInitUsesExternalBA(GlobalVariable* GV) {
if (!GV->hasInitializer())
return 0;
Constant *I = GV->getInitializer();
// walk the values used by the initializer
// (and recurse into things like ConstantExpr)
std::vector<Constant*> Todo;
std::set<Constant*> Done;
Todo.push_back(I);
while (!Todo.empty()) {
Constant* V = Todo.back();
Todo.pop_back();
Done.insert(V);
if (BlockAddress *BA = dyn_cast<BlockAddress>(V)) {
Function *F = BA->getFunction();
if (F->isDeclaration())
return F;
}
for (User::op_iterator i = V->op_begin(), e = V->op_end(); i != e; ++i) {
Constant *C = dyn_cast<Constant>(*i);
if (C && !isa<GlobalValue>(C) && !Done.count(C))
Todo.push_back(C);
}
}
return 0;
}
} // end anonymous namespace
/// deleteInstructionFromProgram - This method clones the current Program and /// deleteInstructionFromProgram - This method clones the current Program and
/// deletes the specified instruction from the cloned module. It then runs a /// deletes the specified instruction from the cloned module. It then runs a
@ -272,11 +304,6 @@ llvm::SplitFunctionsOutOfModule(Module *M,
ValueToValueMapTy NewVMap; ValueToValueMapTy NewVMap;
Module *New = CloneModule(M, NewVMap); Module *New = CloneModule(M, NewVMap);
// Make sure global initializers exist only in the safe module (CBE->.so)
for (Module::global_iterator I = New->global_begin(), E = New->global_end();
I != E; ++I)
I->setInitializer(0); // Delete the initializer to make it external
// Remove the Test functions from the Safe module // Remove the Test functions from the Safe module
std::set<Function *> TestFunctions; std::set<Function *> TestFunctions;
for (unsigned i = 0, e = F.size(); i != e; ++i) { for (unsigned i = 0, e = F.size(); i != e; ++i) {
@ -295,6 +322,27 @@ llvm::SplitFunctionsOutOfModule(Module *M,
DeleteFunctionBody(I); DeleteFunctionBody(I);
// Try to split the global initializers evenly
for (Module::global_iterator I = M->global_begin(), E = M->global_end();
I != E; ++I) {
GlobalVariable *GV = cast<GlobalVariable>(NewVMap[I]);
if (Function *TestFn = globalInitUsesExternalBA(I)) {
if (Function *SafeFn = globalInitUsesExternalBA(GV)) {
errs() << "*** Error: when reducing functions, encountered "
"the global '";
WriteAsOperand(errs(), GV, false);
errs() << "' with an initializer that references blockaddresses "
"from safe function '" << SafeFn->getName()
<< "' and from test function '" << TestFn->getName() << "'.\n";
exit(1);
}
I->setInitializer(0); // Delete the initializer to make it external
} else {
// If we keep it in the safe module, then delete it in the test module
GV->setInitializer(0);
}
}
// Make sure that there is a global ctor/dtor array in both halves of the // Make sure that there is a global ctor/dtor array in both halves of the
// module if they both have static ctor/dtor functions. // module if they both have static ctor/dtor functions.
SplitStaticCtorDtor("llvm.global_ctors", M, New, NewVMap); SplitStaticCtorDtor("llvm.global_ctors", M, New, NewVMap);