[llvm] r223681 - Lazily link GlobalVariables and GlobalAliases.
Rafael Espindola
rafael.espindola at gmail.com
Mon Dec 8 10:45:17 PST 2014
Author: rafael
Date: Mon Dec 8 12:45:16 2014
New Revision: 223681
URL: http://llvm.org/viewvc/llvm-project?rev=223681&view=rev
Log:
Lazily link GlobalVariables and GlobalAliases.
We were already lazily linking functions, but all GlobalValues can be treated
uniformly for this.
The test updates are to ensure that a given GlobalValue is still linked in.
This fixes pr21494.
Added:
llvm/trunk/test/Linker/pr21494.ll
Modified:
llvm/trunk/lib/Linker/LinkModules.cpp
llvm/trunk/test/LTO/cfi_endproc.ll
llvm/trunk/test/LTO/linkonce_odr_func.ll
llvm/trunk/test/Linker/Inputs/testlink.ll
llvm/trunk/test/Linker/lto-attributes.ll
llvm/trunk/test/Linker/testlink.ll
Modified: llvm/trunk/lib/Linker/LinkModules.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Linker/LinkModules.cpp?rev=223681&r1=223680&r2=223681&view=diff
==============================================================================
--- llvm/trunk/lib/Linker/LinkModules.cpp (original)
+++ llvm/trunk/lib/Linker/LinkModules.cpp Mon Dec 8 12:45:16 2014
@@ -365,13 +365,13 @@ class ModuleLinker;
class ValueMaterializerTy : public ValueMaterializer {
TypeMapTy &TypeMap;
Module *DstM;
- std::vector<Function *> &LazilyLinkFunctions;
+ std::vector<GlobalValue *> &LazilyLinkGlobalValues;
public:
ValueMaterializerTy(TypeMapTy &TypeMap, Module *DstM,
- std::vector<Function *> &LazilyLinkFunctions)
+ std::vector<GlobalValue *> &LazilyLinkGlobalValues)
: ValueMaterializer(), TypeMap(TypeMap), DstM(DstM),
- LazilyLinkFunctions(LazilyLinkFunctions) {}
+ LazilyLinkGlobalValues(LazilyLinkGlobalValues) {}
Value *materializeValueFor(Value *V) override;
};
@@ -413,8 +413,8 @@ class ModuleLinker {
// Set of items not to link in from source.
SmallPtrSet<const Value *, 16> DoNotLinkFromSource;
- // Vector of functions to lazily link in.
- std::vector<Function *> LazilyLinkFunctions;
+ // Vector of GlobalValues to lazily link in.
+ std::vector<GlobalValue *> LazilyLinkGlobalValues;
Linker::DiagnosticHandlerFunction DiagnosticHandler;
@@ -422,7 +422,7 @@ public:
ModuleLinker(Module *dstM, Linker::IdentifiedStructTypeSet &Set, Module *srcM,
Linker::DiagnosticHandlerFunction DiagnosticHandler)
: DstM(dstM), SrcM(srcM), TypeMap(Set),
- ValMaterializer(TypeMap, DstM, LazilyLinkFunctions),
+ ValMaterializer(TypeMap, DstM, LazilyLinkGlobalValues),
DiagnosticHandler(DiagnosticHandler) {}
bool run();
@@ -484,16 +484,15 @@ private:
const GlobalVariable *SrcGV);
bool linkGlobalValueProto(GlobalValue *GV);
- GlobalValue *linkGlobalVariableProto(const GlobalVariable *SGVar);
- GlobalValue *linkFunctionProto(const Function *SF, GlobalValue *DGV);
- GlobalValue *linkGlobalAliasProto(const GlobalAlias *SGA);
-
bool linkModuleFlagsMetadata();
void linkAppendingVarInit(const AppendingVarInfo &AVI);
- void linkGlobalInits();
- bool linkFunctionBody(Function &Src);
- void linkAliasBodies();
+
+ void linkGlobalInit(GlobalVariable &Dst, GlobalVariable &Src);
+ bool linkFunctionBody(Function &Dst, Function &Src);
+ void linkAliasBody(GlobalAlias &Dst, GlobalAlias &Src);
+ bool linkGlobalValueBody(GlobalValue &Src);
+
void linkNamedMDNodes();
};
}
@@ -539,22 +538,71 @@ static bool isLessConstraining(GlobalVal
return false;
}
+/// Loop through the global variables in the src module and merge them into the
+/// dest module.
+static GlobalVariable *copyGlobalVariableProto(TypeMapTy &TypeMap, Module &DstM,
+ const GlobalVariable *SGVar) {
+ // No linking to be performed or linking from the source: simply create an
+ // identical version of the symbol over in the dest module... the
+ // initializer will be filled in later by LinkGlobalInits.
+ GlobalVariable *NewDGV = new GlobalVariable(
+ DstM, TypeMap.get(SGVar->getType()->getElementType()),
+ SGVar->isConstant(), SGVar->getLinkage(), /*init*/ nullptr,
+ SGVar->getName(), /*insertbefore*/ nullptr, SGVar->getThreadLocalMode(),
+ SGVar->getType()->getAddressSpace());
+
+ return NewDGV;
+}
+
+/// Link the function in the source module into the destination module if
+/// needed, setting up mapping information.
+static Function *copyFunctionProto(TypeMapTy &TypeMap, Module &DstM,
+ const Function *SF) {
+ // If there is no linkage to be performed or we are linking from the source,
+ // bring SF over.
+ return Function::Create(TypeMap.get(SF->getFunctionType()), SF->getLinkage(),
+ SF->getName(), &DstM);
+}
+
+/// Set up prototypes for any aliases that come over from the source module.
+static GlobalAlias *copyGlobalAliasProto(TypeMapTy &TypeMap, Module &DstM,
+ const GlobalAlias *SGA) {
+ // If there is no linkage to be performed or we're linking from the source,
+ // bring over SGA.
+ auto *PTy = cast<PointerType>(TypeMap.get(SGA->getType()));
+ return GlobalAlias::create(PTy->getElementType(), PTy->getAddressSpace(),
+ SGA->getLinkage(), SGA->getName(), &DstM);
+}
+
+static GlobalValue *copyGlobalValueProto(TypeMapTy &TypeMap, Module &DstM,
+ const GlobalValue *SGV) {
+ GlobalValue *NewGV;
+ if (auto *SGVar = dyn_cast<GlobalVariable>(SGV))
+ NewGV = copyGlobalVariableProto(TypeMap, DstM, SGVar);
+ else if (auto *SF = dyn_cast<Function>(SGV))
+ NewGV = copyFunctionProto(TypeMap, DstM, SF);
+ else
+ NewGV = copyGlobalAliasProto(TypeMap, DstM, cast<GlobalAlias>(SGV));
+ copyGVAttributes(NewGV, SGV);
+ return NewGV;
+}
+
Value *ValueMaterializerTy::materializeValueFor(Value *V) {
- Function *SF = dyn_cast<Function>(V);
- if (!SF)
+ auto *SGV = dyn_cast<GlobalValue>(V);
+ if (!SGV)
return nullptr;
- Function *DF = Function::Create(TypeMap.get(SF->getFunctionType()),
- SF->getLinkage(), SF->getName(), DstM);
- copyGVAttributes(DF, SF);
+ GlobalValue *DGV = copyGlobalValueProto(TypeMap, *DstM, SGV);
- if (Comdat *SC = SF->getComdat()) {
- Comdat *DC = DstM->getOrInsertComdat(SC->getName());
- DF->setComdat(DC);
+ if (Comdat *SC = SGV->getComdat()) {
+ if (auto *DGO = dyn_cast<GlobalObject>(DGV)) {
+ Comdat *DC = DstM->getOrInsertComdat(SC->getName());
+ DGO->setComdat(DC);
+ }
}
- LazilyLinkFunctions.push_back(SF);
- return DF;
+ LazilyLinkGlobalValues.push_back(SGV);
+ return DGV;
}
bool ModuleLinker::getComdatLeader(Module *M, StringRef ComdatName,
@@ -1021,19 +1069,16 @@ bool ModuleLinker::linkGlobalValueProto(
if (!LinkFromSrc) {
NewGV = DGV;
} else {
- if (auto *SGVar = dyn_cast<GlobalVariable>(SGV))
- NewGV = linkGlobalVariableProto(SGVar);
- else if (auto *SF = dyn_cast<Function>(SGV))
- NewGV = linkFunctionProto(SF, DGV);
- else
- NewGV = linkGlobalAliasProto(cast<GlobalAlias>(SGV));
- }
-
- if (!NewGV)
- return false;
+ // If the GV is to be lazily linked, don't create it just yet.
+ // The ValueMaterializerTy will deal with creating it if it's used.
+ if (!DGV && (SGV->hasLocalLinkage() || SGV->hasLinkOnceLinkage() ||
+ SGV->hasAvailableExternallyLinkage())) {
+ DoNotLinkFromSource.insert(SGV);
+ return false;
+ }
- if (NewGV != DGV)
- copyGVAttributes(NewGV, SGV);
+ NewGV = copyGlobalValueProto(TypeMap, *DstM, SGV);
+ }
NewGV->setUnnamedAddr(HasUnnamedAddr);
NewGV->setVisibility(Visibility);
@@ -1066,49 +1111,6 @@ bool ModuleLinker::linkGlobalValueProto(
return false;
}
-/// Loop through the global variables in the src module and merge them into the
-/// dest module.
-GlobalValue *
-ModuleLinker::linkGlobalVariableProto(const GlobalVariable *SGVar) {
- // No linking to be performed or linking from the source: simply create an
- // identical version of the symbol over in the dest module... the
- // initializer will be filled in later by LinkGlobalInits.
- GlobalVariable *NewDGV = new GlobalVariable(
- *DstM, TypeMap.get(SGVar->getType()->getElementType()),
- SGVar->isConstant(), SGVar->getLinkage(), /*init*/ nullptr,
- SGVar->getName(), /*insertbefore*/ nullptr, SGVar->getThreadLocalMode(),
- SGVar->getType()->getAddressSpace());
-
- return NewDGV;
-}
-
-/// Link the function in the source module into the destination module if
-/// needed, setting up mapping information.
-GlobalValue *ModuleLinker::linkFunctionProto(const Function *SF,
- GlobalValue *DGV) {
- // If the function is to be lazily linked, don't create it just yet.
- // The ValueMaterializerTy will deal with creating it if it's used.
- if (!DGV && (SF->hasLocalLinkage() || SF->hasLinkOnceLinkage() ||
- SF->hasAvailableExternallyLinkage())) {
- DoNotLinkFromSource.insert(SF);
- return nullptr;
- }
-
- // If there is no linkage to be performed or we are linking from the source,
- // bring SF over.
- return Function::Create(TypeMap.get(SF->getFunctionType()), SF->getLinkage(),
- SF->getName(), DstM);
-}
-
-/// Set up prototypes for any aliases that come over from the source module.
-GlobalValue *ModuleLinker::linkGlobalAliasProto(const GlobalAlias *SGA) {
- // If there is no linkage to be performed or we're linking from the source,
- // bring over SGA.
- auto *PTy = cast<PointerType>(TypeMap.get(SGA->getType()));
- return GlobalAlias::create(PTy->getElementType(), PTy->getAddressSpace(),
- SGA->getLinkage(), SGA->getName(), DstM);
-}
-
static void getArrayElements(const Constant *C,
SmallVectorImpl<Constant *> &Dest) {
unsigned NumElements = cast<ArrayType>(C->getType())->getNumElements();
@@ -1151,27 +1153,17 @@ void ModuleLinker::linkAppendingVarInit(
/// Update the initializers in the Dest module now that all globals that may be
/// referenced are in Dest.
-void ModuleLinker::linkGlobalInits() {
- // Loop over all of the globals in the src module, mapping them over as we go
- for (GlobalVariable &Src : SrcM->globals()) {
- // Only process initialized GV's or ones not already in dest.
- if (!Src.hasInitializer() || DoNotLinkFromSource.count(&Src))
- continue;
-
- // Grab destination global variable.
- GlobalVariable *Dst = cast<GlobalVariable>(ValueMap[&Src]);
- // Figure out what the initializer looks like in the dest module.
- Dst->setInitializer(MapValue(Src.getInitializer(), ValueMap, RF_None,
- &TypeMap, &ValMaterializer));
- }
+void ModuleLinker::linkGlobalInit(GlobalVariable &Dst, GlobalVariable &Src) {
+ // Figure out what the initializer looks like in the dest module.
+ Dst.setInitializer(MapValue(Src.getInitializer(), ValueMap, RF_None, &TypeMap,
+ &ValMaterializer));
}
/// Copy the source function over into the dest function and fix up references
/// to values. At this point we know that Dest is an external function, and
/// that Src is not.
-bool ModuleLinker::linkFunctionBody(Function &Src) {
- Function *Dst = cast<Function>(ValueMap[&Src]);
- assert(Dst && Dst->isDeclaration() && !Src.isDeclaration());
+bool ModuleLinker::linkFunctionBody(Function &Dst, Function &Src) {
+ assert(Dst.isDeclaration() && !Src.isDeclaration());
// Materialize if needed.
if (std::error_code EC = Src.materialize())
@@ -1179,17 +1171,16 @@ bool ModuleLinker::linkFunctionBody(Func
// Link in the prefix data.
if (Src.hasPrefixData())
- Dst->setPrefixData(MapValue(Src.getPrefixData(), ValueMap, RF_None,
- &TypeMap, &ValMaterializer));
+ Dst.setPrefixData(MapValue(Src.getPrefixData(), ValueMap, RF_None, &TypeMap,
+ &ValMaterializer));
// Link in the prologue data.
if (Src.hasPrologueData())
- Dst->setPrologueData(MapValue(Src.getPrologueData(), ValueMap, RF_None,
+ Dst.setPrologueData(MapValue(Src.getPrologueData(), ValueMap, RF_None,
&TypeMap, &ValMaterializer));
-
// Go through and convert function arguments over, remembering the mapping.
- Function::arg_iterator DI = Dst->arg_begin();
+ Function::arg_iterator DI = Dst.arg_begin();
for (Argument &Arg : Src.args()) {
DI->setName(Arg.getName()); // Copy the name over.
@@ -1199,13 +1190,13 @@ bool ModuleLinker::linkFunctionBody(Func
}
// Splice the body of the source function into the dest function.
- Dst->getBasicBlockList().splice(Dst->end(), Src.getBasicBlockList());
+ Dst.getBasicBlockList().splice(Dst.end(), Src.getBasicBlockList());
// At this point, all of the instructions and values of the function are now
// copied over. The only problem is that they are still referencing values in
// the Source function as operands. Loop through all of the operands of the
// functions and patch them up to point to the local versions.
- for (BasicBlock &BB : *Dst)
+ for (BasicBlock &BB : Dst)
for (Instruction &I : BB)
RemapInstruction(&I, ValueMap, RF_IgnoreMissingEntries, &TypeMap,
&ValMaterializer);
@@ -1218,18 +1209,24 @@ bool ModuleLinker::linkFunctionBody(Func
return false;
}
-/// Insert all of the aliases in Src into the Dest module.
-void ModuleLinker::linkAliasBodies() {
- for (GlobalAlias &Src : SrcM->aliases()) {
- if (DoNotLinkFromSource.count(&Src))
- continue;
- if (Constant *Aliasee = Src.getAliasee()) {
- GlobalAlias *DA = cast<GlobalAlias>(ValueMap[&Src]);
- Constant *Val =
- MapValue(Aliasee, ValueMap, RF_None, &TypeMap, &ValMaterializer);
- DA->setAliasee(Val);
- }
+void ModuleLinker::linkAliasBody(GlobalAlias &Dst, GlobalAlias &Src) {
+ Constant *Aliasee = Src.getAliasee();
+ Constant *Val =
+ MapValue(Aliasee, ValueMap, RF_None, &TypeMap, &ValMaterializer);
+ Dst.setAliasee(Val);
+}
+
+bool ModuleLinker::linkGlobalValueBody(GlobalValue &Src) {
+ Value *Dst = ValueMap[&Src];
+ assert(Dst);
+ if (auto *F = dyn_cast<Function>(&Src))
+ return linkFunctionBody(cast<Function>(*Dst), *F);
+ if (auto *GVar = dyn_cast<GlobalVariable>(&Src)) {
+ linkGlobalInit(cast<GlobalVariable>(*Dst), *GVar);
+ return false;
}
+ linkAliasBody(cast<GlobalAlias>(*Dst), cast<GlobalAlias>(Src));
+ return false;
}
/// Insert all of the named MDNodes in Src into the Dest module.
@@ -1502,12 +1499,16 @@ bool ModuleLinker::run() {
if (DoNotLinkFromSource.count(&SF))
continue;
- if (linkFunctionBody(SF))
+ if (linkGlobalValueBody(SF))
return true;
}
// Resolve all uses of aliases with aliasees.
- linkAliasBodies();
+ for (GlobalAlias &Src : SrcM->aliases()) {
+ if (DoNotLinkFromSource.count(&Src))
+ continue;
+ linkGlobalValueBody(Src);
+ }
// Remap all of the named MDNodes in Src into the DstM module. We do this
// after linking GlobalValues so that MDNodes that reference GlobalValues
@@ -1520,14 +1521,19 @@ bool ModuleLinker::run() {
// Update the initializers in the DstM module now that all globals that may
// be referenced are in DstM.
- linkGlobalInits();
+ for (GlobalVariable &Src : SrcM->globals()) {
+ // Only process initialized GV's or ones not already in dest.
+ if (!Src.hasInitializer() || DoNotLinkFromSource.count(&Src))
+ continue;
+ linkGlobalValueBody(Src);
+ }
// Process vector of lazily linked in functions.
- while (!LazilyLinkFunctions.empty()) {
- Function *SF = LazilyLinkFunctions.back();
- LazilyLinkFunctions.pop_back();
+ while (!LazilyLinkGlobalValues.empty()) {
+ GlobalValue *SGV = LazilyLinkGlobalValues.back();
+ LazilyLinkGlobalValues.pop_back();
- if (linkFunctionBody(*SF))
+ if (linkGlobalValueBody(*SGV))
return true;
}
Modified: llvm/trunk/test/LTO/cfi_endproc.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/LTO/cfi_endproc.ll?rev=223681&r1=223680&r2=223681&view=diff
==============================================================================
--- llvm/trunk/test/LTO/cfi_endproc.ll (original)
+++ llvm/trunk/test/LTO/cfi_endproc.ll Mon Dec 8 12:45:16 2014
@@ -35,3 +35,8 @@ define i32* @get_zed1() {
; ZED1_AND_ZED2: d zed2
@zed2 = linkonce_odr unnamed_addr global i32 42
+
+define i32 @useZed2() {
+ %x = load i32* @zed2
+ ret i32 %x
+}
Modified: llvm/trunk/test/LTO/linkonce_odr_func.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/LTO/linkonce_odr_func.ll?rev=223681&r1=223680&r2=223681&view=diff
==============================================================================
--- llvm/trunk/test/LTO/linkonce_odr_func.ll (original)
+++ llvm/trunk/test/LTO/linkonce_odr_func.ll Mon Dec 8 12:45:16 2014
@@ -29,9 +29,19 @@ define linkonce_odr void @foo4() noinlin
; CHECK: r v1
@v1 = linkonce_odr constant i32 32
+define i32 @useV1() {
+ %x = load i32* @v1
+ ret i32 %x
+}
+
; CHECK: V v2
@v2 = linkonce_odr global i32 32
+define i32 @useV2() {
+ %x = load i32* @v2
+ ret i32 %x
+}
+
declare void @f(void()*)
declare void @p()
Modified: llvm/trunk/test/Linker/Inputs/testlink.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Linker/Inputs/testlink.ll?rev=223681&r1=223680&r2=223681&view=diff
==============================================================================
--- llvm/trunk/test/Linker/Inputs/testlink.ll (original)
+++ llvm/trunk/test/Linker/Inputs/testlink.ll Mon Dec 8 12:45:16 2014
@@ -17,6 +17,8 @@
;; Intern in both testlink[12].ll
@Intern1 = internal constant i32 52
+ at Use2Intern1 = global i32* @Intern1
+
;; Intern in one but not in other
@Intern2 = constant i32 12345
Modified: llvm/trunk/test/Linker/lto-attributes.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Linker/lto-attributes.ll?rev=223681&r1=223680&r2=223681&view=diff
==============================================================================
--- llvm/trunk/test/Linker/lto-attributes.ll (original)
+++ llvm/trunk/test/Linker/lto-attributes.ll Mon Dec 8 12:45:16 2014
@@ -1,7 +1,10 @@
; RUN: llvm-link -S %s -o - | FileCheck %s
-; CHECK: @foo = private externally_initialized global i8* null
+; CHECK-DAG: @foo = private externally_initialized global i8* null
@foo = private externally_initialized global i8* null
-; CHECK: @array = appending global [7 x i8] c"abcdefg", align 1
+
+ at useFoo = global i8** @foo
+
+; CHECK-DAG: @array = appending global [7 x i8] c"abcdefg", align 1
@array = appending global [7 x i8] c"abcdefg", align 1
Added: llvm/trunk/test/Linker/pr21494.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Linker/pr21494.ll?rev=223681&view=auto
==============================================================================
--- llvm/trunk/test/Linker/pr21494.ll (added)
+++ llvm/trunk/test/Linker/pr21494.ll Mon Dec 8 12:45:16 2014
@@ -0,0 +1,23 @@
+; RUN: llvm-link %s -S -o - | FileCheck %s
+
+ at g1 = private global i8 0
+; CHECK-NOT: @g1
+
+ at g2 = linkonce_odr global i8 0
+; CHECK-NOT: @g2
+
+ at a1 = private alias i8* @g1
+; CHECK-NOT: @a1
+
+ at a2 = linkonce_odr alias i8* @g2
+; CHECK-NOT: @a2
+
+define private void @f1() {
+ ret void
+}
+; CHECK-NOT: @f1
+
+define linkonce_odr void @f2() {
+ ret void
+}
+; CHECK-NOT: @f2
Modified: llvm/trunk/test/Linker/testlink.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Linker/testlink.ll?rev=223681&r1=223680&r2=223681&view=diff
==============================================================================
--- llvm/trunk/test/Linker/testlink.ll (original)
+++ llvm/trunk/test/Linker/testlink.ll Mon Dec 8 12:45:16 2014
@@ -39,15 +39,20 @@
; CHECK-DAG: @Intern1 = internal constant i32 42
@Intern1 = internal constant i32 42
+ at UseIntern1 = global i32* @Intern1
+
; This should get renamed since there is a definition that is non-internal in
; the other module.
; CHECK-DAG: @Intern2{{[0-9]+}} = internal constant i32 792
@Intern2 = internal constant i32 792
+ at UseIntern2 = global i32* @Intern2
; CHECK-DAG: @MyVarPtr = linkonce global { i32* } { i32* @MyVar }
@MyVarPtr = linkonce global { i32* } { i32* @MyVar }
+ at UseMyVarPtr = global { i32* }* @MyVarPtr
+
; CHECK-DAG: @MyVar = global i32 4
@MyVar = external global i32
More information about the llvm-commits
mailing list