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 g...@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 <rguent...@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. */