aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@adacore.com>2012-06-15 09:22:00 +0000
committerEric Botcazou <ebotcazou@gcc.gnu.org>2012-06-15 09:22:00 +0000
commit2da02156af964dbd197f19cbd7fea003a73aacb3 (patch)
tree25c62c51c178ea6a10880eb537b869fdb857970d /gcc
parent6724292e72a9bdbafb0d95587740378f36036707 (diff)
downloadgcc-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/ChangeLog24
-rw-r--r--gcc/ada/ChangeLog6
-rw-r--r--gcc/ada/gcc-interface/misc.c3
-rw-r--r--gcc/common.opt4
-rw-r--r--gcc/cse.c8
-rw-r--r--gcc/dce.c11
-rw-r--r--gcc/doc/invoke.texi10
-rw-r--r--gcc/dse.c2
-rw-r--r--gcc/function.c1
-rw-r--r--gcc/function.h4
-rw-r--r--gcc/lto-streamer-in.c1
-rw-r--r--gcc/lto-streamer-out.c1
-rw-r--r--gcc/tree-ssa-dce.c6
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
diff --git a/gcc/cse.c b/gcc/cse.c
index 783c932..9d5e32e 100644
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -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);
diff --git a/gcc/dce.c b/gcc/dce.c
index 86edea1..8954d5c 100644
--- a/gcc/dce.c
+++ b/gcc/dce.c
@@ -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
diff --git a/gcc/dse.c b/gcc/dse.c
index da52415..0e40c85 100644
--- a/gcc/dse.c
+++ b/gcc/dse.c
@@ -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;