diff options
author | Eric Botcazou <ebotcazou@adacore.com> | 2012-06-15 09:22:00 +0000 |
---|---|---|
committer | Eric Botcazou <ebotcazou@gcc.gnu.org> | 2012-06-15 09:22:00 +0000 |
commit | 2da02156af964dbd197f19cbd7fea003a73aacb3 (patch) | |
tree | 25c62c51c178ea6a10880eb537b869fdb857970d /gcc | |
parent | 6724292e72a9bdbafb0d95587740378f36036707 (diff) | |
download | gcc-2da02156af964dbd197f19cbd7fea003a73aacb3.zip gcc-2da02156af964dbd197f19cbd7fea003a73aacb3.tar.gz gcc-2da02156af964dbd197f19cbd7fea003a73aacb3.tar.bz2 |
re PR middle-end/53590 (compiler fails to generate SIMD instruction for FP division)
PR middle-end/53590
* common.opt (-fdelete-dead-exceptions): New switch.
* doc/invoke.texi (Code Gen Options): Document it.
* cse.c (count_reg_usage) <CALL_INSN>: Use !insn_nothrow_p in lieu of
insn_could_throw_p predicate. Do not skip an insn that could throw
if dead exceptions can be deleted.
(insn_live_p): Likewise, do not return true in that case.
* dce.c (can_alter_cfg): New flag.
(deletable_insn_p): Do not return false for an insn that can throw if
the CFG can be altered and dead exceptions can be deleted.
(init_dce): Set can_alter_cfg to false for fast DCE, true otherwise.
* dse.c (scan_insn): Use !insn_nothrow_p in lieu of insn_could_throw_
predicate. Do not preserve an insn that could throw if dead exceptions
can be deleted.
* function.h (struct function): Add can_delete_dead_exceptions flag.
* function.c (allocate_struct_function): Set it.
* lto-streamer-in.c (input_struct_function_base): Stream it.
* lto-streamer-out.c (input_struct_function_base): Likewise.
* tree-ssa-dce.c (mark_stmt_if_obviously_necessary): Do not mark a
statement that could throw as necessary if dead exceptions can be
deleted.
ada/
* gcc-interface/misc.c (gnat_init_options_struct): Set
opts->x_flag_delete_dead_exceptions to 1.
From-SVN: r188651
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 24 | ||||
-rw-r--r-- | gcc/ada/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/ada/gcc-interface/misc.c | 3 | ||||
-rw-r--r-- | gcc/common.opt | 4 | ||||
-rw-r--r-- | gcc/cse.c | 8 | ||||
-rw-r--r-- | gcc/dce.c | 11 | ||||
-rw-r--r-- | gcc/doc/invoke.texi | 10 | ||||
-rw-r--r-- | gcc/dse.c | 2 | ||||
-rw-r--r-- | gcc/function.c | 1 | ||||
-rw-r--r-- | gcc/function.h | 4 | ||||
-rw-r--r-- | gcc/lto-streamer-in.c | 1 | ||||
-rw-r--r-- | gcc/lto-streamer-out.c | 1 | ||||
-rw-r--r-- | gcc/tree-ssa-dce.c | 6 |
13 files changed, 71 insertions, 10 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e929f2f..0322fbf 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,27 @@ +2012-06-15 Eric Botcazou <ebotcazou@adacore.com> + + PR middle-end/53590 + * common.opt (-fdelete-dead-exceptions): New switch. + * doc/invoke.texi (Code Gen Options): Document it. + * cse.c (count_reg_usage) <CALL_INSN>: Use !insn_nothrow_p in lieu of + insn_could_throw_p predicate. Do not skip an insn that could throw + if dead exceptions can be deleted. + (insn_live_p): Likewise, do not return true in that case. + * dce.c (can_alter_cfg): New flag. + (deletable_insn_p): Do not return false for an insn that can throw if + the CFG can be altered and dead exceptions can be deleted. + (init_dce): Set can_alter_cfg to false for fast DCE, true otherwise. + * dse.c (scan_insn): Use !insn_nothrow_p in lieu of insn_could_throw_ + predicate. Do not preserve an insn that could throw if dead exceptions + can be deleted. + * function.h (struct function): Add can_delete_dead_exceptions flag. + * function.c (allocate_struct_function): Set it. + * lto-streamer-in.c (input_struct_function_base): Stream it. + * lto-streamer-out.c (input_struct_function_base): Likewise. + * tree-ssa-dce.c (mark_stmt_if_obviously_necessary): Do not mark a + statement that could throw as necessary if dead exceptions can be + deleted. + 2012-06-14 Maxim Kuvyrkov <maxim@codesourcery.com> * config/tilegx/sync.md (atomic_fetch_sub<mode>): Fix typo. diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index c2e60dd..d9be5f8 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,9 @@ +2012-06-15 Eric Botcazou <ebotcazou@adacore.com> + + PR middle-end/53590 + * gcc-interface/misc.c (gnat_init_options_struct): Set + opts->x_flag_delete_dead_exceptions to 1. + 2012-06-14 Jose Ruiz <ruiz@adacore.com> * gcc-interface/Make-lang.in (ada.install-common, ada.uninstall): diff --git a/gcc/ada/gcc-interface/misc.c b/gcc/ada/gcc-interface/misc.c index 6d77dc8..baa44c9 100644 --- a/gcc/ada/gcc-interface/misc.c +++ b/gcc/ada/gcc-interface/misc.c @@ -167,6 +167,9 @@ gnat_init_options_struct (struct gcc_options *opts) { /* Uninitialized really means uninitialized in Ada. */ opts->x_flag_zero_initialized_in_bss = 0; + + /* We can delete dead instructions that may throw exceptions in Ada. */ + opts->x_flag_delete_dead_exceptions = 1; } /* Initialize for option processing. */ diff --git a/gcc/common.opt b/gcc/common.opt index 5b1b4d8..2a14f18 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -979,6 +979,10 @@ fdelayed-branch Common Report Var(flag_delayed_branch) Optimization Attempt to fill delay slots of branch instructions +fdelete-dead-exceptions +Common Report Var(flag_delete_dead_exceptions) Init(0) +Delete dead instructions that may throw exceptions + fdelete-null-pointer-checks Common Report Var(flag_delete_null_pointer_checks) Init(1) Optimization Delete useless null pointer checks @@ -599,7 +599,6 @@ static void invalidate_from_clobbers (rtx); static void invalidate_from_sets_and_clobbers (rtx); static rtx cse_process_notes (rtx, rtx, bool *); static void cse_extended_basic_block (struct cse_basic_block_data *); -static void count_reg_usage (rtx, int *, rtx, int); static int check_for_label_ref (rtx *, void *); extern void dump_class (struct table_elt*); static void get_cse_reg_info_1 (unsigned int regno); @@ -6692,10 +6691,11 @@ count_reg_usage (rtx x, int *counts, rtx dest, int incr) case CALL_INSN: case INSN: case JUMP_INSN: - /* We expect dest to be NULL_RTX here. If the insn may trap, + /* We expect dest to be NULL_RTX here. If the insn may throw, or if it cannot be deleted due to side-effects, mark this fact by setting DEST to pc_rtx. */ - if (insn_could_throw_p (x) || side_effects_p (PATTERN (x))) + if ((!cfun->can_delete_dead_exceptions && !insn_nothrow_p (x)) + || side_effects_p (PATTERN (x))) dest = pc_rtx; if (code == CALL_INSN) count_reg_usage (CALL_INSN_FUNCTION_USAGE (x), counts, dest, incr); @@ -6800,7 +6800,7 @@ static bool insn_live_p (rtx insn, int *counts) { int i; - if (insn_could_throw_p (insn)) + if (!cfun->can_delete_dead_exceptions && !insn_nothrow_p (insn)) return true; else if (GET_CODE (PATTERN (insn)) == SET) return set_live_p (PATTERN (insn), insn, counts); @@ -47,6 +47,9 @@ along with GCC; see the file COPYING3. If not see we don't want to reenter it. */ static bool df_in_progress = false; +/* True if we are allowed to alter the CFG in this pass. */ +static bool can_alter_cfg = false; + /* Instructions that have been marked but whose dependencies have not yet been processed. */ static VEC(rtx,heap) *worklist; @@ -113,8 +116,9 @@ deletable_insn_p (rtx insn, bool fast, bitmap arg_stores) if (!NONJUMP_INSN_P (insn)) return false; - /* Don't delete insns that can throw. */ - if (!insn_nothrow_p (insn)) + /* Don't delete insns that may throw if we cannot do so. */ + if (!(cfun->can_delete_dead_exceptions && can_alter_cfg) + && !insn_nothrow_p (insn)) return false; body = PATTERN (insn); @@ -711,7 +715,10 @@ init_dce (bool fast) { bitmap_obstack_initialize (&dce_blocks_bitmap_obstack); bitmap_obstack_initialize (&dce_tmp_bitmap_obstack); + can_alter_cfg = false; } + else + can_alter_cfg = true; marked = sbitmap_alloc (get_max_uid () + 1); sbitmap_zero (marked); diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 9fa0085..b74f9ab 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -975,7 +975,7 @@ See S/390 and zSeries Options. @xref{Code Gen Options,,Options for Code Generation Conventions}. @gccoptlist{-fcall-saved-@var{reg} -fcall-used-@var{reg} @gol -ffixed-@var{reg} -fexceptions @gol --fnon-call-exceptions -funwind-tables @gol +-fnon-call-exceptions -fdelete-dead-exceptions -funwind-tables @gol -fasynchronous-unwind-tables @gol -finhibit-size-directive -finstrument-functions @gol -finstrument-functions-exclude-function-list=@var{sym},@var{sym},@dots{} @gol @@ -19317,6 +19317,14 @@ instructions to throw exceptions, i.e.@: memory references or floating-point instructions. It does not allow exceptions to be thrown from arbitrary signal handlers such as @code{SIGALRM}. +@item -fdelete-dead-exceptions +@opindex fdelete-dead-exceptions +Consider that instructions that may throw exceptions but don't otherwise +contribute to the execution of the program can be optimized away. +This option is enabled by default for the Ada front end, as permitted by +the Ada language specification. +Optimization passes that cause dead exceptions to be removed are enabled independently at different optimization levels. + @item -funwind-tables @opindex funwind-tables Similar to @option{-fexceptions}, except that it just generates any needed @@ -2628,7 +2628,7 @@ scan_insn (bb_info_t bb_info, rtx insn) them. */ if ((GET_CODE (PATTERN (insn)) == CLOBBER) || volatile_refs_p (PATTERN (insn)) - || insn_could_throw_p (insn) + || (!cfun->can_delete_dead_exceptions && !insn_nothrow_p (insn)) || (RTX_FRAME_RELATED_P (insn)) || find_reg_note (insn, REG_FRAME_RELATED_EXPR, NULL_RTX)) insn_info->cannot_delete = true; diff --git a/gcc/function.c b/gcc/function.c index 274d421..9e79bcd 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -4496,6 +4496,7 @@ allocate_struct_function (tree fndecl, bool abstract_p) /* ??? This could be set on a per-function basis by the front-end but is this worth the hassle? */ cfun->can_throw_non_call_exceptions = flag_non_call_exceptions; + cfun->can_delete_dead_exceptions = flag_delete_dead_exceptions; } } diff --git a/gcc/function.h b/gcc/function.h index c8357bf..f2fb099 100644 --- a/gcc/function.h +++ b/gcc/function.h @@ -615,6 +615,10 @@ struct GTY(()) function { exceptions. */ unsigned int can_throw_non_call_exceptions : 1; + /* Nonzero if instructions that may throw exceptions but don't otherwise + contribute to the execution of the program can be deleted. */ + unsigned int can_delete_dead_exceptions : 1; + /* Fields below this point are not set for abstract functions; see allocate_struct_function. */ diff --git a/gcc/lto-streamer-in.c b/gcc/lto-streamer-in.c index ddb91d8..9839094 100644 --- a/gcc/lto-streamer-in.c +++ b/gcc/lto-streamer-in.c @@ -803,6 +803,7 @@ input_struct_function_base (struct function *fn, struct data_in *data_in, fn->returns_pcc_struct = bp_unpack_value (&bp, 1); fn->returns_struct = bp_unpack_value (&bp, 1); fn->can_throw_non_call_exceptions = bp_unpack_value (&bp, 1); + fn->can_delete_dead_exceptions = bp_unpack_value (&bp, 1); fn->always_inline_functions_inlined = bp_unpack_value (&bp, 1); fn->after_inlining = bp_unpack_value (&bp, 1); fn->stdarg = bp_unpack_value (&bp, 1); diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c index 7f12e1c..370bf0a 100644 --- a/gcc/lto-streamer-out.c +++ b/gcc/lto-streamer-out.c @@ -761,6 +761,7 @@ output_struct_function_base (struct output_block *ob, struct function *fn) bp_pack_value (&bp, fn->returns_pcc_struct, 1); bp_pack_value (&bp, fn->returns_struct, 1); bp_pack_value (&bp, fn->can_throw_non_call_exceptions, 1); + bp_pack_value (&bp, fn->can_delete_dead_exceptions, 1); bp_pack_value (&bp, fn->always_inline_functions_inlined, 1); bp_pack_value (&bp, fn->after_inlining, 1); bp_pack_value (&bp, fn->stdarg, 1); diff --git a/gcc/tree-ssa-dce.c b/gcc/tree-ssa-dce.c index 1d72e06..8763cfb 100644 --- a/gcc/tree-ssa-dce.c +++ b/gcc/tree-ssa-dce.c @@ -272,8 +272,10 @@ static void mark_stmt_if_obviously_necessary (gimple stmt, bool aggressive) { /* With non-call exceptions, we have to assume that all statements could - throw. If a statement may throw, it is inherently necessary. */ - if (cfun->can_throw_non_call_exceptions && stmt_could_throw_p (stmt)) + throw. If a statement could throw, it can be deemed necessary. */ + if (cfun->can_throw_non_call_exceptions + && !cfun->can_delete_dead_exceptions + && stmt_could_throw_p (stmt)) { mark_stmt_necessary (stmt, true); return; |