aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/gcc-interface/trans.c
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@adacore.com>2015-11-30 11:46:32 +0000
committerEric Botcazou <ebotcazou@gcc.gnu.org>2015-11-30 11:46:32 +0000
commit933a73251d95fb930028cb76eee7a892f41f867b (patch)
tree04f64660b152400aaf2762b907ade2f74782d611 /gcc/ada/gcc-interface/trans.c
parentf8125f0c9ce43aac6d7a96753e4617af68ee0009 (diff)
downloadgcc-933a73251d95fb930028cb76eee7a892f41f867b.zip
gcc-933a73251d95fb930028cb76eee7a892f41f867b.tar.gz
gcc-933a73251d95fb930028cb76eee7a892f41f867b.tar.bz2
gigi.h (is_simple_additive_expression): Declare.
* gcc-interface/gigi.h (is_simple_additive_expression): Declare. * gcc-interface/trans.c (struct range_check_info_d): Add DISP and NEG_P fields. (find_loop_for): Add DISP and NEG_P parameters with default value. Call is_simple_additive_expression to handle additive expressions. (Loop_Statement_to_gnu): Deal with displacement in range checks. (Raise_Error_to_gnu): Likewise. (gnat_to_gnu): Add call to find_loop_for. (is_simple_additive_expression): New function extracted from... (gnat_invariant_expr): ...here. Call it on the expression. From-SVN: r231064
Diffstat (limited to 'gcc/ada/gcc-interface/trans.c')
-rw-r--r--gcc/ada/gcc-interface/trans.c80
1 files changed, 61 insertions, 19 deletions
diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c
index fdcf9a3..4c1e3aa 100644
--- a/gcc/ada/gcc-interface/trans.c
+++ b/gcc/ada/gcc-interface/trans.c
@@ -180,6 +180,8 @@ static GTY(()) vec<tree, va_gc> *gnu_return_var_stack;
struct GTY(()) range_check_info_d {
tree low_bound;
tree high_bound;
+ tree disp;
+ bool neg_p;
tree type;
tree invariant_cond;
tree inserted_cond;
@@ -2638,15 +2640,36 @@ inside_loop_p (void)
return !vec_safe_is_empty (gnu_loop_stack);
}
-/* Find out whether VAR is the iteration variable of an enclosing loop in the
- current function. If so, return the loop; otherwise, return NULL. */
+/* Find out whether EXPR is a simple additive expression based on the iteration
+ variable of some enclosing loop in the current function. If so, return the
+ loop and set *DISP to the displacement and *NEG_P to true if this is for a
+ subtraction; otherwise, return NULL. */
static struct loop_info_d *
-find_loop_for (tree var)
+find_loop_for (tree expr, tree *disp = NULL, bool *neg_p = NULL)
{
+ tree var, add, cst;
+ bool minus_p;
struct loop_info_d *iter = NULL;
unsigned int i;
+ if (is_simple_additive_expression (expr, &add, &cst, &minus_p))
+ {
+ var = add;
+ if (disp)
+ *disp = cst;
+ if (neg_p)
+ *neg_p = minus_p;
+ }
+ else
+ {
+ var = expr;
+ if (disp)
+ *disp = NULL_TREE;
+ if (neg_p)
+ *neg_p = false;
+ }
+
var = remove_conversions (var, false);
if (TREE_CODE (var) != VAR_DECL)
@@ -3123,19 +3146,35 @@ Loop_Statement_to_gnu (Node_Id gnat_node)
FOR_EACH_VEC_ELT (*gnu_loop_info->checks, i, rci)
{
- tree low_ok
- = rci->low_bound
- ? build_binary_op (GE_EXPR, boolean_type_node,
- convert (rci->type, gnu_low),
- rci->low_bound)
- : boolean_true_node;
-
- tree high_ok
- = rci->high_bound
- ? build_binary_op (LE_EXPR, boolean_type_node,
- convert (rci->type, gnu_high),
- rci->high_bound)
- : boolean_true_node;
+ tree low_ok, high_ok;
+
+ if (rci->low_bound)
+ {
+ tree gnu_adjusted_low = convert (rci->type, gnu_low);
+ if (rci->disp)
+ gnu_adjusted_low
+ = fold_build2 (rci->neg_p ? MINUS_EXPR : PLUS_EXPR,
+ rci->type, gnu_adjusted_low, rci->disp);
+ low_ok
+ = build_binary_op (GE_EXPR, boolean_type_node,
+ gnu_adjusted_low, rci->low_bound);
+ }
+ else
+ low_ok = boolean_true_node;
+
+ if (rci->high_bound)
+ {
+ tree gnu_adjusted_high = convert (rci->type, gnu_high);
+ if (rci->disp)
+ gnu_adjusted_high
+ = fold_build2 (rci->neg_p ? MINUS_EXPR : PLUS_EXPR,
+ rci->type, gnu_adjusted_high, rci->disp);
+ high_ok
+ = build_binary_op (LE_EXPR, boolean_type_node,
+ gnu_adjusted_high, rci->high_bound);
+ }
+ else
+ high_ok = boolean_true_node;
tree range_ok
= build_binary_op (TRUTH_ANDIF_EXPR, boolean_type_node,
@@ -5492,7 +5531,8 @@ Raise_Error_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p)
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;
+ tree gnu_index, gnu_low_bound, gnu_high_bound, disp;
+ bool neg_p;
struct loop_info_d *loop;
switch (Nkind (Right_Opnd (gnat_cond)))
@@ -5559,11 +5599,13 @@ Raise_Error_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p)
|| (gnu_low_bound = gnat_invariant_expr (gnu_low_bound)))
&& (!gnu_high_bound
|| (gnu_high_bound = gnat_invariant_expr (gnu_high_bound)))
- && (loop = find_loop_for (gnu_index)))
+ && (loop = find_loop_for (gnu_index, &disp, &neg_p)))
{
struct range_check_info_d *rci = ggc_alloc<range_check_info_d> ();
rci->low_bound = gnu_low_bound;
rci->high_bound = gnu_high_bound;
+ rci->disp = disp;
+ rci->neg_p = neg_p;
rci->type = get_unpadded_type (gnat_type);
rci->inserted_cond
= build1 (SAVE_EXPR, boolean_type_node, boolean_true_node);
@@ -6197,7 +6239,7 @@ gnat_to_gnu (Node_Id gnat_node)
&& tree_int_cst_equal (TYPE_MIN_VALUE (TYPE_DOMAIN (gnu_type)),
TYPE_MAX_VALUE (TYPE_DOMAIN (gnu_type)))
&& !array_at_struct_end_p (gnu_result)
- && (loop = find_loop_for (skip_simple_arithmetic (gnu_expr)))
+ && (loop = find_loop_for (gnu_expr))
&& !loop->artificial
&& !loop->has_checks
&& tree_int_cst_equal (TYPE_MIN_VALUE (TYPE_DOMAIN (gnu_type)),