-
Notifications
You must be signed in to change notification settings - Fork 12.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add function merger to be run during LTO link with gold plugin #121343
base: main
Are you sure you want to change the base?
Conversation
Patch adds 'merge-functions' plugin option for this purpose.
@llvm/pr-subscribers-lto Author: None (eleviant) ChangesPatch adds 'merge-functions' plugin option for this purpose. Full diff: https://github.com/llvm/llvm-project/pull/121343.diff 3 Files Affected:
diff --git a/llvm/test/tools/gold/X86/Inputs/merge-functions-foo.ll b/llvm/test/tools/gold/X86/Inputs/merge-functions-foo.ll
new file mode 100644
index 00000000000000..f2bcff89868e14
--- /dev/null
+++ b/llvm/test/tools/gold/X86/Inputs/merge-functions-foo.ll
@@ -0,0 +1,25 @@
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-linux-gnu"
+
+@_g = dso_local global i32 0, align 4
+@llvm.compiler.used = appending global [1 x ptr] [ptr @_g], section "llvm.metadata"
+
+define dso_local i32 @foo(i32 noundef %0) #0 {
+ %2 = add nsw i32 %0, 42
+ store i32 %2, ptr @_g, align 4
+ ret i32 %2
+}
+
+attributes #0 = { noinline }
+
+!llvm.module.flags = !{!0, !1}
+
+!0 = !{i32 1, !"ThinLTO", i32 0}
+!1 = !{i32 1, !"EnableSplitLTOUnit", i32 1}
+
+^0 = module: (path: "/tmp/func2.o", hash: (0, 0, 0, 0, 0))
+^1 = gv: (name: "foo", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 1, live: 0, dsoLocal: 1, canAutoHide: 0), insts: 3, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 1, returnDoesNotAlias: 0, noInline: 1, alwaysInline: 0, noUnwind: 1, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0), refs: (^3)))) ; guid = 6699318081062747564
+^2 = gv: (name: "llvm.compiler.used", summaries: (variable: (module: ^0, flags: (linkage: appending, visibility: default, notEligibleToImport: 1, live: 1, dsoLocal: 0, canAutoHide: 0), varFlags: (readonly: 0, writeonly: 0, constant: 0), refs: (^3)))) ; guid = 9610627770985738006
+^3 = gv: (name: "_g", summaries: (variable: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 1, live: 0, dsoLocal: 1, canAutoHide: 0), varFlags: (readonly: 1, writeonly: 1, constant: 0)))) ; guid = 9713702464056781075
+^4 = flags: 8
+^5 = blockcount: 0
diff --git a/llvm/test/tools/gold/X86/merge-functions.ll b/llvm/test/tools/gold/X86/merge-functions.ll
new file mode 100644
index 00000000000000..d4a49b1c40b477
--- /dev/null
+++ b/llvm/test/tools/gold/X86/merge-functions.ll
@@ -0,0 +1,49 @@
+; RUN: llvm-as %s -o %t.bc
+; RUN: llvm-as %p/Inputs/merge-functions-foo.ll -o %t-foo.bc
+; RUN: %gold -plugin %llvmshlibdir/LLVMgold%shlibext \
+; RUN: -m elf_x86_64 \
+; RUN: -plugin-opt=merge-functions \
+; RUN: -plugin-opt=save-temps \
+; RUN: -u main \
+; RUN: %t.bc %t-foo.bc \
+; RUN: -o %t-out
+; RUN: llvm-dis %t-out.0.5.precodegen.bc -o - | FileCheck %s
+
+; Check that we've merged foo and bar
+; CHECK: define dso_local noundef i32 @main()
+; CHECK-NEXT: tail call fastcc void @bar()
+; CHECK-NEXT: tail call fastcc void @bar()
+
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-linux-gnu"
+
+@_g = external local_unnamed_addr global i32, align 4
+
+define dso_local i32 @bar(i32 noundef %0) #0 {
+ %2 = add nsw i32 %0, 42
+ store i32 %2, ptr @_g, align 4
+ ret i32 %2
+}
+
+define dso_local noundef i32 @main() {
+ %1 = tail call i32 @foo(i32 noundef 1)
+ %2 = tail call i32 @bar(i32 noundef 1)
+ ret i32 0
+}
+
+declare i32 @foo(i32 noundef) local_unnamed_addr #2
+
+attributes #0 = { noinline }
+
+!llvm.module.flags = !{!0, !1}
+
+!0 = !{i32 1, !"ThinLTO", i32 0}
+!1 = !{i32 1, !"EnableSplitLTOUnit", i32 1}
+
+^0 = module: (path: "merge-functions.o", hash: (0, 0, 0, 0, 0))
+^1 = gv: (name: "foo") ; guid = 6699318081062747564
+^2 = gv: (name: "_g") ; guid = 9713702464056781075
+^3 = gv: (name: "main", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 1, live: 0, dsoLocal: 1, canAutoHide: 0), insts: 3, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 1, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0), calls: ((callee: ^1, tail: 1), (callee: ^4, tail: 1))))) ; guid = 15822663052811949562
+^4 = gv: (name: "bar", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 1, live: 0, dsoLocal: 1, canAutoHide: 0), insts: 3, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 1, returnDoesNotAlias: 0, noInline: 1, alwaysInline: 0, noUnwind: 1, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0), refs: (^2)))) ; guid = 16434608426314478903
+^5 = flags: 8
+^6 = blockcount: 0
diff --git a/llvm/tools/gold/gold-plugin.cpp b/llvm/tools/gold/gold-plugin.cpp
index 6d0021c85f20fb..f6ca15a73115e0 100644
--- a/llvm/tools/gold/gold-plugin.cpp
+++ b/llvm/tools/gold/gold-plugin.cpp
@@ -222,6 +222,10 @@ namespace options {
static std::string cs_profile_path;
static bool cs_pgo_gen = false;
+ // When true, MergeFunctions pass is used
+ // in LTO link pipeline.
+ static bool merge_functions = false;
+
// Time trace options.
static std::string time_trace_file;
static unsigned time_trace_granularity = 500;
@@ -288,6 +292,8 @@ namespace options {
sample_profile = std::string(opt);
} else if (opt == "cs-profile-generate") {
cs_pgo_gen = true;
+ } else if (opt == "merge-functions") {
+ merge_functions = true;
} else if (opt.consume_front("cs-profile-path=")) {
cs_profile_path = std::string(opt);
} else if (opt == "new-pass-manager") {
@@ -893,6 +899,7 @@ static std::unique_ptr<LTO> createLTO(IndexWriteCallback OnIndexWrite,
Conf.OptLevel = options::OptLevel;
Conf.PTO.LoopVectorization = options::OptLevel > 1;
Conf.PTO.SLPVectorization = options::OptLevel > 1;
+ Conf.PTO.MergeFunctions = options::merge_functions;
Conf.AlwaysEmitRegularLTOObj = !options::obj_path.empty();
if (options::thinlto_index_only) {
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change looks ok to me. However, should this pass be enabled by default instead, maybe at least when optimizing for size? It's unfortunate to have to wire through options for individual passes like this. cc @aeubanks for thoughts since he has done some pass pipeline work.
@@ -222,6 +222,10 @@ namespace options { | |||
static std::string cs_profile_path; | |||
static bool cs_pgo_gen = false; | |||
|
|||
// When true, MergeFunctions pass is used |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: these 2 comment lines can be combined
My understanding is that this option should be passed by clang driver when both -flto and -fmerge-functions are enabled and otherwise should be set to false, because at the moment function merger is not being implicitly enabled by Os or any other optimization level. |
Patch adds 'merge-functions' plugin option for this purpose.