This adds a new optimization level, -Og, as previously discussed. It aims at providing fast compilation, a superior debugging experience and reasonable runtime performance. Instead of making -O1 this optimization level this adds a new -Og.
It's a first cut, highlighting that our fixed pass pipeline and simply enabling/disabling individual passes (but not pass copies for example) doesn't scale to properly differentiate between -Og and -O[23]. -O1 should get similar treatment, eventually just building on -Og but not focusing on debugging experience. That is, I expect that in the end we will at least have two post-IPA optimization pipelines. It also means that you cannot enable PRE or VRP with -Og at the moment because these passes are not anywhere scheduled (similar to the situation with -O0). It has some funny effect on dump-file naming of the pass copies though, which hints at that the current setup is too static. For that reason the new queue comes after the old, to not confuse too many testcases. It also does not yet disable any of the early optimizations that make debugging harder (SRA comes to my mind here, as does switch-conversion and partial inlining). The question arises if we want to support in any reasonable way using profile-feedback or LTO for -O[01g], thus if we rather want to delay some of the early opts to after IPA optimizations. Not bootstrapped or fully tested, but it works for the compile torture. Comments welcome, Thanks, Richard. 2012-08-10 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 12:48:38.986018411 +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,359 ---- break; case OPT_LEVELS_1_PLUS_SPEED_ONLY: ! enabled = (level >= 1 && !size && !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: --- 361,367 ---- 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, --- 407,413 ---- 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. */ --- 417,424 ---- 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. */ *************** default_options_optimization (struct gcc *** 540,545 **** --- 543,549 ---- 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 **** --- 559,565 ---- 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 **** --- 570,576 ---- /* 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 **** --- 578,592 ---- 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); --- 597,604 ---- 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, --- 628,635 ---- 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 **** --- 1425,1431 ---- 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