OSDN Git Service

* gcc-interface/trans.c (gnat_to_gnu) <N_Slice>: Simplify expansion
authorbosch <bosch@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 17 Oct 2008 19:22:42 +0000 (19:22 +0000)
committerbosch <bosch@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 17 Oct 2008 19:22:42 +0000 (19:22 +0000)
to use only a single check instead of three, and avoid unnecessary
COMPOUND_EXPR.
(emit_check): Avoid useless COMPOUND_EXPRs and SAVE_EXPRs, sometimes
creating more opportunities for optimizations.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@141198 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ada/ChangeLog
gcc/ada/gcc-interface/trans.c

index 7cbfc1b..caee726 100644 (file)
@@ -1,3 +1,11 @@
+2008-10-17  Geert Bosch  <bosch@adacore.com>
+
+       * gcc-interface/trans.c (gnat_to_gnu) <N_Slice>: Simplify expansion
+       to use only a single check instead of three, and avoid unnecessary
+       COMPOUND_EXPR.
+       (emit_check): Avoid useless COMPOUND_EXPRs and SAVE_EXPRs, sometimes
+       creating more opportunities for optimizations.
+
 2008-10-13  Jakub Jelinek  <jakub@redhat.com>
 
        PR middle-end/37601
index e4c8622..6ade568 100644 (file)
@@ -3563,32 +3563,40 @@ gnat_to_gnu (Node_Id gnat_node)
            /* Get the permitted bounds.  */
            tree gnu_base_index_type
              = TYPE_INDEX_TYPE (TYPE_DOMAIN (gnu_type));
-           tree gnu_base_min_expr = TYPE_MIN_VALUE (gnu_base_index_type);
-           tree gnu_base_max_expr = TYPE_MAX_VALUE (gnu_base_index_type);
+           tree gnu_base_min_expr = SUBSTITUTE_PLACEHOLDER_IN_EXPR
+             (TYPE_MIN_VALUE (gnu_base_index_type), gnu_result);
+           tree gnu_base_max_expr = SUBSTITUTE_PLACEHOLDER_IN_EXPR
+             (TYPE_MAX_VALUE (gnu_base_index_type), gnu_result);
            tree gnu_expr_l, gnu_expr_h, gnu_expr_type;
 
-           /* Check to see that the minimum slice value is in range.  */
-           gnu_expr_l = emit_index_check (gnu_result,
-                                          gnu_min_expr,
-                                          gnu_base_min_expr,
-                                          gnu_base_max_expr);
-
-           /* Check to see that the maximum slice value is in range.  */
-           gnu_expr_h = emit_index_check (gnu_result,
-                                          gnu_max_expr,
-                                          gnu_base_min_expr,
-                                          gnu_base_max_expr);
+          gnu_min_expr = protect_multiple_eval (gnu_min_expr);
+          gnu_max_expr = protect_multiple_eval (gnu_max_expr);
 
            /* Derive a good type to convert everything to.  */
-           gnu_expr_type = get_base_type (TREE_TYPE (gnu_expr_l));
-
-           /* Build a compound expression that does the range checks and
-              returns the low bound.  */
-           gnu_expr = build_binary_op (COMPOUND_EXPR, gnu_expr_type,
-                                       convert (gnu_expr_type, gnu_expr_h),
-                                       convert (gnu_expr_type, gnu_expr_l));
-
-          /* Build a conditional expression that does the range check and
+           gnu_expr_type = get_base_type (TREE_TYPE (gnu_index_type));
+
+           /* Test whether the minimum slice value is too small.  */
+           gnu_expr_l = build_binary_op (LT_EXPR, integer_type_node,
+                                         convert (gnu_expr_type,
+                                                  gnu_min_expr),
+                                         convert (gnu_expr_type,
+                                                  gnu_base_min_expr));
+
+           /* Test whether the maximum slice value is too large.  */
+           gnu_expr_h = build_binary_op (GT_EXPR, integer_type_node,
+                                         convert (gnu_expr_type,
+                                                  gnu_max_expr),
+                                         convert (gnu_expr_type,
+                                                  gnu_base_max_expr));
+
+           /* Build a slice index check that returns the low bound,
+               assuming the slice is not empty.  */
+           gnu_expr = emit_check
+             (build_binary_op (TRUTH_ORIF_EXPR, integer_type_node,
+                               gnu_expr_l, gnu_expr_h),
+              gnu_min_expr, CE_Index_Check_Failed);
+
+          /* Build a conditional expression that does the index checks and
              returns the low bound if the slice is not empty (max >= min),
              and returns the naked low bound otherwise (max < min), unless
              it is non-constant and the high bound is; this prevents VRP
@@ -6186,33 +6194,18 @@ emit_index_check (tree gnu_array_object,
 static tree
 emit_check (tree gnu_cond, tree gnu_expr, int reason)
 {
-  tree gnu_call;
-  tree gnu_result;
+  tree gnu_call = build_call_raise (reason, Empty, N_Raise_Constraint_Error);
+  tree gnu_result
+    = fold_build3 (COND_EXPR, TREE_TYPE (gnu_expr), gnu_cond,
+                  build2 (COMPOUND_EXPR, TREE_TYPE (gnu_expr), gnu_call,
+                          convert (TREE_TYPE (gnu_expr), integer_zero_node)),
+                  gnu_expr);
 
-  gnu_call = build_call_raise (reason, Empty, N_Raise_Constraint_Error);
-
-  /* Use an outer COMPOUND_EXPR to make sure that GNU_EXPR will get evaluated
-     in front of the comparison in case it ends up being a SAVE_EXPR.  Put the
-     whole thing inside its own SAVE_EXPR so the inner SAVE_EXPR doesn't leak
-     out.  */
-  gnu_result = fold_build3 (COND_EXPR, TREE_TYPE (gnu_expr), gnu_cond,
-                           build2 (COMPOUND_EXPR, TREE_TYPE (gnu_expr),
-                                   gnu_call, gnu_expr),
-                           gnu_expr);
-
-  /* If GNU_EXPR has side effects, make the outer COMPOUND_EXPR and
-     protect it.  Otherwise, show GNU_RESULT has no side effects: we
-     don't need to evaluate it just for the check.  */
-  if (TREE_SIDE_EFFECTS (gnu_expr))
-    gnu_result
-      = build2 (COMPOUND_EXPR, TREE_TYPE (gnu_expr), gnu_expr, gnu_result);
-  else
-    TREE_SIDE_EFFECTS (gnu_result) = 0;
+  /* GNU_RESULT has side effects if and only if GNU_EXPR has:
+     we don't need to evaluate it just for the check.  */
+  TREE_SIDE_EFFECTS (gnu_result) = TREE_SIDE_EFFECTS (gnu_expr);
 
-  /* ??? Unfortunately, if we don't put a SAVE_EXPR around this whole thing,
-     we will repeatedly do the test.  It would be nice if GCC was able
-     to optimize this and only do it once.  */
-  return save_expr (gnu_result);
+  return gnu_result;
 }
 \f
 /* Return an expression that converts GNU_EXPR to GNAT_TYPE, doing