diff options
author | Hal Finkel <hfinkel@anl.gov> | 2015-11-26 19:23:49 +0000 |
---|---|---|
committer | Hal Finkel <hfinkel@anl.gov> | 2015-11-26 19:23:49 +0000 |
commit | 28ad2b47dd109450ef910fdf477a2831f2f7947b (patch) | |
tree | 3c10f35ddf2e71d24afb1a2ee572502b47473ceb /llvm/tools/bugpoint/ExtractFunction.cpp | |
parent | 8934577171b967cc23186c2ffa0a0c4b54a8d992 (diff) | |
download | bcm5719-llvm-28ad2b47dd109450ef910fdf477a2831f2f7947b.tar.gz bcm5719-llvm-28ad2b47dd109450ef910fdf477a2831f2f7947b.zip |
[bugpoint] Fix "Alias must point to a definition" problems
GlobalAliases may reference function definitions, but not function declarations.
bugpoint would sometimes create invalid IR by deleting a function's body (thus
mutating a function definition into a declaration) without first 'fixing' any
GlobalAliases that reference that function definition.
This change iteratively prevents that issue. Before deleting a function's body,
it scans the module for GlobalAliases which reference that function. When
found, it eliminates them using replaceAllUsesWith.
Fixes PR20788.
Patch by Nick Johnson!
llvm-svn: 254171
Diffstat (limited to 'llvm/tools/bugpoint/ExtractFunction.cpp')
-rw-r--r-- | llvm/tools/bugpoint/ExtractFunction.cpp | 36 |
1 files changed, 34 insertions, 2 deletions
diff --git a/llvm/tools/bugpoint/ExtractFunction.cpp b/llvm/tools/bugpoint/ExtractFunction.cpp index 21d3d984599..7b98cb8fb55 100644 --- a/llvm/tools/bugpoint/ExtractFunction.cpp +++ b/llvm/tools/bugpoint/ExtractFunction.cpp @@ -179,11 +179,43 @@ std::unique_ptr<Module> BugDriver::extractLoop(Module *M) { return NewM; } +static void eliminateAliases(GlobalValue *GV) { + // First, check whether a GlobalAlias references this definition. + // GlobalAlias MAY NOT reference declarations. + for (;;) { + // 1. Find aliases + SmallVector<GlobalAlias*,1> aliases; + Module *M = GV->getParent(); + for (Module::alias_iterator I=M->alias_begin(), E=M->alias_end(); I!=E; ++I) + if (I->getAliasee()->stripPointerCasts() == GV) + aliases.push_back(&*I); + if (aliases.empty()) + break; + // 2. Resolve aliases + for (unsigned i=0, e=aliases.size(); i<e; ++i) { + aliases[i]->replaceAllUsesWith(aliases[i]->getAliasee()); + aliases[i]->eraseFromParent(); + } + // 3. Repeat until no more aliases found; there might + // be an alias to an alias... + } +} + +// +// DeleteGlobalInitializer - "Remove" the global variable by deleting its initializer, +// making it external. +// +void llvm::DeleteGlobalInitializer(GlobalVariable *GV) { + eliminateAliases(GV); + GV->setInitializer(nullptr); +} // DeleteFunctionBody - "Remove" the function by deleting all of its basic // blocks, making it external. // void llvm::DeleteFunctionBody(Function *F) { + eliminateAliases(F); + // delete the body of the function... F->deleteBody(); assert(F->isDeclaration() && "This didn't make the function external!"); @@ -323,10 +355,10 @@ llvm::SplitFunctionsOutOfModule(Module *M, << "' and from test function '" << TestFn->getName() << "'.\n"; exit(1); } - I.setInitializer(nullptr); // Delete the initializer to make it external + DeleteGlobalInitializer(&I); // 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(nullptr); + DeleteGlobalInitializer(GV); } } |