mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			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:
		
							parent
							
								
									4aff6d1744
								
							
						
					
					
						commit
						6fd6a2ffee
					
				|  | @ -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. | ||||
|  |  | |||
|  | @ -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. | ||||
|  |  | |||
|  | @ -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 | ||||
|  |  | |||
|  | @ -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; | ||||
|  |  | |||
							
								
								
									
										154
									
								
								gcc/opts.c
								
								
								
								
							
							
						
						
									
										154
									
								
								gcc/opts.c
								
								
								
								
							|  | @ -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 | ||||
|  |  | |||
|  | @ -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. | ||||
|  |  | |||
|  | @ -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 } */ | ||||
|  | @ -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"} } */ | ||||
|   | ||||
|  | @ -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" } } */ | ||||
		Loading…
	
		Reference in New Issue
	
	 Qing Zhao
						Qing Zhao