diff mbox

Fix PR middle-end/53590

Message ID 201206131206.04396.ebotcazou@adacore.com
State New
Headers show

Commit Message

Eric Botcazou June 13, 2012, 10:06 a.m. UTC
This PR is about straight-line code not being as much vectorized in Ada as in C 
or C++.  The problem stems from the very conservative semantics implemented 
under -fnon-call-exceptions for the sake of Java.  We don't need it in Ada.

Tested on x86_64-suse-linux, OK for the mainline?


2012-06-13  Eric Botcazou  <ebotcazou@adacore.com>

	PR middle-end/53590
	* common.opt (-fdelete-dead-exceptions): New switch.
	* doc/invoke.texi (Optimization Options): Document it.
	* cse.c (insn_live_p): Do not return true for an insn that could throw
	if dead exceptions can be deleted.
	* 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): Do not preserve an insn that could throw if dead
	exceptions can be deleted.
	* 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.

Comments

Richard Biener June 13, 2012, 10:59 a.m. UTC | #1
On Wed, Jun 13, 2012 at 12:06 PM, Eric Botcazou <ebotcazou@adacore.com> wrote:
> This PR is about straight-line code not being as much vectorized in Ada as in C
> or C++.  The problem stems from the very conservative semantics implemented
> under -fnon-call-exceptions for the sake of Java.  We don't need it in Ada.
>
> Tested on x86_64-suse-linux, OK for the mainline?

+@item -fdelete-dead-exceptions
+@opindex fdelete-dead-exceptions
+Assume that statements that may raise exceptions but don't otherwise contribute
+to the execution of the program can be optimized away.
+
+Most languages supporting exceptions disable this option at all levels.
+Otherwise it is enabled at all levels: @option{-O0}, @option{-O1},
+@option{-O2}, @option{-O3}, @option{-Os}.  Passes that use the information
+are enabled independently at different optimization levels.

I would not iterate all optimization levels here (you miss -Ofast), nor mention
them.  Thus, simply

+@item -fdelete-dead-exceptions
+@opindex fdelete-dead-exceptions
+Assume that statements that may raise exceptions but don't otherwise contribute
+to the execution of the program can be optimized away.
+
This flag is set by the frontends according to their language specification.
Passes that cause dead exceptions to be removed are enabled
independently at different optimization levels.

and be done with that.  Btw, what is "doesn't otherwise contribute to
the execution"?
That is, is the Ada equivalent of

 try { a / maybe_zero; } catch (...) { printf ("maybe_zero was zero!"); }

dead code?

Btw, I suppose you need to arrange to properly transfer the flag for LTO
in some way (well, or conservatively not remove dead exceptions at link-time).

Thanks,
Richard.

>
> 2012-06-13  Eric Botcazou  <ebotcazou@adacore.com>
>
>        PR middle-end/53590
>        * common.opt (-fdelete-dead-exceptions): New switch.
>        * doc/invoke.texi (Optimization Options): Document it.
>        * cse.c (insn_live_p): Do not return true for an insn that could throw
>        if dead exceptions can be deleted.
>        * 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): Do not preserve an insn that could throw if dead
>        exceptions can be deleted.
>        * 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.
>
>
> --
> Eric Botcazou
Eric Botcazou June 13, 2012, 11:08 a.m. UTC | #2
> +@item -fdelete-dead-exceptions
> +@opindex fdelete-dead-exceptions
> +Assume that statements that may raise exceptions but don't otherwise
> contribute +to the execution of the program can be optimized away.
> +
> This flag is set by the frontends according to their language
> specification. Passes that cause dead exceptions to be removed are enabled
> independently at different optimization levels.
>
> and be done with that.

OK, will make the change.

> Btw, what is "doesn't otherwise contribute to the execution"?
> That is, is the Ada equivalent of
>
>  try { a / maybe_zero; } catch (...) { printf ("maybe_zero was zero!"); }
>
> dead code?

Essentially, yes.  There is a special permission to optimize it away if the 
result of the division isn't used.

> Btw, I suppose you need to arrange to properly transfer the flag for LTO
> in some way (well, or conservatively not remove dead exceptions at
> link-time).

I can add a flag in 'struct function' next to can_throw_non_call_exceptions.
Richard Biener June 13, 2012, 11:24 a.m. UTC | #3
On Wed, Jun 13, 2012 at 1:08 PM, Eric Botcazou <ebotcazou@adacore.com> wrote:
>> +@item -fdelete-dead-exceptions
>> +@opindex fdelete-dead-exceptions
>> +Assume that statements that may raise exceptions but don't otherwise
>> contribute +to the execution of the program can be optimized away.
>> +
>> This flag is set by the frontends according to their language
>> specification. Passes that cause dead exceptions to be removed are enabled
>> independently at different optimization levels.
>>
>> and be done with that.
>
> OK, will make the change.
>
>> Btw, what is "doesn't otherwise contribute to the execution"?
>> That is, is the Ada equivalent of
>>
>>  try { a / maybe_zero; } catch (...) { printf ("maybe_zero was zero!"); }
>>
>> dead code?
>
> Essentially, yes.  There is a special permission to optimize it away if the
> result of the division isn't used.
>
>> Btw, I suppose you need to arrange to properly transfer the flag for LTO
>> in some way (well, or conservatively not remove dead exceptions at
>> link-time).
>
> I can add a flag in 'struct function' next to can_throw_non_call_exceptions.

Not sure if it's worth it though, is it?  This can be done as a followup anyway.

The patch is otherwise ok.

Thanks,
Richard.

> --
> Eric Botcazou
Eric Botcazou June 13, 2012, 11:32 a.m. UTC | #4
> Not sure if it's worth it though, is it?  This can be done as a followup
> anyway.

If we don't do it, we'll get another PR saying "this works in LTO mode with 
other versions of the Ada compiler" (which is true) so I'll proceed.

> The patch is otherwise ok.

Thanks.
diff mbox

Patch

Index: common.opt
===================================================================
--- common.opt	(revision 188445)
+++ common.opt	(working copy)
@@ -979,6 +987,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) Optimization
+Delete dead statements that may raise exceptions
+
 fdelete-null-pointer-checks
 Common Report Var(flag_delete_null_pointer_checks) Init(1) Optimization
 Delete useless null pointer checks
Index: doc/invoke.texi
===================================================================
--- doc/invoke.texi	(revision 188445)
+++ doc/invoke.texi	(working copy)
@@ -359,7 +359,7 @@  Objective-C and Objective-C++ Dialects}.
 -fcse-follow-jumps -fcse-skip-blocks -fcx-fortran-rules @gol
 -fcx-limited-range @gol
 -fdata-sections -fdce -fdelayed-branch @gol
--fdelete-null-pointer-checks -fdevirtualize -fdse @gol
+-fdelete-dead-exceptions -fdelete-null-pointer-checks -fdevirtualize -fdse @gol
 -fearly-inlining -fipa-sra -fexpensive-optimizations -ffat-lto-objects @gol
 -ffast-math -ffinite-math-only -ffloat-store -fexcess-precision=@var{style} @gol
 -fforward-propagate -ffp-contract=@var{style} -ffunction-sections @gol
@@ -6774,6 +6786,16 @@  branch-less equivalents.
 
 Enabled at levels @option{-O}, @option{-O2}, @option{-O3}, @option{-Os}.
 
+@item -fdelete-dead-exceptions
+@opindex fdelete-dead-exceptions
+Assume that statements that may raise exceptions but don't otherwise contribute
+to the execution of the program can be optimized away.
+
+Most languages supporting exceptions disable this option at all levels.
+Otherwise it is enabled at all levels: @option{-O0}, @option{-O1},
+@option{-O2}, @option{-O3}, @option{-Os}.  Passes that use the information
+are enabled independently at different optimization levels.
+
 @item -fdelete-null-pointer-checks
 @opindex fdelete-null-pointer-checks
 Assume that programs cannot safely dereference null pointers, and that
Index: cse.c
===================================================================
--- cse.c	(revision 188445)
+++ cse.c	(working copy)
@@ -6800,7 +6800,7 @@  static bool
 insn_live_p (rtx insn, int *counts)
 {
   int i;
-  if (insn_could_throw_p (insn))
+  if (!flag_delete_dead_exceptions && insn_could_throw_p (insn))
     return true;
   else if (GET_CODE (PATTERN (insn)) == SET)
     return set_live_p (PATTERN (insn), insn, counts);
Index: dce.c
===================================================================
--- dce.c	(revision 188445)
+++ dce.c	(working copy)
@@ -47,6 +47,9 @@  along with GCC; see the file COPYING3.
    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,10 @@  deletable_insn_p (rtx insn, bool fast, b
   if (!NONJUMP_INSN_P (insn))
     return false;
 
-  /* Don't delete insns that can throw.  */
-  if (!insn_nothrow_p (insn))
+  /* Don't delete insns that can throw if we need to preserve the CFG or
+     statements that may raise exceptions.  */
+  if ((!can_alter_cfg || !flag_delete_dead_exceptions)
+      && !insn_nothrow_p (insn))
     return false;
 
   body = PATTERN (insn);
@@ -711,7 +716,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: dse.c
===================================================================
--- dse.c	(revision 188445)
+++ dse.c	(working copy)
@@ -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)
+      || (!flag_delete_dead_exceptions && insn_could_throw_p (insn))
       || (RTX_FRAME_RELATED_P (insn))
       || find_reg_note (insn, REG_FRAME_RELATED_EXPR, NULL_RTX))
     insn_info->cannot_delete = true;
Index: tree-ssa-dce.c
===================================================================
--- tree-ssa-dce.c	(revision 188445)
+++ tree-ssa-dce.c	(working copy)
@@ -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
+      && !flag_delete_dead_exceptions
+      && stmt_could_throw_p (stmt))
     {
       mark_stmt_necessary (stmt, true);
       return;
Index: ada/gcc-interface/misc.c
===================================================================
--- ada/gcc-interface/misc.c	(revision 188445)
+++ ada/gcc-interface/misc.c	(working copy)
@@ -167,6 +164,9 @@  gnat_init_options_struct (struct gcc_opt
 {
   /* Uninitialized really means uninitialized in Ada.  */
   opts->x_flag_zero_initialized_in_bss = 0;
+
+  /* We can delete dead statements that may raise exceptions in Ada.  */
+  opts->x_flag_delete_dead_exceptions = 1;
 }
 
 /* Initialize for option processing.  */