[Sync] Multi-version lto symbol parse and lto units ipa-inline extension
Add feature multi-version lto symbol parse and lto units ipa-inline extension
This commit is contained in:
parent
b334128bc9
commit
0c0de95dd2
6263
0303-Add-generation-of-stream-in-functions-for-pre-versio.patch
Normal file
6263
0303-Add-generation-of-stream-in-functions-for-pre-versio.patch
Normal file
File diff suppressed because it is too large
Load Diff
963
0304-Add-multi-version-lto-symbol-parse-cross-lto-units-i.patch
Normal file
963
0304-Add-multi-version-lto-symbol-parse-cross-lto-units-i.patch
Normal file
@ -0,0 +1,963 @@
|
|||||||
|
From f81a5b294711e3a420fe66702f0d9221332271c4 Mon Sep 17 00:00:00 2001
|
||||||
|
From: h00564365 <huangxiaoquan1@huawei.com>
|
||||||
|
Date: Wed, 13 Nov 2024 17:18:01 +0800
|
||||||
|
Subject: [PATCH 2/2] Add multi-version lto symbol parse, cross lto units
|
||||||
|
ipa-inline extension, and lto compression algorithm specified.
|
||||||
|
|
||||||
|
---
|
||||||
|
gcc/common.opt | 20 +++
|
||||||
|
gcc/config/aarch64/aarch64.cc | 41 ++++++
|
||||||
|
gcc/doc/tm.texi | 6 +
|
||||||
|
gcc/doc/tm.texi.in | 2 +
|
||||||
|
gcc/ipa-inline.cc | 141 ++++++++++++++++++-
|
||||||
|
gcc/lto-compress.cc | 6 +-
|
||||||
|
gcc/lto-section-in.cc | 5 +
|
||||||
|
gcc/lto-streamer-out.cc | 7 +-
|
||||||
|
gcc/lto-wrapper.cc | 4 +
|
||||||
|
gcc/optc-save-gen.awk | 57 ++++++++
|
||||||
|
gcc/opth-gen.awk | 3 +
|
||||||
|
gcc/opts.cc | 46 ++++++
|
||||||
|
gcc/target.def | 10 ++
|
||||||
|
gcc/testsuite/gcc.dg/lto/binary-inline-1_0.c | 15 ++
|
||||||
|
gcc/testsuite/gcc.dg/lto/binary-inline-1_1.c | 6 +
|
||||||
|
gcc/testsuite/gcc.dg/lto/binary-inline-2_0.c | 15 ++
|
||||||
|
gcc/testsuite/gcc.dg/lto/binary-inline-2_1.c | 5 +
|
||||||
|
gcc/testsuite/gcc.dg/lto/binary-inline-3_0.c | 15 ++
|
||||||
|
gcc/testsuite/gcc.dg/lto/binary-inline-3_1.c | 10 ++
|
||||||
|
gcc/tree-streamer-in.cc | 58 +++++++-
|
||||||
|
lto-plugin/lto-plugin.c | 83 +++++++++++
|
||||||
|
21 files changed, 547 insertions(+), 8 deletions(-)
|
||||||
|
create mode 100644 gcc/testsuite/gcc.dg/lto/binary-inline-1_0.c
|
||||||
|
create mode 100644 gcc/testsuite/gcc.dg/lto/binary-inline-1_1.c
|
||||||
|
create mode 100644 gcc/testsuite/gcc.dg/lto/binary-inline-2_0.c
|
||||||
|
create mode 100644 gcc/testsuite/gcc.dg/lto/binary-inline-2_1.c
|
||||||
|
create mode 100644 gcc/testsuite/gcc.dg/lto/binary-inline-3_0.c
|
||||||
|
create mode 100644 gcc/testsuite/gcc.dg/lto/binary-inline-3_1.c
|
||||||
|
|
||||||
|
diff --git a/gcc/common.opt b/gcc/common.opt
|
||||||
|
index be5fcc681..78cfc333a 100644
|
||||||
|
--- a/gcc/common.opt
|
||||||
|
+++ b/gcc/common.opt
|
||||||
|
@@ -1928,6 +1928,21 @@ finline-atomics
|
||||||
|
Common Var(flag_inline_atomics) Init(1) Optimization
|
||||||
|
Inline __atomic operations when a lock free instruction sequence is available.
|
||||||
|
|
||||||
|
+fmulti-version-lib=
|
||||||
|
+Common Joined Var(multi_version_lib_string)
|
||||||
|
+Use specify LTO stream in mode for specified target (object or lib). If there
|
||||||
|
+are multiple target files, use commas (,) to separate them and without spaces.
|
||||||
|
+
|
||||||
|
+finline-force
|
||||||
|
+Common Var(flag_inline_force) Init(0) Optimization
|
||||||
|
+Force perform ipa inline when march options are incompatible between functions.
|
||||||
|
+
|
||||||
|
+finline-force=
|
||||||
|
+Common Joined Var(force_inline_targets_string)
|
||||||
|
+Force perform ipa inline specified target(object or lib) when march options are
|
||||||
|
+incompatible between functions. If there are multiple target files, use commas
|
||||||
|
+(,) to separate them and without spaces.
|
||||||
|
+
|
||||||
|
fcf-protection
|
||||||
|
Common RejectNegative Alias(fcf-protection=,full)
|
||||||
|
|
||||||
|
@@ -2168,6 +2183,11 @@ flto-partition=
|
||||||
|
Common Joined RejectNegative Enum(lto_partition_model) Var(flag_lto_partition) Init(LTO_PARTITION_BALANCED)
|
||||||
|
Specify the algorithm to partition symbols and vars at linktime.
|
||||||
|
|
||||||
|
+flto-compression-algorithm=
|
||||||
|
+Common Joined Var(lto_compression_algorithm)
|
||||||
|
+-flto-compression-algorithm=<format> Generate lto compression in zlib/zstd
|
||||||
|
+format <format>.
|
||||||
|
+
|
||||||
|
; The initial value of -1 comes from Z_DEFAULT_COMPRESSION in zlib.h.
|
||||||
|
flto-compression-level=
|
||||||
|
Common Joined RejectNegative UInteger Var(flag_lto_compression_level) Init(-1) IntegerRange(0, 19)
|
||||||
|
diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
|
||||||
|
index 025a3c478..f095f17aa 100644
|
||||||
|
--- a/gcc/config/aarch64/aarch64.cc
|
||||||
|
+++ b/gcc/config/aarch64/aarch64.cc
|
||||||
|
@@ -20829,6 +20829,44 @@ aarch64_option_print (FILE *file, int indent, struct cl_target_option *ptr)
|
||||||
|
arch->name, extension.c_str ());
|
||||||
|
}
|
||||||
|
|
||||||
|
+/* Implement TARGET_OPTION_PRINT_DIFF. */
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+aarch64_option_print_diff (FILE *file, int indent,
|
||||||
|
+ struct cl_target_option *ptr1,
|
||||||
|
+ struct cl_target_option *ptr2)
|
||||||
|
+{
|
||||||
|
+ const char *const cpu1
|
||||||
|
+ = aarch64_get_tune_cpu (ptr1->x_selected_tune)->name;
|
||||||
|
+ const struct processor *arch1 = aarch64_get_arch (ptr1->x_selected_arch);
|
||||||
|
+ std::string extension1
|
||||||
|
+ = aarch64_get_extension_string_for_isa_flags (ptr1->x_aarch64_isa_flags,
|
||||||
|
+ arch1->flags);
|
||||||
|
+
|
||||||
|
+ const char *const cpu2
|
||||||
|
+ = aarch64_get_tune_cpu (ptr2->x_selected_tune)->name;
|
||||||
|
+ const struct processor *arch2 = aarch64_get_arch (ptr2->x_selected_arch);
|
||||||
|
+ std::string extension2
|
||||||
|
+ = aarch64_get_extension_string_for_isa_flags (ptr2->x_aarch64_isa_flags,
|
||||||
|
+ arch2->flags);
|
||||||
|
+
|
||||||
|
+ if (cpu1 != cpu2 && (!cpu1 || !cpu2 || strcmp (cpu1, cpu2)))
|
||||||
|
+ fprintf (file, "%*s%s (%s/%s)\n", indent, "",
|
||||||
|
+ "cpu", cpu1 ? cpu1 : "(null)", cpu2 ? cpu2 : "(null)");
|
||||||
|
+
|
||||||
|
+ if (arch1->name != arch2->name
|
||||||
|
+ && (!arch1->name || !arch2->name || strcmp (arch1->name, arch2->name)))
|
||||||
|
+ fprintf (file, "%*s%s (%s/%s)\n", indent, "",
|
||||||
|
+ "arch", arch1->name ? arch1->name : "(null)",
|
||||||
|
+ arch2->name ? arch2->name : "(null)");
|
||||||
|
+
|
||||||
|
+ if (extension1 != extension2)
|
||||||
|
+ fprintf (file, "%*s%s (%s/%s)\n", indent, "",
|
||||||
|
+ "extension",
|
||||||
|
+ extension1.empty () ? "(null)" : extension1.c_str (),
|
||||||
|
+ extension2.empty () ? "(null)" : extension2.c_str ());
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static GTY(()) tree aarch64_previous_fndecl;
|
||||||
|
|
||||||
|
void
|
||||||
|
@@ -31161,6 +31199,9 @@ aarch64_libgcc_floating_mode_supported_p
|
||||||
|
#undef TARGET_OPTION_PRINT
|
||||||
|
#define TARGET_OPTION_PRINT aarch64_option_print
|
||||||
|
|
||||||
|
+#undef TARGET_OPTION_PRINT_DIFF
|
||||||
|
+#define TARGET_OPTION_PRINT_DIFF aarch64_option_print_diff
|
||||||
|
+
|
||||||
|
#undef TARGET_OPTION_VALID_ATTRIBUTE_P
|
||||||
|
#define TARGET_OPTION_VALID_ATTRIBUTE_P aarch64_option_valid_attribute_p
|
||||||
|
|
||||||
|
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
|
||||||
|
index 1e96521e6..50bbbbc42 100644
|
||||||
|
--- a/gcc/doc/tm.texi
|
||||||
|
+++ b/gcc/doc/tm.texi
|
||||||
|
@@ -10589,6 +10589,12 @@ information in the @code{struct cl_target_option} structure for
|
||||||
|
function-specific options.
|
||||||
|
@end deftypefn
|
||||||
|
|
||||||
|
+@deftypefn {Target Hook} void TARGET_OPTION_PRINT_DIFF (FILE *@var{file}, int @var{indent}, struct cl_target_option *@var{ptr1}, struct cl_target_option *@var{ptr2})
|
||||||
|
+This hook is called to print diff additional target-specific
|
||||||
|
+information in the ptr1 and ptr2 @code{struct cl_target_option} structure for
|
||||||
|
+function-specific options.
|
||||||
|
+@end deftypefn
|
||||||
|
+
|
||||||
|
@deftypefn {Target Hook} bool TARGET_OPTION_PRAGMA_PARSE (tree @var{args}, tree @var{pop_target})
|
||||||
|
This target hook parses the options for @code{#pragma GCC target}, which
|
||||||
|
sets the target-specific options for functions that occur later in the
|
||||||
|
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
|
||||||
|
index 2dd515659..cfda60304 100644
|
||||||
|
--- a/gcc/doc/tm.texi.in
|
||||||
|
+++ b/gcc/doc/tm.texi.in
|
||||||
|
@@ -6985,6 +6985,8 @@ on this implementation detail.
|
||||||
|
|
||||||
|
@hook TARGET_OPTION_PRINT
|
||||||
|
|
||||||
|
+@hook TARGET_OPTION_PRINT_DIFF
|
||||||
|
+
|
||||||
|
@hook TARGET_OPTION_PRAGMA_PARSE
|
||||||
|
|
||||||
|
@hook TARGET_OPTION_OVERRIDE
|
||||||
|
diff --git a/gcc/ipa-inline.cc b/gcc/ipa-inline.cc
|
||||||
|
index f8bb072c4..8d5cc9a84 100644
|
||||||
|
--- a/gcc/ipa-inline.cc
|
||||||
|
+++ b/gcc/ipa-inline.cc
|
||||||
|
@@ -90,6 +90,8 @@ along with GCC; see the file COPYING3. If not see
|
||||||
|
the need for offline copy of the function. */
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
+#define INCLUDE_SET
|
||||||
|
+#define INCLUDE_STRING
|
||||||
|
#include "system.h"
|
||||||
|
#include "coretypes.h"
|
||||||
|
#include "backend.h"
|
||||||
|
@@ -127,6 +129,7 @@ typedef fibonacci_node <sreal, cgraph_edge> edge_heap_node_t;
|
||||||
|
static int overall_size;
|
||||||
|
static profile_count max_count;
|
||||||
|
static profile_count spec_rem;
|
||||||
|
+static std::set<std::string> force_inline_targets;
|
||||||
|
|
||||||
|
/* Return false when inlining edge E would lead to violating
|
||||||
|
limits on function unit growth or stack usage growth.
|
||||||
|
@@ -222,6 +225,38 @@ caller_growth_limits (struct cgraph_edge *e)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
+/* Warn and prompt the user, and output only once for the file pair where
|
||||||
|
+ the function is located. */
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+prompt_inline_failed_target_option_reason (struct cgraph_edge *e)
|
||||||
|
+{
|
||||||
|
+ static std::set<std::pair<void*, void*>> address_pair_set;
|
||||||
|
+ if (e->inline_failed == CIF_TARGET_OPTION_MISMATCH
|
||||||
|
+ && !cl_target_option_eq_major (target_opts_for_fn (e->caller->decl),
|
||||||
|
+ target_opts_for_fn (e->callee->ultimate_alias_target ()->decl))
|
||||||
|
+ && e->caller->lto_file_data
|
||||||
|
+ && e->callee->ultimate_alias_target ()->lto_file_data)
|
||||||
|
+ {
|
||||||
|
+ std::pair<void*, void*> addr_pair
|
||||||
|
+ = std::make_pair (&e->caller->lto_file_data,
|
||||||
|
+ &e->callee->ultimate_alias_target ()->lto_file_data);
|
||||||
|
+ if (address_pair_set.find (addr_pair) != address_pair_set.end ())
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ address_pair_set.insert (addr_pair);
|
||||||
|
+ warning (0, "LTO objects caller in: %s, callee in: %s, not inlinable: %s."
|
||||||
|
+ " Try to use -finline-force=callee_object_or_lib_name to force "
|
||||||
|
+ "inline", e->caller->lto_file_data->file_name,
|
||||||
|
+ e->callee->ultimate_alias_target ()->lto_file_data->file_name,
|
||||||
|
+ cgraph_inline_failed_string (CIF_TARGET_OPTION_MISMATCH));
|
||||||
|
+
|
||||||
|
+ cl_target_option_print_diff
|
||||||
|
+ (stderr, 2, target_opts_for_fn (e->caller->decl),
|
||||||
|
+ target_opts_for_fn (e->callee->ultimate_alias_target ()->decl));
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/* Dump info about why inlining has failed. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
@@ -254,6 +289,8 @@ report_inline_failed_reason (struct cgraph_edge *e)
|
||||||
|
(dump_file, 2, opts_for_fn (e->caller->decl),
|
||||||
|
opts_for_fn (e->callee->ultimate_alias_target ()->decl));
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ prompt_inline_failed_target_option_reason (e);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Decide whether sanitizer-related attributes allow inlining. */
|
||||||
|
@@ -310,6 +347,77 @@ sanitize_attrs_match_for_inline_p (const_tree caller, const_tree callee)
|
||||||
|
(opts_for_fn (caller->decl)->x_##flag \
|
||||||
|
!= opts_for_fn (callee->decl)->x_##flag)
|
||||||
|
|
||||||
|
+/* find related node that has lto_file_data. */
|
||||||
|
+
|
||||||
|
+static cgraph_node *
|
||||||
|
+find_related_node_lto_file_data (cgraph_node *node)
|
||||||
|
+{
|
||||||
|
+ cgraph_node *cur = node;
|
||||||
|
+
|
||||||
|
+ while (cur->clone_of)
|
||||||
|
+ {
|
||||||
|
+ /* Switch to original node, for example xxx.constprop.x function. */
|
||||||
|
+ cur = cur->clone_of;
|
||||||
|
+ if (cur->lto_file_data)
|
||||||
|
+ return cur;
|
||||||
|
+
|
||||||
|
+ /* Find the lto_file_data information of referring. */
|
||||||
|
+ struct ipa_ref *ref = NULL;
|
||||||
|
+ for (int i = 0; cur->iterate_referring (i, ref); i++)
|
||||||
|
+ {
|
||||||
|
+ struct cgraph_node *cnode = dyn_cast <cgraph_node *> (ref->referring);
|
||||||
|
+ if (cnode && cnode->lto_file_data)
|
||||||
|
+ return cnode;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return NULL;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Determines whether to force inline or force inline only the specified
|
||||||
|
+ object. Use for 3 inline extensions:
|
||||||
|
+ 1) CIF_TARGET_OPTION_MISMATCH: cancel the restriction that the target options
|
||||||
|
+ of different compilation units are different.
|
||||||
|
+ 2) CIF_OVERWRITABLE: indicates that the function is available, which is
|
||||||
|
+ similar to the "inline" keyword indication.
|
||||||
|
+ 3) CIF_OPTIMIZATION_MISMATCH: cancel the check in the case of fp_expressions,
|
||||||
|
+ which is similar to the "always_inline" attribute.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+static bool
|
||||||
|
+can_force_inline_p (cgraph_node *callee)
|
||||||
|
+{
|
||||||
|
+ if (!in_lto_p)
|
||||||
|
+ return false;
|
||||||
|
+ if (flag_inline_force)
|
||||||
|
+ return true;
|
||||||
|
+ if (force_inline_targets_string)
|
||||||
|
+ {
|
||||||
|
+ cgraph_node * node = callee;
|
||||||
|
+ std::string name = "";
|
||||||
|
+ if (callee->ultimate_alias_target () == NULL
|
||||||
|
+ || callee->ultimate_alias_target ()->lto_file_data == NULL)
|
||||||
|
+ {
|
||||||
|
+ node = find_related_node_lto_file_data (callee);
|
||||||
|
+ if (node && node->lto_file_data)
|
||||||
|
+ name = node->lto_file_data->file_name;
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ name = node->ultimate_alias_target ()->lto_file_data->file_name;
|
||||||
|
+ while (!name.empty () && name.back () == '/')
|
||||||
|
+ name.erase (name.length () - 1);
|
||||||
|
+ if (name.empty ())
|
||||||
|
+ return false;
|
||||||
|
+ size_t last_slash_pos = name.find_last_of ('/');
|
||||||
|
+ if (last_slash_pos != std::string::npos
|
||||||
|
+ && last_slash_pos != name.length () - 1)
|
||||||
|
+ name = name.substr (last_slash_pos + 1);
|
||||||
|
+ if (force_inline_targets.find (name) != force_inline_targets.end ())
|
||||||
|
+ return true;
|
||||||
|
+ }
|
||||||
|
+ return false;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/* Decide if we can inline the edge and possibly update
|
||||||
|
inline_failed reason.
|
||||||
|
We check whether inlining is possible at all and whether
|
||||||
|
@@ -352,7 +460,7 @@ can_inline_edge_p (struct cgraph_edge *e, bool report,
|
||||||
|
e->inline_failed = CIF_USES_COMDAT_LOCAL;
|
||||||
|
inlinable = false;
|
||||||
|
}
|
||||||
|
- else if (avail <= AVAIL_INTERPOSABLE)
|
||||||
|
+ else if (avail <= AVAIL_INTERPOSABLE && !can_force_inline_p (callee))
|
||||||
|
{
|
||||||
|
e->inline_failed = CIF_OVERWRITABLE;
|
||||||
|
inlinable = false;
|
||||||
|
@@ -378,8 +486,8 @@ can_inline_edge_p (struct cgraph_edge *e, bool report,
|
||||||
|
inlinable = false;
|
||||||
|
}
|
||||||
|
/* Check compatibility of target optimization options. */
|
||||||
|
- else if (!targetm.target_option.can_inline_p (caller->decl,
|
||||||
|
- callee->decl))
|
||||||
|
+ else if (!can_force_inline_p (callee)
|
||||||
|
+ && !targetm.target_option.can_inline_p (caller->decl, callee->decl))
|
||||||
|
{
|
||||||
|
e->inline_failed = CIF_TARGET_OPTION_MISMATCH;
|
||||||
|
inlinable = false;
|
||||||
|
@@ -495,7 +603,8 @@ can_inline_edge_by_limits_p (struct cgraph_edge *e, bool report,
|
||||||
|
bool always_inline =
|
||||||
|
(DECL_DISREGARD_INLINE_LIMITS (callee->decl)
|
||||||
|
&& lookup_attribute ("always_inline",
|
||||||
|
- DECL_ATTRIBUTES (callee->decl)));
|
||||||
|
+ DECL_ATTRIBUTES (callee->decl)))
|
||||||
|
+ || can_force_inline_p (callee);
|
||||||
|
ipa_fn_summary *caller_info = ipa_fn_summaries->get (caller);
|
||||||
|
ipa_fn_summary *callee_info = ipa_fn_summaries->get (callee);
|
||||||
|
|
||||||
|
@@ -2652,6 +2761,27 @@ flatten_remove_node_hook (struct cgraph_node *node, void *data)
|
||||||
|
removed->add (node);
|
||||||
|
}
|
||||||
|
|
||||||
|
+/* Parse string that specify forced inlining, separated by commas. */
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+parse_force_inline_targets_string (const char* s)
|
||||||
|
+{
|
||||||
|
+ std::string target_string (s);
|
||||||
|
+ std::string delim = ",";
|
||||||
|
+ size_t start = 0;
|
||||||
|
+ size_t end = target_string.find (delim);
|
||||||
|
+ if (target_string.substr (start, end - start) == "")
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ while (end != std::string::npos)
|
||||||
|
+ {
|
||||||
|
+ force_inline_targets.insert (target_string.substr (start, end - start));
|
||||||
|
+ start = end + delim.size ();
|
||||||
|
+ end = target_string.find (delim, start);
|
||||||
|
+ }
|
||||||
|
+ force_inline_targets.insert (target_string.substr (start, end - start));
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/* Decide on the inlining. We do so in the topological order to avoid
|
||||||
|
expenses on updating data structures. */
|
||||||
|
|
||||||
|
@@ -2665,6 +2795,9 @@ ipa_inline (void)
|
||||||
|
int cold;
|
||||||
|
bool remove_functions = false;
|
||||||
|
|
||||||
|
+ if (force_inline_targets_string)
|
||||||
|
+ parse_force_inline_targets_string (force_inline_targets_string);
|
||||||
|
+
|
||||||
|
order = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count);
|
||||||
|
|
||||||
|
if (dump_file)
|
||||||
|
diff --git a/gcc/lto-compress.cc b/gcc/lto-compress.cc
|
||||||
|
index 27f0992a8..f9d0722a9 100644
|
||||||
|
--- a/gcc/lto-compress.cc
|
||||||
|
+++ b/gcc/lto-compress.cc
|
||||||
|
@@ -305,7 +305,11 @@ void
|
||||||
|
lto_end_compression (struct lto_compression_stream *stream)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_ZSTD_H
|
||||||
|
- lto_compression_zstd (stream);
|
||||||
|
+ if (lto_compression_algorithm
|
||||||
|
+ && strcmp (lto_compression_algorithm, "zstd") == 0)
|
||||||
|
+ lto_compression_zstd (stream);
|
||||||
|
+ else
|
||||||
|
+ lto_compression_zlib (stream);
|
||||||
|
#else
|
||||||
|
lto_compression_zlib (stream);
|
||||||
|
#endif
|
||||||
|
diff --git a/gcc/lto-section-in.cc b/gcc/lto-section-in.cc
|
||||||
|
index ba87c7276..947f8eb15 100644
|
||||||
|
--- a/gcc/lto-section-in.cc
|
||||||
|
+++ b/gcc/lto-section-in.cc
|
||||||
|
@@ -448,6 +448,11 @@ lto_free_function_in_decl_state_for_node (symtab_node *node)
|
||||||
|
lto_free_function_in_decl_state (*slot);
|
||||||
|
node->lto_file_data->function_decl_states->clear_slot (slot);
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ /* In force inline case, keep lto file path information. */
|
||||||
|
+ if (in_lto_p && (flag_inline_force || force_inline_targets_string))
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
node->lto_file_data = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/gcc/lto-streamer-out.cc b/gcc/lto-streamer-out.cc
|
||||||
|
index 471f35c31..a574f0f1e 100644
|
||||||
|
--- a/gcc/lto-streamer-out.cc
|
||||||
|
+++ b/gcc/lto-streamer-out.cc
|
||||||
|
@@ -2666,7 +2666,12 @@ produce_lto_section ()
|
||||||
|
free (section_name);
|
||||||
|
|
||||||
|
#ifdef HAVE_ZSTD_H
|
||||||
|
- lto_compression compression = ZSTD;
|
||||||
|
+ lto_compression compression = ZLIB;
|
||||||
|
+ if (lto_compression_algorithm
|
||||||
|
+ && strcmp (lto_compression_algorithm, "zstd") == 0)
|
||||||
|
+ compression = ZSTD;
|
||||||
|
+ else
|
||||||
|
+ compression = ZLIB;
|
||||||
|
#else
|
||||||
|
lto_compression compression = ZLIB;
|
||||||
|
#endif
|
||||||
|
diff --git a/gcc/lto-wrapper.cc b/gcc/lto-wrapper.cc
|
||||||
|
index 155ccce57..2b1994652 100644
|
||||||
|
--- a/gcc/lto-wrapper.cc
|
||||||
|
+++ b/gcc/lto-wrapper.cc
|
||||||
|
@@ -491,6 +491,8 @@ merge_and_complain (vec<cl_decoded_option> &decoded_options,
|
||||||
|
|| decoded_options[j].opt_index == OPT_fpic)
|
||||||
|
{
|
||||||
|
/* -fno-pic in one unit implies -fno-pic everywhere. */
|
||||||
|
+ /* The -fno-pic adjustment here should provide some information hints,
|
||||||
|
+ but may affect the use case test of deja. */
|
||||||
|
if (decoded_options[j].value == 0)
|
||||||
|
j++;
|
||||||
|
/* If we have no pic option or merge in -fno-pic, we still may turn
|
||||||
|
@@ -534,6 +536,8 @@ merge_and_complain (vec<cl_decoded_option> &decoded_options,
|
||||||
|
|| decoded_options[j].opt_index == OPT_fpie)
|
||||||
|
{
|
||||||
|
/* -fno-pie in one unit implies -fno-pie everywhere. */
|
||||||
|
+ /* The -fno-pie adjustment here should provide some information hints,
|
||||||
|
+ but may affect the use case test of deja. */
|
||||||
|
if (decoded_options[j].value == 0)
|
||||||
|
j++;
|
||||||
|
/* If we have no pie option or merge in -fno-pie, we still preserve
|
||||||
|
diff --git a/gcc/optc-save-gen.awk b/gcc/optc-save-gen.awk
|
||||||
|
index 7c012dd4e..94b85b331 100644
|
||||||
|
--- a/gcc/optc-save-gen.awk
|
||||||
|
+++ b/gcc/optc-save-gen.awk
|
||||||
|
@@ -1043,6 +1043,10 @@ for (i = 0; i < n_target_string; i++) {
|
||||||
|
print "";
|
||||||
|
}
|
||||||
|
|
||||||
|
+print "";
|
||||||
|
+print " if (targetm.target_option.print_diff)";
|
||||||
|
+print " targetm.target_option.print_diff (file, indent, ptr1, ptr2);";
|
||||||
|
+
|
||||||
|
print "}";
|
||||||
|
|
||||||
|
print "";
|
||||||
|
@@ -1160,6 +1164,59 @@ print " return true;";
|
||||||
|
|
||||||
|
print "}";
|
||||||
|
|
||||||
|
+print "";
|
||||||
|
+print "/* Compare two target major options. */";
|
||||||
|
+print "bool";
|
||||||
|
+print "cl_target_option_eq_major (struct cl_target_option const *ptr1 ATTRIBUTE_UNUSED,";
|
||||||
|
+print " struct cl_target_option const *ptr2 ATTRIBUTE_UNUSED)";
|
||||||
|
+print "{";
|
||||||
|
+n_target_val_major = 0;
|
||||||
|
+
|
||||||
|
+for (i = 0; i < n_target_save; i++) {
|
||||||
|
+ var = target_save_decl[i];
|
||||||
|
+ sub (" *=.*", "", var);
|
||||||
|
+ name = var;
|
||||||
|
+ type = var;
|
||||||
|
+ sub("^.*[ *]", "", name)
|
||||||
|
+ sub(" *" name "$", "", type)
|
||||||
|
+ if (target_save_decl[i] ~ "^const char \\*+[_" alnum "]+$")
|
||||||
|
+ continue;
|
||||||
|
+ if (target_save_decl[i] ~ " .*\\[.+\\]+$")
|
||||||
|
+ continue;
|
||||||
|
+
|
||||||
|
+ var_target_val_major[n_target_val_major++] = name;
|
||||||
|
+}
|
||||||
|
+if (have_save) {
|
||||||
|
+ for (i = 0; i < n_opts; i++) {
|
||||||
|
+ if (flag_set_p("Save", flags[i])) {
|
||||||
|
+ name = var_name(flags[i])
|
||||||
|
+ if(name == "")
|
||||||
|
+ name = "target_flags";
|
||||||
|
+
|
||||||
|
+ if(name in var_list_seen)
|
||||||
|
+ continue;
|
||||||
|
+
|
||||||
|
+ var_list_seen[name]++;
|
||||||
|
+ otype = var_type_struct(flags[i])
|
||||||
|
+ if (otype ~ "^const char \\**$")
|
||||||
|
+ continue;
|
||||||
|
+ var_target_val_major[n_target_val_major++] = "x_" name;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+} else {
|
||||||
|
+ var_target_val_major[n_target_val_major++] = "x_target_flags";
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+for (i = 0; i < n_target_val_major; i++) {
|
||||||
|
+ name = var_target_val_major[i]
|
||||||
|
+ print " if (ptr1->" name" != ptr2->" name ")";
|
||||||
|
+ print " return false;";
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+print " return true;";
|
||||||
|
+
|
||||||
|
+print "}";
|
||||||
|
+
|
||||||
|
print "";
|
||||||
|
print "/* Hash target options */";
|
||||||
|
print "hashval_t";
|
||||||
|
diff --git a/gcc/opth-gen.awk b/gcc/opth-gen.awk
|
||||||
|
index 8bba8ec45..cb016e85d 100644
|
||||||
|
--- a/gcc/opth-gen.awk
|
||||||
|
+++ b/gcc/opth-gen.awk
|
||||||
|
@@ -330,6 +330,9 @@ print "";
|
||||||
|
print "/* Compare two target option variables from a structure. */";
|
||||||
|
print "extern bool cl_target_option_eq (const struct cl_target_option *, const struct cl_target_option *);";
|
||||||
|
print "";
|
||||||
|
+print "/* Compare two target major option variables from a structure. */";
|
||||||
|
+print "extern bool cl_target_option_eq_major (const struct cl_target_option *, const struct cl_target_option *);";
|
||||||
|
+print "";
|
||||||
|
print "/* Free heap memory used by target option variables. */";
|
||||||
|
print "extern void cl_target_option_free (struct cl_target_option *);";
|
||||||
|
print "";
|
||||||
|
diff --git a/gcc/opts.cc b/gcc/opts.cc
|
||||||
|
index d97f6079f..d9de8747c 100644
|
||||||
|
--- a/gcc/opts.cc
|
||||||
|
+++ b/gcc/opts.cc
|
||||||
|
@@ -2611,6 +2611,32 @@ print_help (struct gcc_options *opts, unsigned int lang_mask,
|
||||||
|
lang_mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
+/* Checks whether the input forced inline string complies with the
|
||||||
|
+ restriction. */
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+check_force_inline_targets_string (const char *arg, location_t loc)
|
||||||
|
+{
|
||||||
|
+ const int MAX_FORCE_INLINE_TARGET_LEN = 10000;
|
||||||
|
+ const int MAX_NUM_TARGET = 100;
|
||||||
|
+ __SIZE_TYPE__ length = strlen (arg);
|
||||||
|
+ int target_num = 1;
|
||||||
|
+ if (length > MAX_FORCE_INLINE_TARGET_LEN)
|
||||||
|
+ error_at (loc,
|
||||||
|
+ "input string exceeds %d characters to %<-finline_force=%> "
|
||||||
|
+ "option: %qs", MAX_FORCE_INLINE_TARGET_LEN, arg);
|
||||||
|
+ for (__SIZE_TYPE__ i = 0; i < length; i++)
|
||||||
|
+ {
|
||||||
|
+ if (arg[i] == ',')
|
||||||
|
+ {
|
||||||
|
+ target_num++;
|
||||||
|
+ if (target_num > MAX_NUM_TARGET)
|
||||||
|
+ error_at (loc, "input target exceeds %d to %<-finline_force=%> "
|
||||||
|
+ "option: %qs", MAX_NUM_TARGET, arg);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/* Handle target- and language-independent options. Return zero to
|
||||||
|
generate an "unknown option" message. Only options that need
|
||||||
|
extra handling need to be listed here; if you simply want
|
||||||
|
@@ -2952,6 +2978,14 @@ common_handle_option (struct gcc_options *opts,
|
||||||
|
value / 2);
|
||||||
|
break;
|
||||||
|
|
||||||
|
+ case OPT_finline_force:
|
||||||
|
+ opts->x_force_inline_targets_string = value ? "" : NULL;
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
+ case OPT_finline_force_:
|
||||||
|
+ check_force_inline_targets_string (arg, loc);
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
case OPT_finstrument_functions_exclude_function_list_:
|
||||||
|
add_comma_separated_to_vector
|
||||||
|
(&opts->x_flag_instrument_functions_exclude_functions, arg);
|
||||||
|
@@ -3226,6 +3260,18 @@ common_handle_option (struct gcc_options *opts,
|
||||||
|
"unrecognized argument to %<-flto=%> option: %qs", arg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
+ case OPT_flto_compression_algorithm_:
|
||||||
|
+ if (atoi (arg) == 0
|
||||||
|
+ && strcmp (arg, "zlib") != 0
|
||||||
|
+#ifdef HAVE_ZSTD_H
|
||||||
|
+ && strcmp (arg, "zstd") != 0
|
||||||
|
+#endif
|
||||||
|
+ )
|
||||||
|
+ error_at (loc,
|
||||||
|
+ "unrecognized argument to %<-flto-compression-algorithm=%> "
|
||||||
|
+ "option: %qs", arg);
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
case OPT_w:
|
||||||
|
dc->dc_inhibit_warnings = true;
|
||||||
|
break;
|
||||||
|
diff --git a/gcc/target.def b/gcc/target.def
|
||||||
|
index 7183f363d..142858fa3 100644
|
||||||
|
--- a/gcc/target.def
|
||||||
|
+++ b/gcc/target.def
|
||||||
|
@@ -6644,6 +6644,16 @@ information in the @code{struct cl_target_option} structure for\n\
|
||||||
|
function-specific options.",
|
||||||
|
void, (FILE *file, int indent, struct cl_target_option *ptr), NULL)
|
||||||
|
|
||||||
|
+/* Function to print any extra target state from the target options
|
||||||
|
+ structure. */
|
||||||
|
+DEFHOOK
|
||||||
|
+(print_diff,
|
||||||
|
+ "This hook is called to print diff additional target-specific\n\
|
||||||
|
+information in the ptr1 and ptr2 @code{struct cl_target_option} structure for\n\
|
||||||
|
+function-specific options.",
|
||||||
|
+ void, (FILE *file, int indent, struct cl_target_option *ptr1,
|
||||||
|
+ struct cl_target_option *ptr2), NULL)
|
||||||
|
+
|
||||||
|
/* Function to parse arguments to be validated for #pragma target, and to
|
||||||
|
change the state if the options are valid. If the first argument is
|
||||||
|
NULL, the second argument specifies the default options to use. Return
|
||||||
|
diff --git a/gcc/testsuite/gcc.dg/lto/binary-inline-1_0.c b/gcc/testsuite/gcc.dg/lto/binary-inline-1_0.c
|
||||||
|
new file mode 100644
|
||||||
|
index 000000000..0b5cd5953
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/gcc/testsuite/gcc.dg/lto/binary-inline-1_0.c
|
||||||
|
@@ -0,0 +1,15 @@
|
||||||
|
+/* { dg-lto-do link } */
|
||||||
|
+/* { dg-require-effective-target shared } */
|
||||||
|
+/* { dg-extra-ld-options {-shared -finline-force=c_lto_binary-inline-1_1.o} } */
|
||||||
|
+/* { dg-lto-options {{-O3 -flto -march=armv8.2-a -fdump-ipa-inline-details}} } */
|
||||||
|
+
|
||||||
|
+extern double multi_op(float x);
|
||||||
|
+
|
||||||
|
+double func_a (float x)
|
||||||
|
+{
|
||||||
|
+ double res = 0;
|
||||||
|
+ res = multi_op (x);
|
||||||
|
+ return res;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* { dg-final { scan-wpa-ipa-dump "Inlined 1 calls" "inline" } } */
|
||||||
|
diff --git a/gcc/testsuite/gcc.dg/lto/binary-inline-1_1.c b/gcc/testsuite/gcc.dg/lto/binary-inline-1_1.c
|
||||||
|
new file mode 100644
|
||||||
|
index 000000000..8181384b7
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/gcc/testsuite/gcc.dg/lto/binary-inline-1_1.c
|
||||||
|
@@ -0,0 +1,6 @@
|
||||||
|
+/* { dg-options "-march=armv8.3-a+sve+f64mm+crc+crypto+fp16+i8mm+simd" } */
|
||||||
|
+
|
||||||
|
+double multi_op (float x)
|
||||||
|
+{
|
||||||
|
+ return x * 2 + 10;
|
||||||
|
+}
|
||||||
|
diff --git a/gcc/testsuite/gcc.dg/lto/binary-inline-2_0.c b/gcc/testsuite/gcc.dg/lto/binary-inline-2_0.c
|
||||||
|
new file mode 100644
|
||||||
|
index 000000000..e873937d3
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/gcc/testsuite/gcc.dg/lto/binary-inline-2_0.c
|
||||||
|
@@ -0,0 +1,15 @@
|
||||||
|
+/* { dg-lto-do link } */
|
||||||
|
+/* { dg-require-effective-target shared } */
|
||||||
|
+/* { dg-extra-ld-options {-shared -finline-force=c_lto_binary-inline-2_1.o} } */
|
||||||
|
+/* { dg-lto-options {{-O3 -flto -fPIC -fdump-ipa-inline-details}} } */
|
||||||
|
+
|
||||||
|
+extern double multi_op(float x);
|
||||||
|
+
|
||||||
|
+double func_a (float x)
|
||||||
|
+{
|
||||||
|
+ double res = 0;
|
||||||
|
+ res = multi_op (x);
|
||||||
|
+ return res;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* { dg-final { scan-wpa-ipa-dump "Inlined 1 calls" "inline" } } */
|
||||||
|
diff --git a/gcc/testsuite/gcc.dg/lto/binary-inline-2_1.c b/gcc/testsuite/gcc.dg/lto/binary-inline-2_1.c
|
||||||
|
new file mode 100644
|
||||||
|
index 000000000..dc7c4fd9f
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/gcc/testsuite/gcc.dg/lto/binary-inline-2_1.c
|
||||||
|
@@ -0,0 +1,5 @@
|
||||||
|
+
|
||||||
|
+double multi_op (float x)
|
||||||
|
+{
|
||||||
|
+ return x * 2 + 10;
|
||||||
|
+}
|
||||||
|
diff --git a/gcc/testsuite/gcc.dg/lto/binary-inline-3_0.c b/gcc/testsuite/gcc.dg/lto/binary-inline-3_0.c
|
||||||
|
new file mode 100644
|
||||||
|
index 000000000..c78ba066d
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/gcc/testsuite/gcc.dg/lto/binary-inline-3_0.c
|
||||||
|
@@ -0,0 +1,15 @@
|
||||||
|
+/* { dg-lto-do link } */
|
||||||
|
+/* { dg-require-effective-target shared } */
|
||||||
|
+/* { dg-extra-ld-options {-shared -finline-force=c_lto_binary-inline-3_1.o} } */
|
||||||
|
+/* { dg-lto-options {{-O3 -flto -fdump-ipa-inline-details}} } */
|
||||||
|
+
|
||||||
|
+extern double multi_op(double x);
|
||||||
|
+
|
||||||
|
+double func_a (double x)
|
||||||
|
+{
|
||||||
|
+ double res = 0;
|
||||||
|
+ res = multi_op (x);
|
||||||
|
+ return res;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* { dg-final { scan-wpa-ipa-dump "Inlined 1 calls" "inline" } } */
|
||||||
|
diff --git a/gcc/testsuite/gcc.dg/lto/binary-inline-3_1.c b/gcc/testsuite/gcc.dg/lto/binary-inline-3_1.c
|
||||||
|
new file mode 100644
|
||||||
|
index 000000000..8b505fa0c
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/gcc/testsuite/gcc.dg/lto/binary-inline-3_1.c
|
||||||
|
@@ -0,0 +1,10 @@
|
||||||
|
+/* { dg-options "-O2 -fno-math-errno" } */
|
||||||
|
+
|
||||||
|
+#include <math.h>
|
||||||
|
+
|
||||||
|
+double multi_op (double x)
|
||||||
|
+{
|
||||||
|
+ double a = 0;
|
||||||
|
+ a = sqrt (x);
|
||||||
|
+ return a * 2 + 10;
|
||||||
|
+}
|
||||||
|
diff --git a/gcc/tree-streamer-in.cc b/gcc/tree-streamer-in.cc
|
||||||
|
index a35a810f4..79f819ad8 100644
|
||||||
|
--- a/gcc/tree-streamer-in.cc
|
||||||
|
+++ b/gcc/tree-streamer-in.cc
|
||||||
|
@@ -20,6 +20,9 @@ along with GCC; see the file COPYING3. If not see
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
+#include <cstdio>
|
||||||
|
+#define INCLUDE_SET
|
||||||
|
+#define INCLUDE_STRING
|
||||||
|
#include "system.h"
|
||||||
|
#include "coretypes.h"
|
||||||
|
#include "backend.h"
|
||||||
|
@@ -36,6 +39,47 @@ along with GCC; see the file COPYING3. If not see
|
||||||
|
#include "asan.h"
|
||||||
|
#include "opts.h"
|
||||||
|
|
||||||
|
+/* Parse string that specify forced inlining, separated by commas. */
|
||||||
|
+static std::set<std::string> multi_version_libs;
|
||||||
|
+static void
|
||||||
|
+parse_multi_version_lib_string (const char* s)
|
||||||
|
+{
|
||||||
|
+ std::string target_string (s);
|
||||||
|
+ std::string delim = ",";
|
||||||
|
+ size_t start = 0;
|
||||||
|
+ size_t end = target_string.find (delim);
|
||||||
|
+ if (target_string.substr (start, end - start) == "")
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ while (end != std::string::npos)
|
||||||
|
+ {
|
||||||
|
+ multi_version_libs.insert (target_string.substr (start, end - start));
|
||||||
|
+ start = end + delim.size ();
|
||||||
|
+ end = target_string.find (delim, start);
|
||||||
|
+ }
|
||||||
|
+ multi_version_libs.insert (target_string.substr (start, end - start));
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static bool
|
||||||
|
+target_lib_p (std::string name)
|
||||||
|
+{
|
||||||
|
+ if (multi_version_libs.empty () && multi_version_lib_string)
|
||||||
|
+ parse_multi_version_lib_string (multi_version_lib_string);
|
||||||
|
+ if (multi_version_lib_string)
|
||||||
|
+ {
|
||||||
|
+ while (!name.empty () && name.back () == '/')
|
||||||
|
+ name.erase (name.length () - 1);
|
||||||
|
+ if (name.empty ())
|
||||||
|
+ return false;
|
||||||
|
+ size_t last_slash_pos = name.find_last_of ('/');
|
||||||
|
+ if (last_slash_pos != std::string::npos
|
||||||
|
+ && last_slash_pos != name.length () - 1)
|
||||||
|
+ name = name.substr (last_slash_pos + 1);
|
||||||
|
+ if (multi_version_libs.find (name) != multi_version_libs.end ())
|
||||||
|
+ return true;
|
||||||
|
+ }
|
||||||
|
+ return false;
|
||||||
|
+}
|
||||||
|
|
||||||
|
/* Read a STRING_CST from the string table in DATA_IN using input
|
||||||
|
block IB. */
|
||||||
|
@@ -555,7 +599,12 @@ streamer_read_tree_bitfields (class lto_input_block *ib,
|
||||||
|
unpack_ts_translation_unit_decl_value_fields (data_in, &bp, expr);
|
||||||
|
|
||||||
|
if (CODE_CONTAINS_STRUCT (code, TS_OPTIMIZATION))
|
||||||
|
- cl_optimization_stream_in (data_in, &bp, TREE_OPTIMIZATION (expr));
|
||||||
|
+ {
|
||||||
|
+ if (target_lib_p (data_in->file_data->file_name))
|
||||||
|
+ cl_optimization_stream_in_prev (data_in, &bp, TREE_OPTIMIZATION (expr));
|
||||||
|
+ else
|
||||||
|
+ cl_optimization_stream_in (data_in, &bp, TREE_OPTIMIZATION (expr));
|
||||||
|
+ }
|
||||||
|
|
||||||
|
if (CODE_CONTAINS_STRUCT (code, TS_CONSTRUCTOR))
|
||||||
|
{
|
||||||
|
@@ -569,7 +618,12 @@ streamer_read_tree_bitfields (class lto_input_block *ib,
|
||||||
|
#ifndef ACCEL_COMPILER
|
||||||
|
if (CODE_CONTAINS_STRUCT (code, TS_TARGET_OPTION))
|
||||||
|
{
|
||||||
|
- cl_target_option_stream_in (data_in, &bp, TREE_TARGET_OPTION (expr));
|
||||||
|
+ if (target_lib_p (data_in->file_data->file_name))
|
||||||
|
+ cl_target_option_stream_in_prev (
|
||||||
|
+ data_in, &bp, TREE_TARGET_OPTION (expr));
|
||||||
|
+ else
|
||||||
|
+ cl_target_option_stream_in (data_in, &bp, TREE_TARGET_OPTION (expr));
|
||||||
|
+
|
||||||
|
if (targetm.target_option.post_stream_in)
|
||||||
|
targetm.target_option.post_stream_in (TREE_TARGET_OPTION (expr));
|
||||||
|
}
|
||||||
|
diff --git a/lto-plugin/lto-plugin.c b/lto-plugin/lto-plugin.c
|
||||||
|
index 33d49571d..b3301a8a4 100644
|
||||||
|
--- a/lto-plugin/lto-plugin.c
|
||||||
|
+++ b/lto-plugin/lto-plugin.c
|
||||||
|
@@ -89,6 +89,10 @@ along with this program; see the file COPYING3. If not see
|
||||||
|
|
||||||
|
#define LTO_SEGMENT_NAME "__GNU_LTO"
|
||||||
|
|
||||||
|
+#define GCC_major_version 12
|
||||||
|
+#define LTO_major_version GCC_major_version
|
||||||
|
+#define LTO_minor_version 0
|
||||||
|
+
|
||||||
|
/* Return true if STR string starts with PREFIX. */
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
@@ -118,6 +122,18 @@ struct plugin_symtab
|
||||||
|
unsigned long long id;
|
||||||
|
};
|
||||||
|
|
||||||
|
+/* Structure that represents LTO ELF section with information
|
||||||
|
+ about the format. */
|
||||||
|
+
|
||||||
|
+struct lto_section
|
||||||
|
+{
|
||||||
|
+ int16_t major_version;
|
||||||
|
+ int16_t minor_version;
|
||||||
|
+ unsigned char slim_object;
|
||||||
|
+ unsigned char _padding;
|
||||||
|
+ uint16_t flags;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
/* Encapsulates object file data during symbol scan. */
|
||||||
|
struct plugin_objfile
|
||||||
|
{
|
||||||
|
@@ -126,6 +142,7 @@ struct plugin_objfile
|
||||||
|
simple_object_read *objfile;
|
||||||
|
struct plugin_symtab *out;
|
||||||
|
const struct ld_plugin_input_file *file;
|
||||||
|
+ struct lto_section version;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* All that we have to remember about a file. */
|
||||||
|
@@ -216,6 +233,8 @@ static int gold_version = -1;
|
||||||
|
(in fact, only first letter of style arg is checked.) */
|
||||||
|
static enum symbol_style sym_style = ss_none;
|
||||||
|
|
||||||
|
+static bool multi_version_lto_parse = false;
|
||||||
|
+
|
||||||
|
static void
|
||||||
|
check_1 (int gate, enum ld_plugin_level level, const char *text)
|
||||||
|
{
|
||||||
|
@@ -1078,6 +1097,59 @@ err:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+/* Process version section of an object file. */
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+process_lto_version (void *data, const char *name, off_t offset, off_t length)
|
||||||
|
+{
|
||||||
|
+ struct plugin_objfile *obj = (struct plugin_objfile *)data;
|
||||||
|
+ char *s;
|
||||||
|
+ char *secdatastart, *secdata;
|
||||||
|
+
|
||||||
|
+ if (!startswith (name, ".gnu.lto_.lto"))
|
||||||
|
+ return 1;
|
||||||
|
+
|
||||||
|
+ s = strrchr (name, '.');
|
||||||
|
+ if (s)
|
||||||
|
+ sscanf (s, ".%" PRI_LL "x", &obj->out->id);
|
||||||
|
+ secdata = secdatastart = xmalloc (length);
|
||||||
|
+ offset += obj->file->offset;
|
||||||
|
+ if (offset != lseek (obj->file->fd, offset, SEEK_SET))
|
||||||
|
+ goto err;
|
||||||
|
+
|
||||||
|
+ do
|
||||||
|
+ {
|
||||||
|
+ ssize_t got = read (obj->file->fd, secdata, length);
|
||||||
|
+ if (got == 0)
|
||||||
|
+ break;
|
||||||
|
+ else if (got > 0)
|
||||||
|
+ {
|
||||||
|
+ secdata += got;
|
||||||
|
+ length -= got;
|
||||||
|
+ }
|
||||||
|
+ else if (errno != EINTR)
|
||||||
|
+ goto err;
|
||||||
|
+ }
|
||||||
|
+ while (length > 0);
|
||||||
|
+ if (length > 0)
|
||||||
|
+ goto err;
|
||||||
|
+
|
||||||
|
+ struct lto_section *lto_info = (struct lto_section *)secdatastart;
|
||||||
|
+ obj->version = *lto_info;
|
||||||
|
+
|
||||||
|
+ obj->found++;
|
||||||
|
+ free (secdatastart);
|
||||||
|
+ return 1;
|
||||||
|
+
|
||||||
|
+err:
|
||||||
|
+ if (message)
|
||||||
|
+ message (LDPL_FATAL, "%s: corrupt object file", obj->file->name);
|
||||||
|
+ /* Force claim_file_handler to abandon this file. */
|
||||||
|
+ obj->found = 0;
|
||||||
|
+ free (secdatastart);
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/* Process one section of an object file. */
|
||||||
|
|
||||||
|
static int
|
||||||
|
@@ -1223,6 +1295,15 @@ claim_file_handler (const struct ld_plugin_input_file *file, int *claimed)
|
||||||
|
if (obj.found == 0 && obj.offload == 0)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
+ if (multi_version_lto_parse)
|
||||||
|
+ {
|
||||||
|
+ simple_object_find_sections (obj.objfile, process_lto_version, &obj,
|
||||||
|
+ &err);
|
||||||
|
+ if (obj.version.major_version != LTO_major_version
|
||||||
|
+ || obj.version.minor_version != LTO_minor_version)
|
||||||
|
+ goto err;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if (obj.found > 1)
|
||||||
|
resolve_conflicts (<o_file.symtab, <o_file.conflicts);
|
||||||
|
|
||||||
|
@@ -1366,6 +1447,8 @@ process_option (const char *option)
|
||||||
|
}
|
||||||
|
else if (startswith (option, "-ltrans-objects="))
|
||||||
|
ltrans_objects = xstrdup (option + strlen ("-ltrans-objects="));
|
||||||
|
+ else if (strcmp (option, "-multi-version-lto-parse") == 0)
|
||||||
|
+ multi_version_lto_parse = true;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int size;
|
||||||
|
--
|
||||||
|
2.25.1
|
||||||
|
|
||||||
12
gcc.spec
12
gcc.spec
@ -2,7 +2,7 @@
|
|||||||
%global gcc_major 12
|
%global gcc_major 12
|
||||||
# Note, gcc_release must be integer, if you want to add suffixes to
|
# Note, gcc_release must be integer, if you want to add suffixes to
|
||||||
# %%{release}, append them after %%{gcc_release} on Release: line.
|
# %%{release}, append them after %%{gcc_release} on Release: line.
|
||||||
%global gcc_release 40
|
%global gcc_release 41
|
||||||
|
|
||||||
%global _unpackaged_files_terminate_build 0
|
%global _unpackaged_files_terminate_build 0
|
||||||
%global _performance_build 1
|
%global _performance_build 1
|
||||||
@ -409,6 +409,8 @@ Patch299: 0299-Backport-Disallow-pointer-operands-for-and-partly-PR.patch
|
|||||||
Patch300: 0300-Remove-erroneous-pattern-from-gimple-ifcvt.patch
|
Patch300: 0300-Remove-erroneous-pattern-from-gimple-ifcvt.patch
|
||||||
Patch301: 0301-Add-required-check-for-iteration-through-uses.patch
|
Patch301: 0301-Add-required-check-for-iteration-through-uses.patch
|
||||||
Patch302: 0302-Added-param-for-optimization-for-merging-bb-s-with-c.patch
|
Patch302: 0302-Added-param-for-optimization-for-merging-bb-s-with-c.patch
|
||||||
|
Patch303: 0303-Add-generation-of-stream-in-functions-for-pre-versio.patch
|
||||||
|
Patch304: 0304-Add-multi-version-lto-symbol-parse-cross-lto-units-i.patch
|
||||||
|
|
||||||
|
|
||||||
# Part 3000 ~ 4999
|
# Part 3000 ~ 4999
|
||||||
@ -1475,6 +1477,8 @@ not stable, so plugins must be rebuilt any time GCC is updated.
|
|||||||
%patch300 -p1
|
%patch300 -p1
|
||||||
%patch301 -p1
|
%patch301 -p1
|
||||||
%patch302 -p1
|
%patch302 -p1
|
||||||
|
%patch303 -p1
|
||||||
|
%patch304 -p1
|
||||||
|
|
||||||
|
|
||||||
%ifarch loongarch64
|
%ifarch loongarch64
|
||||||
@ -4067,6 +4071,12 @@ end
|
|||||||
%doc rpm.doc/changelogs/libcc1/ChangeLog*
|
%doc rpm.doc/changelogs/libcc1/ChangeLog*
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Thu Nov 21 2024 liyancheng <412998149@qq.com> - 12.3.1-41
|
||||||
|
- Type:Sync
|
||||||
|
- ID:NA
|
||||||
|
- SUG:NA
|
||||||
|
- DESC:Multi-version lto symbol parse and lto units ipa-inline extension
|
||||||
|
|
||||||
* Thu Nov 21 2024 liyancheng <412998149@qq.com> - 12.3.1-40
|
* Thu Nov 21 2024 liyancheng <412998149@qq.com> - 12.3.1-40
|
||||||
- Type:bugfix
|
- Type:bugfix
|
||||||
- ID:NA
|
- ID:NA
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user