re PR middle-end/53590 (compiler fails to generate SIMD instruction for FP division)
authorEric Botcazou <ebotcazou@adacore.com>
Fri, 15 Jun 2012 09:22:00 +0000 (09:22 +0000)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Fri, 15 Jun 2012 09:22:00 +0000 (09:22 +0000)
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

13 files changed:
gcc/ChangeLog
gcc/ada/ChangeLog
gcc/ada/gcc-interface/misc.c
gcc/common.opt
gcc/cse.c
gcc/dce.c
gcc/doc/invoke.texi
gcc/dse.c
gcc/function.c
gcc/function.h
gcc/lto-streamer-in.c
gcc/lto-streamer-out.c
gcc/tree-ssa-dce.c

index e929f2fa249ee392eb8405f494be5dd3b5238c90..0322fbf9f428aa0985ab32f01e612fe84fe89587 100644 (file)
@@ -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.
index c2e60dd85918ae64a4e871376641b9f0cdcb334c..d9be5f8e1cbe71a5bda4513a8b2847897440620a 100644 (file)
@@ -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):
index 6d77dc804aff7f020dbeccc5cfefdff4543df294..baa44c95be7d14530bcaf4d65c92c8691c7108e3 100644 (file)
@@ -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.  */
index 5b1b4d8eea3f7c7faf930d5c43a5c788de7c4af9..2a14f18909739b5f2a4e9eb240e1623abbc35230 100644 (file)
@@ -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
index 783c932aed01de3c1b949a0298425da2d490fa0a..9d5e32eee39d00733e4a08e08f7ebdd0804ef009 100644 (file)
--- 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);
index 86edea11c55602180116ef4b1846ece2fea7f3a0..8954d5c0c01fd188eee894606c11d53f286f1201 100644 (file)
--- 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);
index 9fa0085ce39d733ef0b4e6607f50f50aca10288e..b74f9abd7d9ab57f38cf764f5fe4f47ebfbff02d 100644 (file)
@@ -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
index da52415083ea1d3dd84a2b268278e0358a20e64a..0e40c8539cfd8e601b08e2a938d623f134650e09 100644 (file)
--- 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;
index 274d42191cb43b412883172f9d393bdc8925d1df..9e79bcd83336f2a8e4b0bb8c83c14af379e5e78f 100644 (file)
@@ -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;
     }
 }
 
index c8357bf5ee0fa6c159896fc4e076f609200da34c..f2fb099ea01e8c3b84ca90cf2e3a0cdacec3856a 100644 (file)
@@ -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.  */
 
index ddb91d8557c5257812d333762a1f95e788c8a880..98390940f1229d91d3249fb215cf5284b327f404 100644 (file)
@@ -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);
index 7f12e1c56b15a80891977cb3f53003c2dd36463c..370bf0a7ae80c40683a9b45dea48d12ceed1be15 100644 (file)
@@ -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);
index 1d72e06fe7697652848857707f74786b70cc7394..8763cfb28d2b8ded3aff1c65c06a1ab36c68ac92 100644 (file)
@@ -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;