Add a new option -flive-patching={inline-only-static|inline-clone}

to support live patching in GCC.

2018-11-29  qing zhao  <qing.zhao@oracle.com>

gcc/ChangeLog:

	* cif-code.def (EXTERN_LIVE_ONLY_STATIC): New CIF code.
	* common.opt: Add -flive-patching flag.
	* doc/invoke.texi: Document -flive-patching.
	* flag-types.h (enum live_patching_level): New enum.
	* ipa-inline.c (can_inline_edge_p): Disable external functions from
	inlining when flag_live_patching is LIVE_PATCHING_INLINE_ONLY_STATIC.
	* opts.c (control_options_for_live_patching): New function.
	(finish_options): Make flag_live_patching incompatible with flag_lto.
	Control IPA optimizations based on different levels of 
	flag_live_patching.

gcc/testsuite/ChangeLog:

	* gcc.dg/live-patching-1.c: New test.
	* gcc.dg/live-patching-2.c: New test.
	* gcc.dg/live-patching-3.c: New test.
	* gcc.dg/tree-ssa/writeonly-3.c: New test.
	* gcc.target/i386/ipa-stack-alignment-2.c: New test.

From-SVN: r266627
This commit is contained in:
Qing Zhao 2018-11-29 16:06:03 +00:00 committed by Qing Zhao
parent 4aff6d1744
commit 6fd6a2ffee
13 changed files with 346 additions and 0 deletions

View File

@ -1,3 +1,16 @@
2018-11-29 qing zhao <qing.zhao@oracle.com>
* cif-code.def (EXTERN_LIVE_ONLY_STATIC): New CIF code.
* common.opt: Add -flive-patching flag.
* doc/invoke.texi: Document -flive-patching.
* flag-types.h (enum live_patching_level): New enum.
* ipa-inline.c (can_inline_edge_p): Disable external functions from
inlining when flag_live_patching is LIVE_PATCHING_INLINE_ONLY_STATIC.
* opts.c (control_options_for_live_patching): New function.
(finish_options): Make flag_live_patching incompatible with flag_lto.
Control IPA optimizations based on different levels of
flag_live_patching.
2018-11-29 Giuliano Belinassi <giuliano.belinassi@usp.br>
* match.pd (sinh (atanh (x))): New simplification rules.

View File

@ -132,6 +132,12 @@ DEFCIFCODE(USES_COMDAT_LOCAL, CIF_FINAL_ERROR,
DEFCIFCODE(ATTRIBUTE_MISMATCH, CIF_FINAL_ERROR,
N_("function attribute mismatch"))
/* 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, CIF_FINAL_ERROR,
N_("function has external linkage when the user requests only"
" inlining static for live patching"))
/* We proved that the call is unreachable. */
DEFCIFCODE(UNREACHABLE, CIF_FINAL_ERROR,
N_("unreachable"))

View File

@ -2181,6 +2181,24 @@ starts and when the destructor finishes.
flifetime-dse=
Common Joined RejectNegative UInteger Var(flag_lifetime_dse) Optimization IntegerRange(0, 2)
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)
flive-range-shrinkage
Common Report Var(flag_live_range_shrinkage) Init(0) Optimization
Relief of register pressure through live range shrinkage.

View File

@ -417,6 +417,7 @@ Objective-C and Objective-C++ Dialects}.
-fipa-bit-cp -fipa-vrp -fipa-pta -fipa-profile -fipa-pure-const @gol
-fipa-reference -fipa-reference-addressable @gol
-fipa-stack-alignment -fipa-icf -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 @gol
@ -9291,6 +9292,65 @@ equivalences that are found only by GCC and equivalences found only by Gold.
This flag is enabled by default at @option{-O2} and @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 -fisolate-erroneous-paths-dereference
@opindex fisolate-erroneous-paths-dereference
Detect paths that trigger erroneous or undefined behavior due to

View File

@ -123,6 +123,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 basic block reordering. */
enum reorder_blocks_algorithm
{

View File

@ -379,6 +379,12 @@ can_inline_edge_p (struct cgraph_edge *e, bool report,
e->inline_failed = CIF_ATTRIBUTE_MISMATCH;
inlinable = false;
}
else if (callee->externally_visible
&& flag_live_patching == LIVE_PATCHING_INLINE_ONLY_STATIC)
{
e->inline_failed = CIF_EXTERN_LIVE_ONLY_STATIC;
inlinable = false;
}
if (!inlinable && report)
report_inline_failed_reason (e);
return inlinable;

View File

@ -702,6 +702,148 @@ 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_ra && opts->x_flag_ipa_ra)
error_at (loc,
"%<-fipa-ra%> is incompatible with "
"%<-flive-patching=inline-only-static|inline-clone%>");
else
opts->x_flag_ipa_ra = 0;
if (opts_set->x_flag_ipa_icf && opts->x_flag_ipa_icf)
error_at (loc,
"%<-fipa-icf%> is incompatible with "
"%<-flive-patching=inline-only-static|inline-clone%>");
else
opts->x_flag_ipa_icf = 0;
if (opts_set->x_flag_ipa_icf_functions && opts->x_flag_ipa_icf_functions)
error_at (loc,
"%<-fipa-icf-functions%> is incompatible with "
"%<-flive-patching=inline-only-static|inline-clone%>");
else
opts->x_flag_ipa_icf_functions = 0;
if (opts_set->x_flag_ipa_icf_variables && opts->x_flag_ipa_icf_variables)
error_at (loc,
"%<-fipa-icf-variables%> is incompatible with "
"%<-flive-patching=inline-only-static|inline-clone%>");
else
opts->x_flag_ipa_icf_variables = 0;
if (opts_set->x_flag_ipa_bit_cp && opts->x_flag_ipa_bit_cp)
error_at (loc,
"%<-fipa-bit-cp%> is incompatible with "
"%<-flive-patching=inline-only-static|inline-clone%>");
else
opts->x_flag_ipa_bit_cp = 0;
if (opts_set->x_flag_ipa_vrp && opts->x_flag_ipa_vrp)
error_at (loc,
"%<-fipa-vrp%> is incompatible with "
"%<-flive-patching=inline-only-static|inline-clone%>");
else
opts->x_flag_ipa_vrp = 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. */
@ -1051,6 +1193,18 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
if ((opts->x_flag_sanitize & SANITIZE_KERNEL_ADDRESS) && opts->x_flag_tm)
sorry ("transactional memory is not supported with "
"%<-fsanitize=kernel-address%>");
/* 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

View File

@ -1,3 +1,11 @@
2018-11-29 qing zhao <qing.zhao@oracle.com>
* gcc.dg/live-patching-1.c: New test.
* gcc.dg/live-patching-2.c: New test.
* gcc.dg/live-patching-3.c: New test.
* gcc.dg/tree-ssa/writeonly-3.c: New test.
* gcc.target/i386/ipa-stack-alignment-2.c: New test.
2018-11-29 Giuliano Belinassi <giuliano.belinassi@usp.br>
* gcc.dg/sinhatanh-1.c: New test.

View File

@ -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" } } */

View File

@ -0,0 +1,9 @@
/* { dg-do compile } */
/* { 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 } */

View File

@ -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 } */

View File

@ -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"} } */

View File

@ -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" } } */