aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Krupcale <mkrupcale@matthewkrupcale.com>2020-08-09 09:45:15 -0400
committerMatthew Krupcale <mkrupcale@matthewkrupcale.com>2020-08-10 23:11:26 -0400
commitc55c3335c5e86777137c8dcca504af9c1d2cadf1 (patch)
treeefcfce351cc754034ba30201d2a3857cb8f6a050
parent1276a28b88295caf27c5df97d2e61b28feed3999 (diff)
Adjust linker arguments for LTO parallelization
GCC 10+ and Clang 4+ support controlling the number of LTO threads/jobs used during linking. Use the build2 scheduler to allocate up to the number of hardware threads to the GCC or Clang linker processes when -flto=auto or -flto=thin is specified, respectively. Otherwise, GCC or Clang will attempt to spawn the number of hardware threads detected for each linker process, which could result in up to n^2 linker threads on a CPU with n hardware threads.
-rw-r--r--libbuild2/cc/link-rule.cxx43
1 files changed, 43 insertions, 0 deletions
diff --git a/libbuild2/cc/link-rule.cxx b/libbuild2/cc/link-rule.cxx
index e94f538..fd5f284 100644
--- a/libbuild2/cc/link-rule.cxx
+++ b/libbuild2/cc/link-rule.cxx
@@ -6,6 +6,7 @@
#include <map>
#include <cstdlib> // exit()
#include <cstring> // strlen()
+#include <string> // to_string()
#include <libbutl/filesystem.mxx> // file_exists(), path_search()
@@ -2991,6 +2992,47 @@ namespace build2
try_rmfile (relt, true);
}
+ // Adjust args for LTO parallelization
+ scheduler::alloc_guard ag;
+ if (!lt.static_library ())
+ {
+ switch (ctype)
+ {
+ case compiler_type::gcc:
+ {
+ cstrings::reverse_iterator args_it;
+ if (cmaj >= 10 &&
+ (args_it = find_option ("-flto=auto", args.rbegin () + 1, args.rend ()))
+ != args.rend ())
+ {
+ ag = scheduler::alloc_guard (ctx.sched, 0);
+ arg1 = "-flto=" + std::to_string (1 + ag.n);
+ *args_it = arg1.c_str ();
+ }
+
+ break;
+ }
+ case compiler_type::clang:
+ {
+ if (cmaj >= 4 && find_option ("-flto=thin", args))
+ {
+ cstrings::reverse_iterator args_it;
+ if ((args_it = find_option_prefix ("-flto-jobs=", args.rbegin () + 1, args.rend ()))
+ == args.rend ())
+ {
+ ag = scheduler::alloc_guard (ctx.sched, 0);
+ arg1 = "-flto-jobs=" + std::to_string (1 + ag.n);
+ args.push_back (arg1.c_str ());
+ }
+ }
+ break;
+ }
+ case compiler_type::msvc:
+ case compiler_type::icc:
+ break;
+ }
+ }
+
if (verb == 1)
text << (lt.static_library () ? "ar " : "ld ") << t;
else if (verb == 2)
@@ -3162,6 +3204,7 @@ namespace build2
}
run_finish (args, pr);
+ ag.deallocate ();
}
catch (const process_error& e)
{