gimple-low.c (struct lower_data): Add cannot_fallthru field.

* gimple-low.c (struct lower_data): Add cannot_fallthru field.
	(lower_stmt) <GIMPLE_BIND>: Add comment.
	<GIMPLE_COND, GIMPLE_GOTO, GIMPLE_SWITCH>: Set cannot_fallthru to true
	and return.
	<GIMPLE_RETURN>: Remove the statement if cannot_fallthru is set.
	Otherwise lower it and set cannot_fallthru to true.
	<GIMPLE_TRY>: Update cannot_fallthru for GIMPLE_TRY_FINALLY and return.
	<GIMPLE_CATCH, GIMPLE_EH_FILTER>; Set cannot_fallthru to false.
	<GIMPLE_CALL>: Set cannot_fallthru to false for BUILT_IN_SETJMP and
	to true for a noreturn call.  Do not remove statements.
	<GIMPLE_OMP_PARALLEL, GIMPLE_OMP_TASK>: Set cannot_fallthru to false.
	Set cannot_fallthru to false on function exit.
	(gimple_stmt_may_fallthru) <GIMPLE_SWITCH>: Really return false.
	<GIMPLE_ASSIGN>: Remove.

From-SVN: r152984
This commit is contained in:
Eric Botcazou 2009-10-19 18:15:49 +00:00 committed by Eric Botcazou
parent 585ba38fd5
commit a141816c42
5 changed files with 104 additions and 24 deletions

View File

@ -1,3 +1,20 @@
2009-10-19 Eric Botcazou <ebotcazou@adacore.com>
* gimple-low.c (struct lower_data): Add cannot_fallthru field.
(lower_stmt) <GIMPLE_BIND>: Add comment.
<GIMPLE_COND, GIMPLE_GOTO, GIMPLE_SWITCH>: Set cannot_fallthru to true
and return.
<GIMPLE_RETURN>: Remove the statement if cannot_fallthru is set.
Otherwise lower it and set cannot_fallthru to true.
<GIMPLE_TRY>: Update cannot_fallthru for GIMPLE_TRY_FINALLY and return.
<GIMPLE_CATCH, GIMPLE_EH_FILTER>; Set cannot_fallthru to false.
<GIMPLE_CALL>: Set cannot_fallthru to false for BUILT_IN_SETJMP and
to true for a noreturn call. Do not remove statements.
<GIMPLE_OMP_PARALLEL, GIMPLE_OMP_TASK>: Set cannot_fallthru to false.
Set cannot_fallthru to false on function exit.
(gimple_stmt_may_fallthru) <GIMPLE_SWITCH>: Really return false.
<GIMPLE_ASSIGN>: Remove.
2009-10-19 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
* config/s390/s390.c (s390_z10_optimize_cmp): Don't touch FP compares.

View File

@ -76,6 +76,9 @@ struct lower_data
of the function. */
VEC(return_statements_t,heap) *return_statements;
/* True if the current statement cannot fall through. */
bool cannot_fallthru;
/* True if the function calls __builtin_setjmp. */
bool calls_builtin_setjmp;
};
@ -317,7 +320,12 @@ lower_omp_directive (gimple_stmt_iterator *gsi, struct lower_data *data)
}
/* Lower statement GSI. DATA is passed through the recursion. */
/* Lower statement GSI. DATA is passed through the recursion. We try to
track the fallthruness of statements and get rid of unreachable return
statements in order to prevent the EH lowering pass from adding useless
edges that can cause bogus warnings to be issued later; this guess need
not be 100% accurate, simply be conservative and reset cannot_fallthru
to false if we don't know. */
static void
lower_stmt (gimple_stmt_iterator *gsi, struct lower_data *data)
@ -330,36 +338,61 @@ lower_stmt (gimple_stmt_iterator *gsi, struct lower_data *data)
{
case GIMPLE_BIND:
lower_gimple_bind (gsi, data);
/* Propagate fallthruness. */
return;
case GIMPLE_COND:
/* The gimplifier has already lowered this into gotos. */
break;
case GIMPLE_GOTO:
case GIMPLE_SWITCH:
data->cannot_fallthru = true;
gsi_next (gsi);
return;
case GIMPLE_RETURN:
lower_gimple_return (gsi, data);
if (data->cannot_fallthru)
{
gsi_remove (gsi, false);
/* Propagate fallthruness. */
}
else
{
lower_gimple_return (gsi, data);
data->cannot_fallthru = true;
}
return;
case GIMPLE_TRY:
lower_sequence (gimple_try_eval (stmt), data);
lower_sequence (gimple_try_cleanup (stmt), data);
{
bool try_cannot_fallthru;
lower_sequence (gimple_try_eval (stmt), data);
try_cannot_fallthru = data->cannot_fallthru;
data->cannot_fallthru = false;
lower_sequence (gimple_try_cleanup (stmt), data);
/* See gimple_stmt_may_fallthru for the rationale. */
if (gimple_try_kind (stmt) == GIMPLE_TRY_FINALLY)
{
data->cannot_fallthru |= try_cannot_fallthru;
gsi_next (gsi);
return;
}
}
break;
case GIMPLE_CATCH:
data->cannot_fallthru = false;
lower_sequence (gimple_catch_handler (stmt), data);
break;
case GIMPLE_EH_FILTER:
data->cannot_fallthru = false;
lower_sequence (gimple_eh_filter_failure (stmt), data);
break;
case GIMPLE_NOP:
case GIMPLE_ASM:
case GIMPLE_ASSIGN:
case GIMPLE_GOTO:
case GIMPLE_PREDICT:
case GIMPLE_LABEL:
case GIMPLE_SWITCH:
case GIMPLE_EH_MUST_NOT_THROW:
case GIMPLE_OMP_FOR:
case GIMPLE_OMP_SECTIONS:
@ -383,21 +416,16 @@ lower_stmt (gimple_stmt_iterator *gsi, struct lower_data *data)
&& DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL
&& DECL_FUNCTION_CODE (decl) == BUILT_IN_SETJMP)
{
data->calls_builtin_setjmp = true;
lower_builtin_setjmp (gsi);
data->cannot_fallthru = false;
data->calls_builtin_setjmp = true;
return;
}
/* After a noreturn call, remove a subsequent GOTO or RETURN that might
have been mechanically added; this will prevent the EH lowering pass
from adding useless edges and thus complicating the initial CFG. */
if (decl && (flags_from_decl_or_type (decl) & ECF_NORETURN))
{
data->cannot_fallthru = true;
gsi_next (gsi);
if (!gsi_end_p (*gsi)
&& (gimple_code (gsi_stmt (*gsi)) == GIMPLE_GOTO
|| gimple_code (gsi_stmt (*gsi)) == GIMPLE_RETURN))
gsi_remove (gsi, false);
return;
}
}
@ -405,13 +433,16 @@ lower_stmt (gimple_stmt_iterator *gsi, struct lower_data *data)
case GIMPLE_OMP_PARALLEL:
case GIMPLE_OMP_TASK:
data->cannot_fallthru = false;
lower_omp_directive (gsi, data);
data->cannot_fallthru = false;
return;
default:
gcc_unreachable ();
}
data->cannot_fallthru = false;
gsi_next (gsi);
}
@ -660,9 +691,9 @@ gimple_stmt_may_fallthru (gimple stmt)
return false;
case GIMPLE_SWITCH:
/* Switch has already been lowered and represents a
branch to a selected label and hence can not fall through. */
return true;
/* Switch has already been lowered and represents a branch
to a selected label and hence can't fall through. */
return false;
case GIMPLE_COND:
/* GIMPLE_COND's are already lowered into a two-way branch. They
@ -688,13 +719,10 @@ gimple_stmt_may_fallthru (gimple stmt)
return (gimple_seq_may_fallthru (gimple_try_eval (stmt))
&& gimple_seq_may_fallthru (gimple_try_cleanup (stmt)));
case GIMPLE_ASSIGN:
return true;
case GIMPLE_CALL:
/* Functions that do not return do not fall through. */
return (gimple_call_flags (stmt) & ECF_NORETURN) == 0;
default:
return true;
}
@ -744,7 +772,7 @@ lower_gimple_return (gimple_stmt_iterator *gsi, struct lower_data *data)
gsi_remove (gsi, false);
}
/* Lower a __builtin_setjmp TSI.
/* Lower a __builtin_setjmp GSI.
__builtin_setjmp is passed a pointer to an array of five words (not
all will be used on all machines). It operates similarly to the C

View File

@ -1,3 +1,7 @@
2009-10-19 Eric Botcazou <ebotcazou@adacore.com>
* gnat.dg/noreturn2.ad[sb]: New test.
2009-10-19 Tobias Burnus <burnus@net-b.de>
PR fortran/41755

View File

@ -0,0 +1,23 @@
-- { dg-do compile }
package body Noreturn2 is
procedure Raise_Exception_No_Defer (Message : String);
pragma No_Return (Raise_Exception_No_Defer);
procedure Raise_From (X : Exception_Occurrence) is
Occurrence_Message : constant String := Exception_Message (X);
begin
if Occurrence_Message = "$" then
Raise_Exception_No_Defer (Occurrence_Message);
else
Raise_Exception_No_Defer ("::" & Occurrence_Message);
end if;
end;
procedure Raise_Exception_No_Defer (Message : String) is
begin
raise Program_Error;
end;
end Noreturn2;

View File

@ -0,0 +1,8 @@
with Ada.Exceptions; use Ada.Exceptions;
package Noreturn2 is
procedure Raise_From (X : Exception_Occurrence);
pragma No_Return (Raise_From);
end Noreturn2;