Files
gcc48/gcc48-flive-patching.patch
Richard Biener a3ce234b23 Accepting request 709668 from home:marxin:branches:devel:gcc48
- Add gcc48-flive-patching.patch patch.
- Add gcc48-ipa-clones-dump.patch in order to provide .ipa-clones dump
  files.

OBS-URL: https://build.opensuse.org/request/show/709668
OBS-URL: https://build.opensuse.org/package/show/devel:gcc/gcc48?expand=0&rev=232
2019-06-13 08:57:13 +00:00

583 lines
19 KiB
Diff
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index 8ab7ae18102..6cede317c17 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -724,7 +724,7 @@ void varpool_node_set_remove (varpool_node_set, struct varpool_node *);
void dump_varpool_node_set (FILE *, varpool_node_set);
void debug_varpool_node_set (varpool_node_set);
void free_varpool_node_set (varpool_node_set);
-void ipa_discover_readonly_nonaddressable_vars (void);
+void ipa_discover_variable_flags (void);
bool cgraph_comdat_can_be_unshared_p (struct cgraph_node *);
bool varpool_externally_visible_p (struct varpool_node *, bool);
diff --git a/gcc/cif-code.def b/gcc/cif-code.def
index 55e0ef45b3b..75e5b4d8bbe 100644
--- a/gcc/cif-code.def
+++ b/gcc/cif-code.def
@@ -106,3 +106,9 @@
/* We know that the call will be optimized out. */
DEFCIFCODE(NEVER_EXECUTED, N_("never executed"))
+
+/* We can't inline because the user requests only static functions
+ but the function has external linkage for live patching purpose. */
+DEFCIFCODE(EXTERN_LIVE_ONLY_STATIC,
+ N_("function has external linkage when the user requests only"
+ " inlining static for live patching"))
diff --git a/gcc/common.opt b/gcc/common.opt
index ec4cafc448b..816e10e7a9d 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -1206,6 +1206,24 @@ Common Report Var(flag_hoist_adjacent_loads) Optimization
Enable hoisting adjacent loads to encourage generating conditional move
instructions
+flive-patching
+Common RejectNegative Alias(flive-patching=,inline-clone) Optimization
+
+flive-patching=
+Common Report Joined RejectNegative Enum(live_patching_level) Var(flag_live_patching) Init(LIVE_PATCHING_NONE) Optimization
+-flive-patching=[inline-only-static|inline-clone] Control IPA
+optimizations to provide a safe compilation for live-patching. At the same
+time, provides multiple-level control on the enabled IPA optimizations.
+
+Enum
+Name(live_patching_level) Type(enum live_patching_level) UnknownError(unknown Live-Patching Level %qs)
+
+EnumValue
+Enum(live_patching_level) String(inline-only-static) Value(LIVE_PATCHING_INLINE_ONLY_STATIC)
+
+EnumValue
+Enum(live_patching_level) String(inline-clone) Value(LIVE_PATCHING_INLINE_CLONE)
+
floop-parallelize-all
Common Report Var(flag_loop_parallelize_all) Optimization
Mark all loops as parallel
@@ -1361,7 +1379,15 @@ Discover pure and const functions
fipa-reference
Common Report Var(flag_ipa_reference) Init(0) Optimization
-Discover readonly and non addressable static variables
+Discover read-only and non addressable static variables.
+
+fipa-reference-addressable
+Common Report Var(flag_ipa_reference_addressable) Init(0) Optimization
+Discover read-only, write-only and non-addressable static variables.
+
+fipa-stack-alignment
+Common Report Var(flag_ipa_stack_alignment) Init(1) Optimization
+Reduce stack alignment on call sites if possible.
fipa-matrix-reorg
Common Ignore
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index caf06c82d1d..4e8867ebf30 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -370,8 +370,9 @@ Objective-C and Objective-C++ Dialects}.
-fif-conversion2 -findirect-inlining @gol
-finline-functions -finline-functions-called-once -finline-limit=@var{n} @gol
-finline-small-functions -fipa-cp -fipa-cp-clone @gol
--fipa-pta -fipa-profile -fipa-pure-const -fipa-reference @gol
--fira-algorithm=@var{algorithm} @gol
+-fipa-pta -fipa-profile -fipa-pure-const -fipa-reference -fipa-reference-addressable @gol
+-fipa-stack-alignment -fira-algorithm=@var{algorithm} @gol
+-flive-patching=@var{level} @gol
-fira-region=@var{region} -fira-hoist-pressure @gol
-fira-loop-pressure -fno-ira-share-save-slots @gol
-fno-ira-share-spill-slots -fira-verbose=@var{n} @gol
@@ -6522,6 +6523,7 @@ compilation time.
-fipa-pure-const @gol
-fipa-profile @gol
-fipa-reference @gol
+-fipa-reference-addressable @gol
-fmerge-constants
-fsplit-wide-types @gol
-ftree-bit-ccp @gol
@@ -7111,6 +7113,65 @@ Perform a number of minor optimizations that are relatively expensive.
Enabled at levels @option{-O2}, @option{-O3}, @option{-Os}.
+@item -flive-patching=@var{level}
+@opindex flive-patching
+Control GCC's optimizations to provide a safe compilation for live-patching.
+
+If the compiler's optimization uses a function's body or information extracted
+from its body to optimize/change another function, the latter is called an
+impacted function of the former. If a function is patched, its impacted
+functions should be patched too.
+
+The impacted functions are decided by the compiler's interprocedural
+optimizations. For example, inlining a function into its caller, cloning
+a function and changing its caller to call this new clone, or extracting
+a function's pureness/constness information to optimize its direct or
+indirect callers, etc.
+
+Usually, the more IPA optimizations enabled, the larger the number of
+impacted functions for each function. In order to control the number of
+impacted functions and computed the list of impacted function easily,
+we provide control to partially enable IPA optimizations on two different
+levels.
+
+The @var{level} argument should be one of the following:
+
+@table @samp
+
+@item inline-clone
+
+Only enable inlining and cloning optimizations, which includes inlining,
+cloning, interprocedural scalar replacement of aggregates and partial inlining.
+As a result, when patching a function, all its callers and its clones'
+callers need to be patched as well.
+
+@option{-flive-patching=inline-clone} disables the following optimization flags:
+@gccoptlist{-fwhole-program -fipa-pta -fipa-reference -fipa-ra @gol
+-fipa-icf -fipa-icf-functions -fipa-icf-variables @gol
+-fipa-bit-cp -fipa-vrp -fipa-pure-const -fipa-reference-addressable @gol
+-fipa-stack-alignment}
+
+@item inline-only-static
+
+Only enable inlining of static functions.
+As a result, when patching a static function, all its callers need to be
+patches as well.
+
+In addition to all the flags that -flive-patching=inline-clone disables,
+@option{-flive-patching=inline-only-static} disables the following additional
+optimization flags:
+@gccoptlist{-fipa-cp-clone -fipa-sra -fpartial-inlining -fipa-cp}
+
+@end table
+
+When -flive-patching specified without any value, the default value
+is "inline-clone".
+
+This flag is disabled by default.
+
+Note that -flive-patching is not supported with link-time optimizer.
+(@option{-flto}).
+
@item -free
@opindex free
Attempt to remove redundant extension instructions. This is especially
@@ -7459,6 +7520,16 @@ Discover which static variables do not escape the
compilation unit.
Enabled by default at @option{-O} and higher.
+@item -fipa-reference-addressable
+@opindex fipa-reference-addressable
+Discover read-only, write-only and non-addressable static variables.
+Enabled by default at @option{-O} and higher.
+
+@item -fipa-stack-alignment
+@opindex fipa-stack-alignment
+Reduce stack alignment on call sites if possible.
+Enabled by default.
+
@item -fipa-pta
@opindex fipa-pta
Perform interprocedural pointer analysis and interprocedural modification
diff --git a/gcc/final.c b/gcc/final.c
index d25b8e0b7e4..cf22d390945 100644
--- a/gcc/final.c
+++ b/gcc/final.c
@@ -4540,7 +4540,8 @@ rest_of_clean_state (void)
/* We can reduce stack alignment on call site only when we are sure that
the function body just produced will be actually used in the final
executable. */
- if (decl_binds_to_current_def_p (current_function_decl))
+ if (flag_ipa_stack_alignment
+ && decl_binds_to_current_def_p (current_function_decl))
{
unsigned int pref = crtl->preferred_stack_boundary;
if (crtl->stack_alignment_needed > crtl->preferred_stack_boundary)
diff --git a/gcc/flag-types.h b/gcc/flag-types.h
index 4fc5d33348e..590071f99ba 100644
--- a/gcc/flag-types.h
+++ b/gcc/flag-types.h
@@ -112,6 +112,14 @@ enum stack_reuse_level
SR_ALL
};
+/* The live patching level. */
+enum live_patching_level
+{
+ LIVE_PATCHING_NONE = 0,
+ LIVE_PATCHING_INLINE_ONLY_STATIC,
+ LIVE_PATCHING_INLINE_CLONE
+};
+
/* The algorithm used for the integrated register allocator (IRA). */
enum ira_algorithm
{
diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c
index 90b2a13fce9..33589cfab16 100644
--- a/gcc/ipa-inline.c
+++ b/gcc/ipa-inline.c
@@ -316,6 +316,13 @@ can_inline_edge_p (struct cgraph_edge *e, bool report)
: e->caller->symbol.decl))
&& !caller_growth_limits (e))
inlinable = false;
+ else if (callee->symbol.externally_visible
+ && !DECL_DISREGARD_INLINE_LIMITS (callee->symbol.decl)
+ && flag_live_patching == LIVE_PATCHING_INLINE_ONLY_STATIC)
+ {
+ e->inline_failed = CIF_EXTERN_LIVE_ONLY_STATIC;
+ inlinable = false;
+ }
/* Don't inline a function with a higher optimization level than the
caller. FIXME: this is really just tip of iceberg of handling
optimization attribute. */
diff --git a/gcc/ipa-reference.c b/gcc/ipa-reference.c
index f3c483f67f9..3463b7655e9 100644
--- a/gcc/ipa-reference.c
+++ b/gcc/ipa-reference.c
@@ -675,7 +675,7 @@ propagate (void)
if (dump_file)
dump_cgraph (dump_file);
- ipa_discover_readonly_nonaddressable_vars ();
+ ipa_discover_variable_flags ();
generate_summary ();
/* Now we know what vars are really statics; prune out those that aren't. */
diff --git a/gcc/ipa.c b/gcc/ipa.c
index be377a70e1d..6bd215f35e6 100644
--- a/gcc/ipa.c
+++ b/gcc/ipa.c
@@ -474,7 +474,7 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
make sense to do it before early optimizations. */
void
-ipa_discover_readonly_nonaddressable_vars (void)
+ipa_discover_variable_flags (void)
{
struct varpool_node *vnode;
if (dump_file)
@@ -1018,7 +1018,7 @@ whole_program_function_and_variable_visibility (void)
{
function_and_variable_visibility (flag_whole_program);
if (optimize)
- ipa_discover_readonly_nonaddressable_vars ();
+ ipa_discover_variable_flags ();
return 0;
}
diff --git a/gcc/opts.c b/gcc/opts.c
index 55cd965282d..78a79daa6dc 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -429,6 +429,7 @@ static const struct default_options default_options_table[] =
{ OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_fif_conversion2, NULL, 1 },
{ OPT_LEVELS_1_PLUS, OPT_fipa_pure_const, NULL, 1 },
{ OPT_LEVELS_1_PLUS, OPT_fipa_reference, NULL, 1 },
+ { OPT_LEVELS_1_PLUS, OPT_fipa_reference_addressable, NULL, 1 },
{ OPT_LEVELS_1_PLUS, OPT_fipa_profile, NULL, 1 },
{ OPT_LEVELS_1_PLUS, OPT_fmerge_constants, NULL, 1 },
{ OPT_LEVELS_1_PLUS, OPT_fshrink_wrap, NULL, 1 },
@@ -623,6 +624,106 @@ default_options_optimization (struct gcc_options *opts,
lang_mask, handlers, loc, dc);
}
+/* Control IPA optimizations based on different live patching LEVEL. */
+static void
+control_options_for_live_patching (struct gcc_options *opts,
+ struct gcc_options *opts_set,
+ enum live_patching_level level,
+ location_t loc)
+{
+ gcc_assert (level > LIVE_PATCHING_NONE);
+
+ switch (level)
+ {
+ case LIVE_PATCHING_INLINE_ONLY_STATIC:
+ if (opts_set->x_flag_ipa_cp_clone && opts->x_flag_ipa_cp_clone)
+ error_at (loc,
+ "%<-fipa-cp-clone%> is incompatible with "
+ "%<-flive-patching=inline-only-static%>");
+ else
+ opts->x_flag_ipa_cp_clone = 0;
+
+ if (opts_set->x_flag_ipa_sra && opts->x_flag_ipa_sra)
+ error_at (loc,
+ "%<-fipa-sra%> is incompatible with "
+ "%<-flive-patching=inline-only-static%>");
+ else
+ opts->x_flag_ipa_sra = 0;
+
+ if (opts_set->x_flag_partial_inlining && opts->x_flag_partial_inlining)
+ error_at (loc,
+ "%<-fpartial-inlining%> is incompatible with "
+ "%<-flive-patching=inline-only-static%>");
+ else
+ opts->x_flag_partial_inlining = 0;
+
+ if (opts_set->x_flag_ipa_cp && opts->x_flag_ipa_cp)
+ error_at (loc,
+ "%<-fipa-cp%> is incompatible with "
+ "%<-flive-patching=inline-only-static%>");
+ else
+ opts->x_flag_ipa_cp = 0;
+
+ /* FALLTHROUGH. */
+ case LIVE_PATCHING_INLINE_CLONE:
+ /* live patching should disable whole-program optimization. */
+ if (opts_set->x_flag_whole_program && opts->x_flag_whole_program)
+ error_at (loc,
+ "%<-fwhole-program%> is incompatible with "
+ "%<-flive-patching=inline-only-static|inline-clone%>");
+ else
+ opts->x_flag_whole_program = 0;
+
+ /* visibility change should be excluded by !flag_whole_program
+ && !in_lto_p && !flag_ipa_cp_clone && !flag_ipa_sra
+ && !flag_partial_inlining. */
+
+ if (opts_set->x_flag_ipa_pta && opts->x_flag_ipa_pta)
+ error_at (loc,
+ "%<-fipa-pta%> is incompatible with "
+ "%<-flive-patching=inline-only-static|inline-clone%>");
+ else
+ opts->x_flag_ipa_pta = 0;
+
+ if (opts_set->x_flag_ipa_reference && opts->x_flag_ipa_reference)
+ error_at (loc,
+ "%<-fipa-reference%> is incompatible with "
+ "%<-flive-patching=inline-only-static|inline-clone%>");
+ else
+ opts->x_flag_ipa_reference = 0;
+
+ if (opts_set->x_flag_ipa_pure_const && opts->x_flag_ipa_pure_const)
+ error_at (loc,
+ "%<-fipa-pure-const%> is incompatible with "
+ "%<-flive-patching=inline-only-static|inline-clone%>");
+ else
+ opts->x_flag_ipa_pure_const = 0;
+
+ /* FIXME: disable unreachable code removal. */
+
+ /* discovery of functions/variables with no address taken. */
+ if (opts_set->x_flag_ipa_reference_addressable
+ && opts->x_flag_ipa_reference_addressable)
+ error_at (loc,
+ "%<-fipa-reference-addressable%> is incompatible with "
+ "%<-flive-patching=inline-only-static|inline-clone%>");
+ else
+ opts->x_flag_ipa_reference_addressable = 0;
+
+ /* ipa stack alignment propagation. */
+ if (opts_set->x_flag_ipa_stack_alignment
+ && opts->x_flag_ipa_stack_alignment)
+ error_at (loc,
+ "%<-fipa-stack-alignment%> is incompatible with "
+ "%<-flive-patching=inline-only-static|inline-clone%>");
+ else
+ opts->x_flag_ipa_stack_alignment = 0;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+}
+
/* After all options at LOC have been read into OPTS and OPTS_SET,
finalize settings of those options and diagnose incompatible
combinations. */
@@ -831,6 +932,18 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
/* The -gsplit-dwarf option requires -gpubnames. */
if (opts->x_dwarf_split_debug_info)
opts->x_debug_generate_pub_sections = 1;
+
+ /* Currently live patching is not support for LTO. */
+ if (opts->x_flag_live_patching && opts->x_flag_lto)
+ sorry ("live patching is not supported with LTO");
+
+ /* Control IPA optimizations based on different -flive-patching level. */
+ if (opts->x_flag_live_patching)
+ {
+ control_options_for_live_patching (opts, opts_set,
+ opts->x_flag_live_patching,
+ loc);
+ }
}
#define LEFT_COLUMN 27
diff --git a/gcc/testsuite/gcc.dg/live-patching-1.c b/gcc/testsuite/gcc.dg/live-patching-1.c
new file mode 100644
index 00000000000..ab4738119b8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/live-patching-1.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -flive-patching=inline-only-static -fdump-ipa-inline" } */
+
+extern int sum, n, m;
+
+int foo (int a)
+{
+ return a + n;
+}
+
+static int bar (int b)
+{
+ return b * m;
+}
+
+int main()
+{
+ sum = foo (m) + bar (n);
+ return 0;
+}
+
+/* { dg-final { scan-ipa-dump "foo/0 function has external linkage when the user requests only inlining static for live patching" "inline" } } */
diff --git a/gcc/testsuite/gcc.dg/live-patching-2.c b/gcc/testsuite/gcc.dg/live-patching-2.c
new file mode 100644
index 00000000000..0dde4e9e0c0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/live-patching-2.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target lto } */
+/* { dg-options "-O2 -flive-patching -flto" } */
+
+int main()
+{
+ return 0;
+}
+
+/* { dg-message "sorry, unimplemented: live patching is not supported with LTO" "-flive-patching and -flto together" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.dg/live-patching-3.c b/gcc/testsuite/gcc.dg/live-patching-3.c
new file mode 100644
index 00000000000..b86f3c6e08a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/live-patching-3.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -flive-patching -fwhole-program" } */
+
+int main()
+{
+ return 0;
+}
+
+/* { dg-message "'-fwhole-program' is incompatible with '-flive-patching=inline-only-static|inline-clone" "" {target "*-*-*"} 0 } */
diff --git a/gcc/testsuite/gcc.dg/live-patching-4.c b/gcc/testsuite/gcc.dg/live-patching-4.c
new file mode 100644
index 00000000000..c3862a5bd7e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/live-patching-4.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -flive-patching=inline-only-static -fdump-tree-einline" } */
+
+extern int sum, n, m;
+
+extern inline __attribute__((always_inline)) int foo (int a);
+inline __attribute__((always_inline)) int foo (int a)
+{
+ return a + n;
+}
+
+static int bar (int b)
+{
+ return b * m;
+}
+
+int main()
+{
+ sum = foo (m) + bar (n);
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump "Inlining foo into main" "einline" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/writeonly-2.c b/gcc/testsuite/gcc.dg/tree-ssa/writeonly-2.c
new file mode 100644
index 00000000000..78893bd7fb8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/writeonly-2.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -fdump-tree-optimized -fno-ipa-reference-addressable" } */
+static struct a {int magic1,b;} a;
+volatile int magic2;
+static struct b {int a,b,c,d,e,f;} magic3;
+
+struct b foo();
+
+void
+t()
+{
+ a.magic1 = 1;
+ magic2 = 1;
+ magic3 = foo();
+}
+/* { dg-final { scan-tree-dump "magic1" "optimized"} } */
+/* { dg-final { scan-tree-dump "magic3" "optimized"} } */
+/* { dg-final { scan-tree-dump "magic2" "optimized"} } */
+/* { dg-final { scan-tree-dump "foo" "optimized"} } */
+
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/writeonly-3.c b/gcc/testsuite/gcc.dg/tree-ssa/writeonly-3.c
new file mode 100644
index 00000000000..b42d9374fe9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/writeonly-3.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -fdump-tree-optimized -flive-patching" } */
+static struct a {int magic1,b;} a;
+volatile int magic2;
+static struct b {int a,b,c,d,e,f;} magic3;
+
+struct b foo();
+
+void
+t()
+{
+ a.magic1 = 1;
+ magic2 = 1;
+ magic3 = foo();
+}
+/* { dg-final { scan-tree-dump "magic1" "optimized"} } */
+/* { dg-final { scan-tree-dump "magic3" "optimized"} } */
+/* { dg-final { scan-tree-dump "magic2" "optimized"} } */
+/* { dg-final { scan-tree-dump "foo" "optimized"} } */
+
diff --git a/gcc/testsuite/gcc.target/i386/ipa-stack-alignment-2.c b/gcc/testsuite/gcc.target/i386/ipa-stack-alignment-2.c
new file mode 100644
index 00000000000..8ba70000b7e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/ipa-stack-alignment-2.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-flive-patching -O" } */
+
+typedef struct {
+ long a;
+ long b[];
+} c;
+
+c *d;
+void e() { d->b[0] = 5; }
+void f() { e(); }
+
+/* { dg-final { scan-assembler "sub.*%.sp" } } */
diff --git a/gcc/testsuite/gcc.target/i386/ipa-stack-alignment.c b/gcc/testsuite/gcc.target/i386/ipa-stack-alignment.c
new file mode 100644
index 00000000000..1176b59aa5f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/ipa-stack-alignment.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-fno-ipa-stack-alignment -O" } */
+
+typedef struct {
+ long a;
+ long b[];
+} c;
+
+c *d;
+void e() { d->b[0] = 5; }
+void f() { e(); }
+
+/* { dg-final { scan-assembler "sub.*%.sp" } } */