summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVlad Tsyrklevich <vlad@tsyrklevich.net>2018-01-10 00:00:51 +0000
committerVlad Tsyrklevich <vlad@tsyrklevich.net>2018-01-10 00:00:51 +0000
commitcdec22ef9a418c971752c0854ebdddf0018dc260 (patch)
treed72c94e5856559617f2cae75df337f0301e8f1e8
parent8d146bbc0cb3fcd00d036354da3fc00777450f0d (diff)
downloadbcm5719-llvm-cdec22ef9a418c971752c0854ebdddf0018dc260.tar.gz
bcm5719-llvm-cdec22ef9a418c971752c0854ebdddf0018dc260.zip
LowerTypeTests: Add limited support for aliases
Summary: LowerTypeTests moves some function definitions from individual object files to the merged module, leaving a stub to be called in the merged module's jump table. If an alias was pointing to such a function definition LowerTypeTests would fail because the alias would be left without a definition to point to. This change 1) emits information about aliases to the ThinLTO summary, 2) replaces aliases pointing to function definitions that are moved to the merged module with function declarations, and 3) re-emits those aliases in the merged module pointing to the correct function definitions. The patch does not correctly fix all possible mis-uses of aliases in LowerTypeTests. For example, it does not handle aliases with a different type from the pointed to function. The addition of alias data increases the size of Chrome build artifacts by less than 1%. Reviewers: pcc Reviewed By: pcc Subscribers: mehdi_amini, eraman, mgrang, llvm-commits, eugenis, kcc Differential Revision: https://reviews.llvm.org/D41741 llvm-svn: 322139
-rw-r--r--llvm/lib/Transforms/IPO/LowerTypeTests.cpp58
-rw-r--r--llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp25
-rw-r--r--llvm/test/Transforms/LowerTypeTests/Inputs/import-alias.yaml11
-rw-r--r--llvm/test/Transforms/LowerTypeTests/export-alias.ll21
-rw-r--r--llvm/test/Transforms/LowerTypeTests/import-alias.ll30
-rw-r--r--llvm/test/Transforms/ThinLTOBitcodeWriter/function-alias.ll25
6 files changed, 170 insertions, 0 deletions
diff --git a/llvm/lib/Transforms/IPO/LowerTypeTests.cpp b/llvm/lib/Transforms/IPO/LowerTypeTests.cpp
index 8db7e1e142d..20f54ef53f7 100644
--- a/llvm/lib/Transforms/IPO/LowerTypeTests.cpp
+++ b/llvm/lib/Transforms/IPO/LowerTypeTests.cpp
@@ -956,6 +956,21 @@ void LowerTypeTestsModule::importFunction(Function *F, bool isDefinition) {
FDecl = Function::Create(F->getFunctionType(), GlobalValue::ExternalLinkage,
Name, &M);
FDecl->setVisibility(Visibility);
+
+ // Delete aliases pointing to this function, they'll be re-created in the
+ // merged output
+ SmallVector<GlobalAlias*, 4> ToErase;
+ for (auto &U : F->uses()) {
+ if (auto *A = dyn_cast<GlobalAlias>(U.getUser())) {
+ Function *AliasDecl = Function::Create(
+ F->getFunctionType(), GlobalValue::ExternalLinkage, "", &M);
+ AliasDecl->takeName(A);
+ A->replaceAllUsesWith(AliasDecl);
+ ToErase.push_back(A);
+ }
+ }
+ for (auto *A : ToErase)
+ A->eraseFromParent();
} else {
// Function definition without type metadata, where some other translation
// unit contained a declaration with type metadata. This normally happens
@@ -1804,6 +1819,49 @@ bool LowerTypeTestsModule::lower() {
allocateByteArrays();
+ // Parse alias data to replace stand-in function declarations for aliases
+ // with an alias to the intended target.
+ if (ExportSummary) {
+ if (NamedMDNode *AliasesMD = M.getNamedMetadata("aliases")) {
+ for (auto AliasMD : AliasesMD->operands()) {
+ assert(AliasMD->getNumOperands() >= 4);
+ StringRef AliasName =
+ cast<MDString>(AliasMD->getOperand(0))->getString();
+ StringRef Aliasee = cast<MDString>(AliasMD->getOperand(1))->getString();
+
+ if (!ExportedFunctions.count(Aliasee) ||
+ ExportedFunctions[Aliasee].Linkage != CFL_Definition ||
+ !M.getNamedAlias(Aliasee))
+ continue;
+
+ GlobalValue::VisibilityTypes Visibility =
+ static_cast<GlobalValue::VisibilityTypes>(
+ cast<ConstantAsMetadata>(AliasMD->getOperand(2))
+ ->getValue()
+ ->getUniqueInteger()
+ .getZExtValue());
+ bool Weak =
+ static_cast<bool>(cast<ConstantAsMetadata>(AliasMD->getOperand(3))
+ ->getValue()
+ ->getUniqueInteger()
+ .getZExtValue());
+
+ auto *Alias = GlobalAlias::create("", M.getNamedAlias(Aliasee));
+ Alias->setVisibility(Visibility);
+ if (Weak)
+ Alias->setLinkage(GlobalValue::WeakAnyLinkage);
+
+ if (auto *F = M.getFunction(AliasName)) {
+ Alias->takeName(F);
+ F->replaceAllUsesWith(Alias);
+ F->eraseFromParent();
+ } else {
+ Alias->setName(AliasName);
+ }
+ }
+ }
+ }
+
return true;
}
diff --git a/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp b/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp
index caffc03339c..f5a3d4452c7 100644
--- a/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp
+++ b/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp
@@ -357,6 +357,31 @@ void splitAndWriteThinLTOBitcode(
NMD->addOperand(MD);
}
+ SmallVector<MDNode *, 8> FunctionAliases;
+ for (auto &A : M.aliases()) {
+ if (!isa<Function>(A.getAliasee()))
+ continue;
+
+ auto *F = cast<Function>(A.getAliasee());
+ auto &Ctx = MergedM->getContext();
+ SmallVector<Metadata *, 4> Elts;
+
+ Elts.push_back(MDString::get(Ctx, A.getName()));
+ Elts.push_back(MDString::get(Ctx, F->getName()));
+ Elts.push_back(ConstantAsMetadata::get(
+ llvm::ConstantInt::get(Type::getInt8Ty(Ctx), A.getVisibility())));
+ Elts.push_back(ConstantAsMetadata::get(
+ llvm::ConstantInt::get(Type::getInt8Ty(Ctx), A.isWeakForLinker())));
+
+ FunctionAliases.push_back(MDTuple::get(Ctx, Elts));
+ }
+
+ if (!FunctionAliases.empty()) {
+ NamedMDNode *NMD = MergedM->getOrInsertNamedMetadata("aliases");
+ for (auto MD : FunctionAliases)
+ NMD->addOperand(MD);
+ }
+
simplifyExternals(*MergedM);
// FIXME: Try to re-use BSI and PFI from the original module here.
diff --git a/llvm/test/Transforms/LowerTypeTests/Inputs/import-alias.yaml b/llvm/test/Transforms/LowerTypeTests/Inputs/import-alias.yaml
new file mode 100644
index 00000000000..a5943cb9fd6
--- /dev/null
+++ b/llvm/test/Transforms/LowerTypeTests/Inputs/import-alias.yaml
@@ -0,0 +1,11 @@
+---
+TypeIdMap:
+ typeid1:
+ TTRes:
+ Kind: AllOnes
+ SizeM1BitWidth: 7
+WithGlobalValueDeadStripping: false
+CfiFunctionDefs:
+ - f
+CfiFunctionDecls:
+...
diff --git a/llvm/test/Transforms/LowerTypeTests/export-alias.ll b/llvm/test/Transforms/LowerTypeTests/export-alias.ll
new file mode 100644
index 00000000000..6e9c074068d
--- /dev/null
+++ b/llvm/test/Transforms/LowerTypeTests/export-alias.ll
@@ -0,0 +1,21 @@
+; RUN: opt -S %s -lowertypetests -lowertypetests-summary-action=export -lowertypetests-read-summary=%S/Inputs/use-typeid1-typeid2.yaml | FileCheck %s
+;
+; CHECK: @alias1 = weak alias void (), void ()* @f
+; CHECK: @alias2 = hidden alias void (), void ()* @f
+; CHECK: declare !type !1 void @alias3()
+; CHECK-NOT: @alias3 = alias
+
+target triple = "x86_64-unknown-linux"
+
+!cfi.functions = !{!0, !2, !3}
+!aliases = !{!4, !5, !6}
+
+!0 = !{!"f", i8 0, !1}
+!1 = !{i64 0, !"typeid1"}
+!2 = !{!"alias1", i8 1, !1}
+; alias2 not included here, this could happen if the only reference to alias2
+; is in a module compiled without cfi-icall
+!3 = !{!"alias3", i8 1, !1}
+!4 = !{!"alias1", !"f", i8 0, i8 1}
+!5 = !{!"alias2", !"f", i8 1, i8 0}
+!6 = !{!"alias3", !"not_present", i8 0, i8 0}
diff --git a/llvm/test/Transforms/LowerTypeTests/import-alias.ll b/llvm/test/Transforms/LowerTypeTests/import-alias.ll
new file mode 100644
index 00000000000..e673da7484c
--- /dev/null
+++ b/llvm/test/Transforms/LowerTypeTests/import-alias.ll
@@ -0,0 +1,30 @@
+; RUN: opt -S %s -lowertypetests -lowertypetests-summary-action=import -lowertypetests-read-summary=%S/Inputs/import-alias.yaml | FileCheck %s
+;
+; Check that the definitions for @f and @f_alias are removed from this module
+; but @g_alias remains.
+;
+; CHECK: @g_alias = alias void (), void ()* @g
+; CHECK: define hidden void @f.cfi
+; CHECK: declare void @f()
+; CHECK: declare void @f_alias()
+
+target triple = "x86_64-unknown-linux"
+
+@f_alias = alias void (), void ()* @f
+@g_alias = alias void (), void ()* @g
+
+; Definition moved to the merged module
+define void @f() {
+ ret void
+}
+
+; Definition not moved to the merged module
+define void @g() {
+ ret void
+}
+
+define void @uses_aliases() {
+ call void @f_alias()
+ call void @g_alias()
+ ret void
+}
diff --git a/llvm/test/Transforms/ThinLTOBitcodeWriter/function-alias.ll b/llvm/test/Transforms/ThinLTOBitcodeWriter/function-alias.ll
new file mode 100644
index 00000000000..119b8219bab
--- /dev/null
+++ b/llvm/test/Transforms/ThinLTOBitcodeWriter/function-alias.ll
@@ -0,0 +1,25 @@
+; RUN: opt -thinlto-bc -o %t %s
+; RUN: llvm-modextract -n 1 -o - %t | llvm-dis | FileCheck --check-prefix=CHECK1 %s
+
+target triple = "x86_64-unknown-linux-gnu"
+
+define hidden void @Func() !type !0 {
+ ret void
+}
+
+; CHECK1: !aliases = !{![[A1:[0-9]+]], ![[A2:[0-9]+]], ![[A3:[0-9]+]]}
+
+; CHECK1: ![[A1]] = !{!"Alias", !"Func", i8 1, i8 0}
+; CHECK1: ![[A2]] = !{!"Hidden_Alias", !"Func", i8 1, i8 0}
+; CHECK1: ![[A3]] = !{!"Weak_Alias", !"Func", i8 0, i8 1}
+@Alias = hidden alias void (), void ()* @Func
+@Hidden_Alias = hidden alias void (), void ()* @Func
+@Weak_Alias = weak alias void (), void ()* @Func
+
+@Variable = global i32 0
+
+; Only generate summary alias information for aliases to functions
+; CHECK1-NOT: Variable_Alias
+@Variable_Alias = alias i32, i32* @Variable
+
+!0 = !{i64 0, !"_ZTSFvvE"}
OpenPOWER on IntegriCloud