| commit 126dab7c9d84294f256b1f7bf91c24a9e7103249 |
| Author: qinzhao <qinzhao@138bc75d-0d04-0410-961f-82ee72b054a4> |
| Date: Thu Nov 29 16:06:03 2018 +0000 |
| |
| 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. |
| |
| |
| git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@266627 138bc75d-0d04-0410-961f-82ee72b054a4 |
| |
| |
| |
| @@ -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")) |
| |
| |
| @@ -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. |
| |
| |
| @@ -389,6 +389,7 @@ Objective-C and Objective-C++ Dialects}. |
| -fipa-bit-cp -fipa-vrp @gol |
| -fipa-pta -fipa-profile -fipa-pure-const -fipa-reference -fipa-icf @gol |
| -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 |
| |
| |
| @@ -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 |
| { |
| |
| |
| @@ -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; |
| |
| |
| @@ -699,6 +699,152 @@ default_options_optimization (struct gcc |
| 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. */ |
| +// GCC 8 doesn't have these options. |
| +#if 0 |
| + 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; |
| +#endif |
| + |
| + 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. */ |
| @@ -1057,6 +1203,18 @@ finish_options (struct gcc_options *opts |
| 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); |
| + } |
| + |
| /* Comes from final.c -- no real reason to change it. */ |
| #define MAX_CODE_ALIGN 16 |
| #define MAX_CODE_ALIGN_VALUE (1 << MAX_CODE_ALIGN) |
| |
| |
| @@ -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" } } */ |
| |
| |
| @@ -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 } */ |
| |
| |
| @@ -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 } */ |