]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
trans.c (Loop_Statement_to_gnu): Also handle invariant conditions with only one bound.
authorEric Botcazou <ebotcazou@adacore.com>
Sun, 6 May 2012 10:51:37 +0000 (10:51 +0000)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Sun, 6 May 2012 10:51:37 +0000 (10:51 +0000)
* 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

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

index f56496544919b5fdf0851c518b7bd8389b767fbf..803e97be8695c80a3d09ae9a2bc1f46ff6e26536 100644 (file)
@@ -1,3 +1,11 @@
+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.
index fb4a2cd5ffedf7f2dd8dd32c166c1ce218573dee..c4b9a7e2e319e4f6a505ea0fe1ac2e6f928b1125 100644 (file)
@@ -2563,13 +2563,19 @@ Loop_Statement_to_gnu (Node_Id gnat_node)
             i++)
          {
            tree low_ok
-             = build_binary_op (GE_EXPR, boolean_type_node,
-                                convert (rci->type, gnu_low),
-                                rci->low_bound);
+             = 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
-             = build_binary_op (LE_EXPR, boolean_type_node,
-                                convert (rci->type, gnu_high),
-                                rci->high_bound);
+             = rci->high_bound
+               ? build_binary_op (LE_EXPR, boolean_type_node,
+                                  convert (rci->type, gnu_high),
+                                  rci->high_bound)
+               : boolean_true_node;
+
            tree range_ok
              = build_binary_op (TRUTH_ANDIF_EXPR, boolean_type_node,
                                 low_ok, high_ok);
@@ -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;
 
       /* 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
          && TREE_CODE (TREE_OPERAND (ret_val, 0)) == INIT_EXPR
          && TREE_OPERAND (TREE_OPERAND (ret_val, 0), 0)
@@ -3122,7 +3128,7 @@ build_return_expr (tree ret_obj, tree ret_val)
          && aggregate_value_p (operation_type, current_function_decl))
        {
          /* 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
              && TREE_CODE (TREE_OPERAND (ret_val, 0)) == INIT_EXPR
              && 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,
    requires atomic synchronization.  */
 
 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)
 {
   const bool function_call = (Nkind (gnat_node) == N_Function_Call);
@@ -4751,6 +4757,134 @@ Compilation_Unit_to_gnu (Node_Id gnat_node)
   invalidate_global_renaming_pointers ();
 }
 \f
+/* 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;
+}
+\f
 /* Return true if GNAT_NODE is on the LHS of an assignment or an actual
    parameter of a call.  */
 
@@ -5949,7 +6083,7 @@ gnat_to_gnu (Node_Id gnat_node)
                                       N_Raise_Storage_Error);
       else if (Nkind (Expression (gnat_node)) == N_Function_Call)
        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)));
       else
        {
@@ -6238,7 +6372,7 @@ gnat_to_gnu (Node_Id gnat_node)
 
     case N_Function_Call:
     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;
 
     /************************/
@@ -6661,105 +6795,10 @@ gnat_to_gnu (Node_Id gnat_node)
     case N_Raise_Constraint_Error:
     case N_Raise_Program_Error:
     case N_Raise_Storage_Error:
-      {
-       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_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);
-      }
+      if (type_annotate_only)
+       gnu_result = alloc_stmt_list ();
+      else
+       gnu_result = Raise_Error_to_gnu (gnat_node, &gnu_result_type);
       break;
 
     case N_Validate_Unchecked_Conversion: