diff --git a/llvm/include/llvm/IR/GlobalAlias.h b/llvm/include/llvm/IR/GlobalAlias.h index f2d9b9676ec96c..f2c56f6b68b797 100644 --- a/llvm/include/llvm/IR/GlobalAlias.h +++ b/llvm/include/llvm/IR/GlobalAlias.h @@ -77,6 +77,12 @@ class GlobalAlias : public GlobalIndirectSymbol, return getIndirectSymbol(); } + const GlobalObject *getBaseObject() const; + GlobalObject *getBaseObject() { + return const_cast( + static_cast(this)->getBaseObject()); + } + static bool isValidLinkage(LinkageTypes L) { return isExternalLinkage(L) || isLocalLinkage(L) || isWeakLinkage(L) || isLinkOnceLinkage(L); diff --git a/llvm/include/llvm/IR/GlobalIFunc.h b/llvm/include/llvm/IR/GlobalIFunc.h index ddd29c8a4a191d..39316937ac4ccc 100644 --- a/llvm/include/llvm/IR/GlobalIFunc.h +++ b/llvm/include/llvm/IR/GlobalIFunc.h @@ -57,11 +57,15 @@ class GlobalIFunc final : public GlobalIndirectSymbol, void setResolver(Constant *Resolver) { setIndirectSymbol(Resolver); } - const Constant *getResolver() const { - return getIndirectSymbol(); - } - Constant *getResolver() { - return getIndirectSymbol(); + const Constant *getResolver() const { return getIndirectSymbol(); } + Constant *getResolver() { return getIndirectSymbol(); } + + // Return the resolver function after peeling off potential ConstantExpr + // indirection. + const Function *getResolverFunction() const; + Function *getResolverFunction() { + return const_cast( + static_cast(this)->getResolverFunction()); } // Methods for support type inquiry through isa, cast, and dyn_cast: diff --git a/llvm/lib/IR/Globals.cpp b/llvm/lib/IR/Globals.cpp index b1c6dcc6672de3..a8dc0e2503964d 100644 --- a/llvm/lib/IR/Globals.cpp +++ b/llvm/lib/IR/Globals.cpp @@ -283,7 +283,7 @@ bool GlobalObject::canIncreaseAlignment() const { const GlobalObject *GlobalValue::getBaseObject() const { if (auto *GO = dyn_cast(this)) return GO; - if (auto *GA = dyn_cast(this)) + if (auto *GA = dyn_cast(this)) return GA->getBaseObject(); return nullptr; } @@ -464,11 +464,6 @@ findBaseObject(const Constant *C, DenseSet &Aliases) { return nullptr; } -const GlobalObject *GlobalIndirectSymbol::getBaseObject() const { - DenseSet Aliases; - return findBaseObject(getOperand(0), Aliases); -} - //===----------------------------------------------------------------------===// // GlobalAlias Implementation //===----------------------------------------------------------------------===// @@ -524,6 +519,11 @@ void GlobalAlias::setAliasee(Constant *Aliasee) { setIndirectSymbol(Aliasee); } +const GlobalObject *GlobalAlias::getBaseObject() const { + DenseSet Aliases; + return findBaseObject(getOperand(0), Aliases); +} + //===----------------------------------------------------------------------===// // GlobalIFunc Implementation //===----------------------------------------------------------------------===// @@ -550,3 +550,8 @@ void GlobalIFunc::removeFromParent() { void GlobalIFunc::eraseFromParent() { getParent()->getIFuncList().erase(getIterator()); } + +const Function *GlobalIFunc::getResolverFunction() const { + DenseSet Aliases; + return cast(findBaseObject(getIndirectSymbol(), Aliases)); +} diff --git a/llvm/lib/Object/IRSymtab.cpp b/llvm/lib/Object/IRSymtab.cpp index 746b008671573e..9208f9018f6e7b 100644 --- a/llvm/lib/Object/IRSymtab.cpp +++ b/llvm/lib/Object/IRSymtab.cpp @@ -284,9 +284,13 @@ Error Builder::addSymbol(const ModuleSymbolTable &Msymtab, } const GlobalObject *Base = GV->getBaseObject(); - if (!Base) - return make_error("Unable to determine comdat of alias!", - inconvertibleErrorCode()); + if (!Base) { + if (isa(GV)) + Base = cast(GV)->getResolverFunction(); + if (!Base) + return make_error("Unable to determine comdat of alias!", + inconvertibleErrorCode()); + } if (const Comdat *C = Base->getComdat()) { Expected ComdatIndexOrErr = getComdatIndex(C, GV->getParent()); if (!ComdatIndexOrErr) diff --git a/llvm/lib/Object/ModuleSymbolTable.cpp b/llvm/lib/Object/ModuleSymbolTable.cpp index 9a79de77af16db..5ae81c9505677d 100644 --- a/llvm/lib/Object/ModuleSymbolTable.cpp +++ b/llvm/lib/Object/ModuleSymbolTable.cpp @@ -204,7 +204,7 @@ uint32_t ModuleSymbolTable::getSymbolFlags(Symbol S) const { if (GVar->isConstant()) Res |= BasicSymbolRef::SF_Const; } - if (dyn_cast_or_null(GV->getBaseObject())) + if (isa_and_nonnull(GV->getBaseObject()) || isa(GV)) Res |= BasicSymbolRef::SF_Executable; if (isa(GV)) Res |= BasicSymbolRef::SF_Indirect; diff --git a/llvm/lib/Transforms/Utils/SplitModule.cpp b/llvm/lib/Transforms/Utils/SplitModule.cpp index 32f2f4e233b2b9..2fd3eed53b5e11 100644 --- a/llvm/lib/Transforms/Utils/SplitModule.cpp +++ b/llvm/lib/Transforms/Utils/SplitModule.cpp @@ -125,9 +125,11 @@ static void findPartitions(Module &M, ClusterIDMapType &ClusterIDMap, // For aliases we should not separate them from their aliasees regardless // of linkage. - if (auto *GIS = dyn_cast(&GV)) { + if (auto *GIS = dyn_cast(&GV)) { if (const GlobalObject *Base = GIS->getBaseObject()) GVtoClusterMap.unionSets(&GV, Base); + } else if (auto *GIS = dyn_cast(&GV)) { + GVtoClusterMap.unionSets(&GV, GIS->getResolverFunction()); } if (const Function *F = dyn_cast(&GV)) { @@ -225,9 +227,12 @@ static void externalize(GlobalValue *GV) { // Returns whether GV should be in partition (0-based) I of N. static bool isInPartition(const GlobalValue *GV, unsigned I, unsigned N) { - if (auto *GIS = dyn_cast(GV)) + if (auto *GIS = dyn_cast(GV)) { if (const GlobalObject *Base = GIS->getBaseObject()) GV = Base; + } else if (auto *GIS = dyn_cast(GV)) { + GV = GIS->getResolverFunction(); + } StringRef Name; if (const Comdat *C = GV->getComdat()) diff --git a/llvm/test/LTO/Resolution/X86/ifunc.ll b/llvm/test/LTO/Resolution/X86/ifunc.ll index 7192ea2d5f771a..afe7c8cd1e7e7d 100644 --- a/llvm/test/LTO/Resolution/X86/ifunc.ll +++ b/llvm/test/LTO/Resolution/X86/ifunc.ll @@ -1,15 +1,23 @@ ; RUN: opt -module-summary -o %t.bc %s -; RUN: llvm-lto2 run %t.bc -r %t.bc,foo,pl -o %t2 +; RUN: llvm-lto2 run %t.bc -r %t.bc,foo,pl -r %t.bc,strlen,pl -o %t2 ; RUN: llvm-nm %t2.1 | FileCheck %s ; CHECK: i foo -; CHECK: t foo_ifunc +; CHECK: t foo_resolver +; CHECK: i strlen +; CHECK: t strlen_resolver target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" -@foo = ifunc i32 (i32), i64 ()* @foo_ifunc +@foo = ifunc i32 (i32), i64 ()* @foo_resolver +@strlen = ifunc i64 (i8*), bitcast (i64 (i8*)* ()* @strlen_resolver to i64 (i8*)*) -define internal i64 @foo_ifunc() { +define internal i64 @foo_resolver() { entry: ret i64 0 } + +define internal i64 (i8*)* @strlen_resolver() { +entry: + ret i64 (i8*)* null +}