This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Add -Og optimization level - optimize for compile-time/debugging experience
- From: Richard Guenther <rguenther at suse dot de>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 18 Sep 2012 13:23:34 +0200 (CEST)
- Subject: [PATCH] Add -Og optimization level - optimize for compile-time/debugging experience
This adds -Og as optimization level targeted at the devel-compile-debug
cycle (formerly mostly tied to -O0 due to debug issues with even -O1).
Discussion on gcc@gcc.gnu.org at least shows interest in this, so this
is a formal patch submission with a request for comments on the
implementation (not necessarily on what passes are enabled and why).
I have bootstrapped and tested this patch with BOOT_C/CXX_FLAGS="-Og -g"
TARGET_CFLAGS="-Og -g" with all languages included (but -Werror disabled,
as expected some new maybe-uninit uses pop up).
Ok for trunk?
Thanks,
Richard.
2012-09-18 Richard Guenther <rguenther@suse.de>
PR other/53316
* common.opt (optimize_debug): New variable.
(Og): New optimization level.
* doc/invoke.texi (Og): Document.
* opts.c (maybe_default_option): Add debug parameter.
(maybe_default_options): Likewise.
(default_options_optimization): Handle -Og.
(common_handle_option): Likewise.
* passes.c (gate_all_optimizations): Do not run with -Og.
(gate_all_optimizations_g): New gate, run with -Og.
(pass_all_optimizations_g): New container pass, run with -Og.
(init_optimization_passes): Schedule pass_all_optimizations_g
alongside pass_all_optimizations.
* gcc/testsuite/lib/c-torture.exp: Add -Og -g to default
TORTURE_OPTIONS.
Index: trunk/gcc/common.opt
===================================================================
*** trunk.orig/gcc/common.opt 2012-07-19 10:39:47.000000000 +0200
--- trunk/gcc/common.opt 2012-08-10 11:58:22.218122816 +0200
*************** int optimize
*** 32,37 ****
--- 32,40 ----
Variable
int optimize_size
+ Variable
+ int optimize_debug
+
; Not used directly to control optimizations, only to save -Ofast
; setting for "optimize" attributes.
Variable
*************** Ofast
*** 446,451 ****
--- 449,458 ----
Common Optimization
Optimize for speed disregarding exact standards compliance
+ Og
+ Common Optimization
+ Optimize for debugging experience rather than speed or size
+
Q
Driver
Index: trunk/gcc/opts.c
===================================================================
*** trunk.orig/gcc/opts.c 2012-07-24 10:35:57.000000000 +0200
--- trunk/gcc/opts.c 2012-08-10 13:47:45.678895549 +0200
*************** init_options_struct (struct gcc_options
*** 314,328 ****
}
/* If indicated by the optimization level LEVEL (-Os if SIZE is set,
! -Ofast if FAST is set), apply the option DEFAULT_OPT to OPTS and
! OPTS_SET, diagnostic context DC, location LOC, with language mask
! LANG_MASK and option handlers HANDLERS. */
static void
maybe_default_option (struct gcc_options *opts,
struct gcc_options *opts_set,
const struct default_options *default_opt,
! int level, bool size, bool fast,
unsigned int lang_mask,
const struct cl_option_handlers *handlers,
location_t loc,
--- 314,328 ----
}
/* If indicated by the optimization level LEVEL (-Os if SIZE is set,
! -Ofast if FAST is set, -Og if DEBUG is set), apply the option DEFAULT_OPT
! to OPTS and OPTS_SET, diagnostic context DC, location LOC, with language
! mask LANG_MASK and option handlers HANDLERS. */
static void
maybe_default_option (struct gcc_options *opts,
struct gcc_options *opts_set,
const struct default_options *default_opt,
! int level, bool size, bool fast, bool debug,
unsigned int lang_mask,
const struct cl_option_handlers *handlers,
location_t loc,
*************** maybe_default_option (struct gcc_options
*** 335,340 ****
--- 335,342 ----
gcc_assert (level == 2);
if (fast)
gcc_assert (level == 3);
+ if (debug)
+ gcc_assert (level == 1);
switch (default_opt->levels)
{
*************** maybe_default_option (struct gcc_options
*** 351,357 ****
break;
case OPT_LEVELS_1_PLUS_SPEED_ONLY:
! enabled = (level >= 1 && !size);
break;
case OPT_LEVELS_2_PLUS:
--- 353,363 ----
break;
case OPT_LEVELS_1_PLUS_SPEED_ONLY:
! enabled = (level >= 1 && !size && !debug);
! break;
!
! case OPT_LEVELS_1_PLUS_NOT_DEBUG:
! enabled = (level >= 1 && !debug);
break;
case OPT_LEVELS_2_PLUS:
*************** maybe_default_option (struct gcc_options
*** 359,365 ****
break;
case OPT_LEVELS_2_PLUS_SPEED_ONLY:
! enabled = (level >= 2 && !size);
break;
case OPT_LEVELS_3_PLUS:
--- 365,371 ----
break;
case OPT_LEVELS_2_PLUS_SPEED_ONLY:
! enabled = (level >= 2 && !size && !debug);
break;
case OPT_LEVELS_3_PLUS:
*************** static void
*** 405,411 ****
maybe_default_options (struct gcc_options *opts,
struct gcc_options *opts_set,
const struct default_options *default_opts,
! int level, bool size, bool fast,
unsigned int lang_mask,
const struct cl_option_handlers *handlers,
location_t loc,
--- 411,417 ----
maybe_default_options (struct gcc_options *opts,
struct gcc_options *opts_set,
const struct default_options *default_opts,
! int level, bool size, bool fast, bool debug,
unsigned int lang_mask,
const struct cl_option_handlers *handlers,
location_t loc,
*************** maybe_default_options (struct gcc_option
*** 415,421 ****
for (i = 0; default_opts[i].levels != OPT_LEVELS_NONE; i++)
maybe_default_option (opts, opts_set, &default_opts[i],
! level, size, fast, lang_mask, handlers, loc, dc);
}
/* Table of options enabled by default at different levels. */
--- 421,428 ----
for (i = 0; default_opts[i].levels != OPT_LEVELS_NONE; i++)
maybe_default_option (opts, opts_set, &default_opts[i],
! level, size, fast, debug,
! lang_mask, handlers, loc, dc);
}
/* Table of options enabled by default at different levels. */
*************** static const struct default_options defa
*** 444,450 ****
{ OPT_LEVELS_1_PLUS, OPT_ftree_dominator_opts, NULL, 1 },
{ OPT_LEVELS_1_PLUS, OPT_ftree_dse, NULL, 1 },
{ OPT_LEVELS_1_PLUS, OPT_ftree_ter, NULL, 1 },
! { OPT_LEVELS_1_PLUS, OPT_ftree_sra, NULL, 1 },
{ OPT_LEVELS_1_PLUS, OPT_ftree_copyrename, NULL, 1 },
{ OPT_LEVELS_1_PLUS, OPT_ftree_fre, NULL, 1 },
{ OPT_LEVELS_1_PLUS, OPT_ftree_copy_prop, NULL, 1 },
--- 451,457 ----
{ OPT_LEVELS_1_PLUS, OPT_ftree_dominator_opts, NULL, 1 },
{ OPT_LEVELS_1_PLUS, OPT_ftree_dse, NULL, 1 },
{ OPT_LEVELS_1_PLUS, OPT_ftree_ter, NULL, 1 },
! { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_ftree_sra, NULL, 1 },
{ OPT_LEVELS_1_PLUS, OPT_ftree_copyrename, NULL, 1 },
{ OPT_LEVELS_1_PLUS, OPT_ftree_fre, NULL, 1 },
{ OPT_LEVELS_1_PLUS, OPT_ftree_copy_prop, NULL, 1 },
*************** static const struct default_options defa
*** 498,504 ****
/* Inlining of functions reducing size is a good idea with -Os
regardless of them being declared inline. */
{ OPT_LEVELS_3_PLUS_AND_SIZE, OPT_finline_functions, NULL, 1 },
! { OPT_LEVELS_1_PLUS, OPT_finline_functions_called_once, NULL, 1 },
{ OPT_LEVELS_3_PLUS, OPT_funswitch_loops, NULL, 1 },
{ OPT_LEVELS_3_PLUS, OPT_fgcse_after_reload, NULL, 1 },
{ OPT_LEVELS_3_PLUS, OPT_ftree_vectorize, NULL, 1 },
--- 505,511 ----
/* Inlining of functions reducing size is a good idea with -Os
regardless of them being declared inline. */
{ OPT_LEVELS_3_PLUS_AND_SIZE, OPT_finline_functions, NULL, 1 },
! { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_finline_functions_called_once, NULL, 1 },
{ OPT_LEVELS_3_PLUS, OPT_funswitch_loops, NULL, 1 },
{ OPT_LEVELS_3_PLUS, OPT_fgcse_after_reload, NULL, 1 },
{ OPT_LEVELS_3_PLUS, OPT_ftree_vectorize, NULL, 1 },
*************** default_options_optimization (struct gcc
*** 540,545 ****
--- 547,553 ----
opts->x_optimize = 1;
opts->x_optimize_size = 0;
opts->x_optimize_fast = 0;
+ opts->x_optimize_debug = 0;
}
else
{
*************** default_options_optimization (struct gcc
*** 555,560 ****
--- 563,569 ----
opts->x_optimize = 255;
opts->x_optimize_size = 0;
opts->x_optimize_fast = 0;
+ opts->x_optimize_debug = 0;
}
}
break;
*************** default_options_optimization (struct gcc
*** 565,570 ****
--- 574,580 ----
/* Optimizing for size forces optimize to be 2. */
opts->x_optimize = 2;
opts->x_optimize_fast = 0;
+ opts->x_optimize_debug = 0;
break;
case OPT_Ofast:
*************** default_options_optimization (struct gcc
*** 572,577 ****
--- 582,596 ----
opts->x_optimize_size = 0;
opts->x_optimize = 3;
opts->x_optimize_fast = 1;
+ opts->x_optimize_debug = 0;
+ break;
+
+ case OPT_Og:
+ /* -Og selects optimization level 1. */
+ opts->x_optimize_size = 0;
+ opts->x_optimize = 1;
+ opts->x_optimize_fast = 0;
+ opts->x_optimize_debug = 1;
break;
default:
*************** default_options_optimization (struct gcc
*** 582,588 ****
maybe_default_options (opts, opts_set, default_options_table,
opts->x_optimize, opts->x_optimize_size,
! opts->x_optimize_fast, lang_mask, handlers, loc, dc);
/* -O2 param settings. */
opt2 = (opts->x_optimize >= 2);
--- 601,608 ----
maybe_default_options (opts, opts_set, default_options_table,
opts->x_optimize, opts->x_optimize_size,
! opts->x_optimize_fast, opts->x_optimize_debug,
! lang_mask, handlers, loc, dc);
/* -O2 param settings. */
opt2 = (opts->x_optimize >= 2);
*************** default_options_optimization (struct gcc
*** 612,618 ****
maybe_default_options (opts, opts_set,
targetm_common.option_optimization_table,
opts->x_optimize, opts->x_optimize_size,
! opts->x_optimize_fast, lang_mask, handlers, loc, dc);
}
/* After all options at LOC have been read into OPTS and OPTS_SET,
--- 632,639 ----
maybe_default_options (opts, opts_set,
targetm_common.option_optimization_table,
opts->x_optimize, opts->x_optimize_size,
! opts->x_optimize_fast, opts->x_optimize_debug,
! lang_mask, handlers, loc, dc);
}
/* After all options at LOC have been read into OPTS and OPTS_SET,
*************** common_handle_option (struct gcc_options
*** 1408,1413 ****
--- 1429,1435 ----
case OPT_O:
case OPT_Os:
case OPT_Ofast:
+ case OPT_Og:
/* Currently handled in a prescan. */
break;
Index: trunk/gcc/passes.c
===================================================================
*** trunk.orig/gcc/passes.c 2012-08-03 10:54:00.000000000 +0200
--- trunk/gcc/passes.c 2012-08-10 12:45:16.449025382 +0200
*************** static struct gimple_opt_pass pass_all_e
*** 337,346 ****
static bool
gate_all_optimizations (void)
{
! return (optimize >= 1
! /* Don't bother doing anything if the program has errors.
! We have to pass down the queue if we already went into SSA */
! && (!seen_error () || gimple_in_ssa_p (cfun)));
}
static struct gimple_opt_pass pass_all_optimizations =
--- 337,343 ----
static bool
gate_all_optimizations (void)
{
! return optimize >= 1 && !optimize_debug;
}
static struct gimple_opt_pass pass_all_optimizations =
*************** static struct gimple_opt_pass pass_all_o
*** 362,367 ****
--- 359,391 ----
}
};
+ /* Gate: execute, or not, all of the non-trivial optimizations. */
+
+ static bool
+ gate_all_optimizations_g (void)
+ {
+ return optimize >= 1 && optimize_debug;
+ }
+
+ static struct gimple_opt_pass pass_all_optimizations_g =
+ {
+ {
+ GIMPLE_PASS,
+ "*all_optimizations_g", /* name */
+ gate_all_optimizations_g, /* gate */
+ NULL, /* execute */
+ NULL, /* sub */
+ NULL, /* next */
+ 0, /* static_pass_number */
+ TV_OPTIMIZE, /* tv_id */
+ 0, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ 0 /* todo_flags_finish */
+ }
+ };
+
static bool
gate_rest_of_compilation (void)
{
*************** init_optimization_passes (void)
*** 1493,1498 ****
--- 1517,1545 ----
NEXT_PASS (pass_uncprop);
NEXT_PASS (pass_local_pure_const);
}
+ NEXT_PASS (pass_all_optimizations_g);
+ {
+ struct opt_pass **p = &pass_all_optimizations_g.pass.sub;
+ NEXT_PASS (pass_remove_cgraph_callee_edges);
+ NEXT_PASS (pass_strip_predict_hints);
+ /* Lower remaining pieces of GIMPLE. */
+ NEXT_PASS (pass_lower_complex);
+ NEXT_PASS (pass_lower_vector_ssa);
+ /* Perform simple scalar cleanup which is constant/copy propagation. */
+ NEXT_PASS (pass_ccp);
+ NEXT_PASS (pass_copy_prop);
+ NEXT_PASS (pass_rename_ssa_copies);
+ NEXT_PASS (pass_dce);
+ /* Fold remaining builtins. */
+ NEXT_PASS (pass_object_sizes);
+ NEXT_PASS (pass_fold_builtins);
+ /* ??? We do want some kind of loop invariant motion, but we possibly
+ need to adjust LIM to be more friendly towards preserving accurate
+ debug information here. */
+ NEXT_PASS (pass_late_warn_uninitialized);
+ NEXT_PASS (pass_uncprop);
+ NEXT_PASS (pass_local_pure_const);
+ }
NEXT_PASS (pass_tm_init);
{
struct opt_pass **p = &pass_tm_init.pass.sub;
Index: trunk/gcc/testsuite/lib/c-torture.exp
===================================================================
*** trunk.orig/gcc/testsuite/lib/c-torture.exp 2011-10-24 10:18:31.000000000 +0200
--- trunk/gcc/testsuite/lib/c-torture.exp 2012-08-10 12:27:25.494062458 +0200
*************** if [info exists TORTURE_OPTIONS] {
*** 42,48 ****
{ -O3 -fomit-frame-pointer -funroll-loops } \
{ -O3 -fomit-frame-pointer -funroll-all-loops -finline-functions } \
{ -O3 -g } \
! { -Os } ]
}
if [info exists ADDITIONAL_TORTURE_OPTIONS] {
--- 42,49 ----
{ -O3 -fomit-frame-pointer -funroll-loops } \
{ -O3 -fomit-frame-pointer -funroll-all-loops -finline-functions } \
{ -O3 -g } \
! { -Os } \
! { -Og -g } ]
}
if [info exists ADDITIONAL_TORTURE_OPTIONS] {
Index: trunk/gcc/doc/invoke.texi
===================================================================
*** trunk.orig/gcc/doc/invoke.texi 2012-08-06 12:36:44.000000000 +0200
--- trunk/gcc/doc/invoke.texi 2012-08-10 13:18:40.760955978 +0200
*************** Objective-C and Objective-C++ Dialects}.
*** 422,428 ****
-fvariable-expansion-in-unroller -fvect-cost-model -fvpt -fweb @gol
-fwhole-program -fwpa -fuse-linker-plugin @gol
--param @var{name}=@var{value}
! -O -O0 -O1 -O2 -O3 -Os -Ofast}
@item Preprocessor Options
@xref{Preprocessor Options,,Options Controlling the Preprocessor}.
--- 422,428 ----
-fvariable-expansion-in-unroller -fvect-cost-model -fvpt -fweb @gol
-fwhole-program -fwpa -fuse-linker-plugin @gol
--param @var{name}=@var{value}
! -O -O0 -O1 -O2 -O3 -Os -Ofast -Og}
@item Preprocessor Options
@xref{Preprocessor Options,,Options Controlling the Preprocessor}.
*************** valid for all standard compliant program
*** 6344,6349 ****
--- 6344,6357 ----
It turns on @option{-ffast-math} and the Fortran-specific
@option{-fno-protect-parens} and @option{-fstack-arrays}.
+ @item -Og
+ @opindex Og
+ Optimize debugging experience. @option{-Og} enables optimizations
+ that do not interfere with debugging. It should be the optimization
+ level of choice for the standard edit-compile-debug cycle, offering
+ a reasonable level of optimization while maintaining fast compilation
+ and a good debugging experience.
+
If you use multiple @option{-O} options, with or without level numbers,
the last such option is the one that is effective.
@end table
Index: trunk/gcc/common/common-target.h
===================================================================
*** trunk.orig/gcc/common/common-target.h 2011-06-15 13:26:57.000000000 +0200
--- trunk/gcc/common/common-target.h 2012-08-10 13:35:25.962921178 +0200
*************** enum opt_levels
*** 33,42 ****
OPT_LEVELS_ALL, /* All levels (used by targets to disable options
enabled in target-independent code). */
OPT_LEVELS_0_ONLY, /* -O0 only. */
! OPT_LEVELS_1_PLUS, /* -O1 and above, including -Os. */
! OPT_LEVELS_1_PLUS_SPEED_ONLY, /* -O1 and above, but not -Os. */
OPT_LEVELS_2_PLUS, /* -O2 and above, including -Os. */
! OPT_LEVELS_2_PLUS_SPEED_ONLY, /* -O2 and above, but not -Os. */
OPT_LEVELS_3_PLUS, /* -O3 and above. */
OPT_LEVELS_3_PLUS_AND_SIZE, /* -O3 and above and -Os. */
OPT_LEVELS_SIZE, /* -Os only. */
--- 33,43 ----
OPT_LEVELS_ALL, /* All levels (used by targets to disable options
enabled in target-independent code). */
OPT_LEVELS_0_ONLY, /* -O0 only. */
! OPT_LEVELS_1_PLUS, /* -O1 and above, including -Os and -Og. */
! OPT_LEVELS_1_PLUS_SPEED_ONLY, /* -O1 and above, but not -Os or -Og. */
! OPT_LEVELS_1_PLUS_NOT_DEBUG, /* -O1 and above, but not -Og. */
OPT_LEVELS_2_PLUS, /* -O2 and above, including -Os. */
! OPT_LEVELS_2_PLUS_SPEED_ONLY, /* -O2 and above, but not -Os or -Og. */
OPT_LEVELS_3_PLUS, /* -O3 and above. */
OPT_LEVELS_3_PLUS_AND_SIZE, /* -O3 and above and -Os. */
OPT_LEVELS_SIZE, /* -Os only. */