Commit 80096613 by Eric Botcazou Committed by Eric Botcazou

trans.c (Loop_Statement_to_gnu): Also handle invariant conditions with only one bound.

	* gcc-interface/trans.c (Loop_Statement_to_gnu): Also handle invariant
	conditions with only one bound.
	(Raise_Error_to_gnu): Likewise.  New function extracted from...
	(gnat_to_gnu) <N_Raise_Constraint_Error>: ...here.  Call above function
	in regular mode only.

From-SVN: r187208
parent 1a5b6cd2
2012-05-06 Eric Botcazou <ebotcazou@adacore.com> 2012-05-06 Eric Botcazou <ebotcazou@adacore.com>
* gcc-interface/trans.c (Loop_Statement_to_gnu): Also handle invariant
conditions with only one bound.
(Raise_Error_to_gnu): Likewise.  New function extracted from...
(gnat_to_gnu) <N_Raise_Constraint_Error>: ...here.  Call above function
in regular mode only.
2012-05-06 Eric Botcazou <ebotcazou@adacore.com>
* gcc-interface/misc.c (gnat_post_options): Disable caret by default. * gcc-interface/misc.c (gnat_post_options): Disable caret by default.
2012-05-06 Eric Botcazou <ebotcazou@adacore.com> 2012-05-06 Eric Botcazou <ebotcazou@adacore.com>
......
...@@ -2563,13 +2563,19 @@ Loop_Statement_to_gnu (Node_Id gnat_node) ...@@ -2563,13 +2563,19 @@ Loop_Statement_to_gnu (Node_Id gnat_node)
i++) i++)
{ {
tree low_ok tree low_ok
= build_binary_op (GE_EXPR, boolean_type_node, = rci->low_bound
convert (rci->type, gnu_low), ? build_binary_op (GE_EXPR, boolean_type_node,
rci->low_bound); convert (rci->type, gnu_low),
rci->low_bound)
: boolean_true_node;
tree high_ok tree high_ok
= build_binary_op (LE_EXPR, boolean_type_node, = rci->high_bound
convert (rci->type, gnu_high), ? build_binary_op (LE_EXPR, boolean_type_node,
rci->high_bound); convert (rci->type, gnu_high),
rci->high_bound)
: boolean_true_node;
tree range_ok tree range_ok
= build_binary_op (TRUTH_ANDIF_EXPR, boolean_type_node, = build_binary_op (TRUTH_ANDIF_EXPR, boolean_type_node,
low_ok, high_ok); low_ok, high_ok);
...@@ -2794,7 +2800,7 @@ finalize_nrv_r (tree *tp, int *walk_subtrees, void *data) ...@@ -2794,7 +2800,7 @@ finalize_nrv_r (tree *tp, int *walk_subtrees, void *data)
tree ret_val = TREE_OPERAND (TREE_OPERAND (t, 0), 1), init_expr; tree ret_val = TREE_OPERAND (TREE_OPERAND (t, 0), 1), init_expr;
/* If this is the temporary created for a return value with variable /* If this is the temporary created for a return value with variable
size in call_to_gnu, we replace the RHS with the init expression. */ size in Call_to_gnu, we replace the RHS with the init expression. */
if (TREE_CODE (ret_val) == COMPOUND_EXPR if (TREE_CODE (ret_val) == COMPOUND_EXPR
&& TREE_CODE (TREE_OPERAND (ret_val, 0)) == INIT_EXPR && TREE_CODE (TREE_OPERAND (ret_val, 0)) == INIT_EXPR
&& TREE_OPERAND (TREE_OPERAND (ret_val, 0), 0) && TREE_OPERAND (TREE_OPERAND (ret_val, 0), 0)
...@@ -3122,7 +3128,7 @@ build_return_expr (tree ret_obj, tree ret_val) ...@@ -3122,7 +3128,7 @@ build_return_expr (tree ret_obj, tree ret_val)
&& aggregate_value_p (operation_type, current_function_decl)) && aggregate_value_p (operation_type, current_function_decl))
{ {
/* Recognize the temporary created for a return value with variable /* Recognize the temporary created for a return value with variable
size in call_to_gnu. We want to eliminate it if possible. */ size in Call_to_gnu. We want to eliminate it if possible. */
if (TREE_CODE (ret_val) == COMPOUND_EXPR if (TREE_CODE (ret_val) == COMPOUND_EXPR
&& TREE_CODE (TREE_OPERAND (ret_val, 0)) == INIT_EXPR && TREE_CODE (TREE_OPERAND (ret_val, 0)) == INIT_EXPR
&& TREE_OPERAND (TREE_OPERAND (ret_val, 0), 0) && TREE_OPERAND (TREE_OPERAND (ret_val, 0), 0)
...@@ -3583,7 +3589,7 @@ create_init_temporary (const char *prefix, tree gnu_init, tree *gnu_init_stmt, ...@@ -3583,7 +3589,7 @@ create_init_temporary (const char *prefix, tree gnu_init, tree *gnu_init_stmt,
requires atomic synchronization. */ requires atomic synchronization. */
static tree static tree
call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target, Call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target,
bool atomic_sync) bool atomic_sync)
{ {
const bool function_call = (Nkind (gnat_node) == N_Function_Call); const bool function_call = (Nkind (gnat_node) == N_Function_Call);
...@@ -4751,6 +4757,134 @@ Compilation_Unit_to_gnu (Node_Id gnat_node) ...@@ -4751,6 +4757,134 @@ Compilation_Unit_to_gnu (Node_Id gnat_node)
invalidate_global_renaming_pointers (); invalidate_global_renaming_pointers ();
} }
/* Subroutine of gnat_to_gnu to translate gnat_node, an N_Raise_xxx_Error,
to a GCC tree, which is returned. GNU_RESULT_TYPE_P is a pointer to where
we should place the result type. LABEL_P is true if there is a label to
branch to for the exception. */
static tree
Raise_Error_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p)
{
const Node_Kind kind = Nkind (gnat_node);
const int reason = UI_To_Int (Reason (gnat_node));
const Node_Id gnat_cond = Condition (gnat_node);
const bool with_extra_info
= Exception_Extra_Info
&& !No_Exception_Handlers_Set ()
&& !get_exception_label (kind);
tree gnu_result = NULL_TREE, gnu_cond = NULL_TREE;
*gnu_result_type_p = get_unpadded_type (Etype (gnat_node));
switch (reason)
{
case CE_Access_Check_Failed:
if (with_extra_info)
gnu_result = build_call_raise_column (reason, gnat_node);
break;
case CE_Index_Check_Failed:
case CE_Range_Check_Failed:
case CE_Invalid_Data:
if (Present (gnat_cond) && Nkind (gnat_cond) == N_Op_Not)
{
Node_Id gnat_range, gnat_index, gnat_type;
tree gnu_index, gnu_low_bound, gnu_high_bound;
struct range_check_info_d *rci;
switch (Nkind (Right_Opnd (gnat_cond)))
{
case N_In:
gnat_range = Right_Opnd (Right_Opnd (gnat_cond));
gcc_assert (Nkind (gnat_range) == N_Range);
gnu_low_bound = gnat_to_gnu (Low_Bound (gnat_range));
gnu_high_bound = gnat_to_gnu (High_Bound (gnat_range));
break;
case N_Op_Ge:
gnu_low_bound = gnat_to_gnu (Right_Opnd (Right_Opnd (gnat_cond)));
gnu_high_bound = NULL_TREE;
break;
case N_Op_Le:
gnu_low_bound = NULL_TREE;
gnu_high_bound = gnat_to_gnu (Right_Opnd (Right_Opnd (gnat_cond)));
break;
default:
goto common;
}
gnat_index = Left_Opnd (Right_Opnd (gnat_cond));
gnat_type = Etype (gnat_index);
gnu_index = gnat_to_gnu (gnat_index);
if (with_extra_info
&& gnu_low_bound
&& gnu_high_bound
&& Known_Esize (gnat_type)
&& UI_To_Int (Esize (gnat_type)) <= 32)
gnu_result
= build_call_raise_range (reason, gnat_node, gnu_index,
gnu_low_bound, gnu_high_bound);
/* If loop unswitching is enabled, we try to compute invariant
conditions for checks applied to iteration variables, i.e.
conditions that are both independent of the variable and
necessary in order for the check to fail in the course of
some iteration, and prepend them to the original condition
of the checks. This will make it possible later for the
loop unswitching pass to replace the loop with two loops,
one of which has the checks eliminated and the other has
the original checks reinstated, and a run time selection.
The former loop will be suitable for vectorization. */
if (flag_unswitch_loops
&& (!gnu_low_bound
|| (gnu_low_bound = gnat_invariant_expr (gnu_low_bound)))
&& (!gnu_high_bound
|| (gnu_high_bound = gnat_invariant_expr (gnu_high_bound)))
&& (rci = push_range_check_info (gnu_index)))
{
rci->low_bound = gnu_low_bound;
rci->high_bound = gnu_high_bound;
rci->type = gnat_to_gnu_type (gnat_type);
rci->invariant_cond = build1 (SAVE_EXPR, boolean_type_node,
boolean_true_node);
gnu_cond = build_binary_op (TRUTH_ANDIF_EXPR,
boolean_type_node,
rci->invariant_cond,
gnat_to_gnu (gnat_cond));
}
}
break;
default:
break;
}
common:
if (!gnu_result)
gnu_result = build_call_raise (reason, gnat_node, kind);
set_expr_location_from_node (gnu_result, gnat_node);
/* If the type is VOID, this is a statement, so we need to generate the code
for the call. Handle a condition, if there is one. */
if (VOID_TYPE_P (*gnu_result_type_p))
{
if (Present (gnat_cond))
{
if (!gnu_cond)
gnu_cond = gnat_to_gnu (gnat_cond);
gnu_result = build3 (COND_EXPR, void_type_node, gnu_cond, gnu_result,
alloc_stmt_list ());
}
}
else
gnu_result = build1 (NULL_EXPR, *gnu_result_type_p, gnu_result);
return gnu_result;
}
/* Return true if GNAT_NODE is on the LHS of an assignment or an actual /* Return true if GNAT_NODE is on the LHS of an assignment or an actual
parameter of a call. */ parameter of a call. */
...@@ -5949,7 +6083,7 @@ gnat_to_gnu (Node_Id gnat_node) ...@@ -5949,7 +6083,7 @@ gnat_to_gnu (Node_Id gnat_node)
N_Raise_Storage_Error); N_Raise_Storage_Error);
else if (Nkind (Expression (gnat_node)) == N_Function_Call) else if (Nkind (Expression (gnat_node)) == N_Function_Call)
gnu_result gnu_result
= call_to_gnu (Expression (gnat_node), &gnu_result_type, gnu_lhs, = Call_to_gnu (Expression (gnat_node), &gnu_result_type, gnu_lhs,
atomic_sync_required_p (Name (gnat_node))); atomic_sync_required_p (Name (gnat_node)));
else else
{ {
...@@ -6238,7 +6372,7 @@ gnat_to_gnu (Node_Id gnat_node) ...@@ -6238,7 +6372,7 @@ gnat_to_gnu (Node_Id gnat_node)
case N_Function_Call: case N_Function_Call:
case N_Procedure_Call_Statement: case N_Procedure_Call_Statement:
gnu_result = call_to_gnu (gnat_node, &gnu_result_type, NULL_TREE, false); gnu_result = Call_to_gnu (gnat_node, &gnu_result_type, NULL_TREE, false);
break; break;
/************************/ /************************/
...@@ -6661,105 +6795,10 @@ gnat_to_gnu (Node_Id gnat_node) ...@@ -6661,105 +6795,10 @@ gnat_to_gnu (Node_Id gnat_node)
case N_Raise_Constraint_Error: case N_Raise_Constraint_Error:
case N_Raise_Program_Error: case N_Raise_Program_Error:
case N_Raise_Storage_Error: case N_Raise_Storage_Error:
{ if (type_annotate_only)
const int reason = UI_To_Int (Reason (gnat_node)); gnu_result = alloc_stmt_list ();
const Node_Id gnat_cond = Condition (gnat_node); else
const bool with_extra_info = Exception_Extra_Info gnu_result = Raise_Error_to_gnu (gnat_node, &gnu_result_type);
&& !No_Exception_Handlers_Set ()
&& !get_exception_label (kind);
tree gnu_cond = NULL_TREE;
if (type_annotate_only)
{
gnu_result = alloc_stmt_list ();
break;
}
gnu_result_type = get_unpadded_type (Etype (gnat_node));
switch (reason)
{
case CE_Access_Check_Failed:
if (with_extra_info)
gnu_result = build_call_raise_column (reason, gnat_node);
break;
case CE_Index_Check_Failed:
case CE_Range_Check_Failed:
case CE_Invalid_Data:
if (Present (gnat_cond)
&& Nkind (gnat_cond) == N_Op_Not
&& Nkind (Right_Opnd (gnat_cond)) == N_In
&& Nkind (Right_Opnd (Right_Opnd (gnat_cond))) == N_Range)
{
Node_Id gnat_index = Left_Opnd (Right_Opnd (gnat_cond));
Node_Id gnat_type = Etype (gnat_index);
Node_Id gnat_range = Right_Opnd (Right_Opnd (gnat_cond));
tree gnu_index = gnat_to_gnu (gnat_index);
tree gnu_low_bound = gnat_to_gnu (Low_Bound (gnat_range));
tree gnu_high_bound = gnat_to_gnu (High_Bound (gnat_range));
struct range_check_info_d *rci;
if (with_extra_info
&& Known_Esize (gnat_type)
&& UI_To_Int (Esize (gnat_type)) <= 32)
gnu_result
= build_call_raise_range (reason, gnat_node, gnu_index,
gnu_low_bound, gnu_high_bound);
/* If loop unswitching is enabled, we try to compute invariant
conditions for checks applied to iteration variables, i.e.
conditions that are both independent of the variable and
necessary in order for the check to fail in the course of
some iteration, and prepend them to the original condition
of the checks. This will make it possible later for the
loop unswitching pass to replace the loop with two loops,
one of which has the checks eliminated and the other has
the original checks reinstated, and a run time selection.
The former loop will be suitable for vectorization. */
if (flag_unswitch_loops
&& (gnu_low_bound = gnat_invariant_expr (gnu_low_bound))
&& (gnu_high_bound = gnat_invariant_expr (gnu_high_bound))
&& (rci = push_range_check_info (gnu_index)))
{
rci->low_bound = gnu_low_bound;
rci->high_bound = gnu_high_bound;
rci->type = gnat_to_gnu_type (gnat_type);
rci->invariant_cond = build1 (SAVE_EXPR, boolean_type_node,
boolean_true_node);
gnu_cond = build_binary_op (TRUTH_ANDIF_EXPR,
boolean_type_node,
rci->invariant_cond,
gnat_to_gnu (gnat_cond));
}
}
break;
default:
break;
}
if (gnu_result == error_mark_node)
gnu_result = build_call_raise (reason, gnat_node, kind);
set_expr_location_from_node (gnu_result, gnat_node);
/* If the type is VOID, this is a statement, so we need to generate
the code for the call. Handle a condition, if there is one. */
if (VOID_TYPE_P (gnu_result_type))
{
if (Present (gnat_cond))
{
if (!gnu_cond)
gnu_cond = gnat_to_gnu (gnat_cond);
gnu_result
= build3 (COND_EXPR, void_type_node, gnu_cond, gnu_result,
alloc_stmt_list ());
}
}
else
gnu_result = build1 (NULL_EXPR, gnu_result_type, gnu_result);
}
break; break;
case N_Validate_Unchecked_Conversion: case N_Validate_Unchecked_Conversion:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment