From: Rafael Espindola Date: Thu, 26 Nov 2015 19:22:59 +0000 (+0000) Subject: Disallow aliases to available_externally. X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=commitdiff_plain;h=58019e7bea3edec0a60b593799142402ab562216 Disallow aliases to available_externally. They are as much trouble as aliases to declarations. They are requiring the code generator to define a symbol with the same value as another symbol, but the second symbol is undefined. If representing this is important for some optimization, we could add support for available_externally aliases. They would be *required* to point to a declaration (or available_externally definition). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@254170 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/IR/Verifier.cpp b/lib/IR/Verifier.cpp index cf7b4cac342..617d965f4cf 100644 --- a/lib/IR/Verifier.cpp +++ b/lib/IR/Verifier.cpp @@ -571,7 +571,8 @@ void Verifier::visitAliaseeSubExpr(const GlobalAlias &GA, const Constant &C) { void Verifier::visitAliaseeSubExpr(SmallPtrSetImpl &Visited, const GlobalAlias &GA, const Constant &C) { if (const auto *GV = dyn_cast(&C)) { - Assert(!GV->isDeclaration(), "Alias must point to a definition", &GA); + Assert(!GV->isDeclarationForLinker(), "Alias must point to a definition", + &GA); if (const auto *GA2 = dyn_cast(GV)) { Assert(Visited.insert(GA2).second, "Aliases cannot form a cycle", &GA); diff --git a/lib/Linker/LinkModules.cpp b/lib/Linker/LinkModules.cpp index 8970fe44613..bd445dd367f 100644 --- a/lib/Linker/LinkModules.cpp +++ b/lib/Linker/LinkModules.cpp @@ -655,7 +655,10 @@ bool ModuleLinker::doImportAsDefinition(const GlobalValue *SGV) { if (GA) { if (GA->hasWeakAnyLinkage()) return false; - return doImportAsDefinition(GA->getBaseObject()); + const GlobalObject *GO = GA->getBaseObject(); + if (!GO->hasLinkOnceODRLinkage()) + return false; + return doImportAsDefinition(GO); } // Always import GlobalVariable definitions, except for the special // case of WeakAny which are imported as ExternalWeak declarations diff --git a/lib/Transforms/IPO/ElimAvailExtern.cpp b/lib/Transforms/IPO/ElimAvailExtern.cpp index 0e138cbbc7a..af313a6b001 100644 --- a/lib/Transforms/IPO/ElimAvailExtern.cpp +++ b/lib/Transforms/IPO/ElimAvailExtern.cpp @@ -49,46 +49,9 @@ ModulePass *llvm::createEliminateAvailableExternallyPass() { return new EliminateAvailableExternally(); } -static void convertAliasToDeclaration(GlobalAlias &GA, Module &M) { - GlobalValue *GVal = GA.getBaseObject(); - GlobalValue *NewGV; - if (auto *GVar = dyn_cast(GVal)) { - GlobalVariable *NewGVar = new GlobalVariable( - M, GVar->getType()->getElementType(), GVar->isConstant(), - GVar->getLinkage(), /*init*/ nullptr, GA.getName(), GVar, - GVar->getThreadLocalMode(), GVar->getType()->getAddressSpace()); - NewGV = NewGVar; - NewGV->copyAttributesFrom(GVar); - } else { - auto *F = dyn_cast(GVal); - assert(F); - Function *NewF = Function::Create(F->getFunctionType(), F->getLinkage(), - GA.getName(), &M); - NewGV = NewF; - NewGV->copyAttributesFrom(F); - } - GA.replaceAllUsesWith(ConstantExpr::getBitCast(NewGV, GA.getType())); - GA.eraseFromParent(); -} - bool EliminateAvailableExternally::runOnModule(Module &M) { bool Changed = false; - // Convert any aliases that alias with an available externally - // value (which will be turned into declarations later on in this routine) - // into declarations themselves. All aliases must be definitions, and - // must alias with a definition. So this involves creating a declaration - // equivalent to the alias's base object. - for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end(); I != E;) { - // Increment the iterator first since we may delete the current alias. - GlobalAlias &GA = *(I++); - GlobalValue *GVal = GA.getBaseObject(); - if (!GVal->hasAvailableExternallyLinkage()) - continue; - convertAliasToDeclaration(GA, M); - Changed = true; - } - // Drop initializers of available externally global variables. for (GlobalVariable &GV : M.globals()) { if (!GV.hasAvailableExternallyLinkage()) diff --git a/test/Linker/funcimport.ll b/test/Linker/funcimport.ll index d6aa0502f26..8a71e21d0ad 100644 --- a/test/Linker/funcimport.ll +++ b/test/Linker/funcimport.ll @@ -36,7 +36,7 @@ ; turned into a declaration, but that strong alias to an imported function ; is imported as alias. ; RUN: llvm-link %t2.bc -functionindex=%t3.thinlto.bc -import=globalfunc2:%t.bc -S | FileCheck %s --check-prefix=IMPORTGLOB2 -; IMPORTGLOB2-DAG: @analias = alias void (...), bitcast (void ()* @globalfunc2 +; IMPORTGLOB2-DAG: declare void @analias() ; IMPORTGLOB2-DAG: declare void @globalfunc1 ; IMPORTGLOB2-DAG: define available_externally void @globalfunc2 ; IMPORTGLOB2-DAG: declare extern_weak void @weakalias @@ -44,7 +44,7 @@ ; Ensure that strong alias imported in second pass of importing ends up ; as an alias. ; RUN: llvm-link %t2.bc -functionindex=%t3.thinlto.bc -import=globalfunc1:%t.bc -import=globalfunc2:%t.bc -S | FileCheck %s --check-prefix=IMPORTGLOB3 -; IMPORTGLOB3-DAG: @analias = alias void (...), bitcast (void ()* @globalfunc2 +; IMPORTGLOB3-DAG: declare void @analias() ; IMPORTGLOB3-DAG: define available_externally void @globalfunc1 ; IMPORTGLOB3-DAG: define available_externally void @globalfunc2 ; IMPORTGLOB3-DAG: declare extern_weak void @weakalias @@ -53,11 +53,17 @@ ; as an alias, and that seeing the alias definition during a second inlining ; pass is handled correctly. ; RUN: llvm-link %t2.bc -functionindex=%t3.thinlto.bc -import=globalfunc2:%t.bc -import=globalfunc1:%t.bc -S | FileCheck %s --check-prefix=IMPORTGLOB4 -; IMPORTGLOB4-DAG: @analias = alias void (...), bitcast (void ()* @globalfunc2 +; IMPORTGLOB4-DAG: declare void @analias() ; IMPORTGLOB4-DAG: define available_externally void @globalfunc2 ; IMPORTGLOB4-DAG: define available_externally void @globalfunc1 ; IMPORTGLOB4-DAG: declare extern_weak void @weakalias +; An alias to an imported function is imported as alias if the function is not +; available_externally. +; RUN: llvm-link %t2.bc -functionindex=%t3.thinlto.bc -import=linkoncefunc:%t.bc -S | FileCheck %s --check-prefix=IMPORTGLOB5 +; IMPORTGLOB5-DAG: linkoncealias = alias void (...), bitcast (void ()* @linkoncefunc to void (...)*) +; IMPORTGLOB5-DAG: define linkonce_odr void @linkoncefunc() + ; Ensure that imported static variable and function references are correctly ; promoted and renamed (including static constant variable). ; RUN: llvm-link %t2.bc -functionindex=%t3.thinlto.bc -import=referencestatics:%t.bc -S | FileCheck %s --check-prefix=IMPORTSTATIC diff --git a/test/Transforms/FunctionImport/funcimport.ll b/test/Transforms/FunctionImport/funcimport.ll index 57452b1ec53..2c9164fdaa9 100644 --- a/test/Transforms/FunctionImport/funcimport.ll +++ b/test/Transforms/FunctionImport/funcimport.ll @@ -14,6 +14,7 @@ define i32 @main() #0 { entry: call void (...) @weakalias() call void (...) @analias() + call void (...) @linkoncealias() %call = call i32 (...) @referencestatics() %call1 = call i32 (...) @referenceglobals() %call2 = call i32 (...) @referencecommon() @@ -27,11 +28,15 @@ entry: ; CHECK-DAG: declare extern_weak void @weakalias() declare void @weakalias(...) #1 -; Aliases import the aliasee function -; CHECK-DAG: @analias = alias void (...), bitcast (void ()* @globalfunc2 to void (...)*) -; CHECK-DAG: define available_externally void @globalfunc2() +; Cannot create an alias to available_externally +; CHECK-DAG: declare void @analias() declare void @analias(...) #1 +; Aliases import the aliasee function +declare void @linkoncealias(...) #1 +; CHECK-DAG: define linkonce_odr void @linkoncefunc() +; CHECK-DAG: @linkoncealias = alias void (...), bitcast (void ()* @linkoncefunc to void (...)* + ; INSTLIMDEF-DAG: define available_externally i32 @referencestatics(i32 %i) ; INSTLIM5-DAG: declare i32 @referencestatics(...) declare i32 @referencestatics(...) #1 diff --git a/test/Verifier/alias.ll b/test/Verifier/alias.ll index 3fb140464ec..1847c0d4214 100644 --- a/test/Verifier/alias.ll +++ b/test/Verifier/alias.ll @@ -11,6 +11,12 @@ declare void @f() ; CHECK: Alias must point to a definition ; CHECK-NEXT: @ga +define available_externally void @f2() { + ret void +} +@fa2 = alias void(), void()* @f2 +; CHECK: Alias must point to a definition +; CHECK-NEXT: @fa2 @test2_a = alias i32, i32* @test2_b @test2_b = alias i32, i32* @test2_a