misc.c (gnat_type_max_size): Try to return a meaningful value for array types with...
authorEric Botcazou <ebotcazou@gcc.gnu.org>
Fri, 24 Feb 2017 10:00:04 +0000 (10:00 +0000)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Fri, 24 Feb 2017 10:00:04 +0000 (10:00 +0000)
* gcc-interface/misc.c (gnat_type_max_size): Try to return a meaningful
value for array types with TYPE_INDEX_TYPE set on their domain type.
* gcc-interface/utils.c (max_size): For operations and expressions, do
not build a new node if the operands have not changed or are missing.

From-SVN: r245698

gcc/ada/gcc-interface/misc.c
gcc/ada/gcc-interface/utils.c

index 1fed72a0520e1f16d112a49a5408975ad9e456ca..cdabfec09d41258467c8d64554043d85a390ea7f 100644 (file)
@@ -6,7 +6,7 @@
  *                                                                          *
  *                           C Implementation File                          *
  *                                                                          *
- *          Copyright (C) 1992-2016, Free Software Foundation, Inc.         *
+ *          Copyright (C) 1992-2017, Free Software Foundation, Inc.         *
  *                                                                          *
  * GNAT is free software;  you can  redistribute it  and/or modify it under *
  * terms of the  GNU General Public License as published  by the Free Soft- *
@@ -736,22 +736,59 @@ gnat_type_max_size (const_tree gnu_type)
      elaborated and possibly replaced by a VAR_DECL.  */
   tree max_unitsize = max_size (TYPE_SIZE_UNIT (gnu_type), true);
 
-  /* If we don't have a constant, see what we can get from TYPE_ADA_SIZE,
-     which should stay untouched.  */
-  if (!tree_fits_uhwi_p (max_unitsize)
-      && RECORD_OR_UNION_TYPE_P (gnu_type)
-      && !TYPE_FAT_POINTER_P (gnu_type)
-      && TYPE_ADA_SIZE (gnu_type))
+  /* If we don't have a constant, try to look at attributes which should have
+     stayed untouched.  */
+  if (!tree_fits_uhwi_p (max_unitsize))
     {
-      tree max_adasize = max_size (TYPE_ADA_SIZE (gnu_type), true);
-
-      /* If we have succeeded in finding a constant, round it up to the
-        type's alignment and return the result in units.  */
-      if (tree_fits_uhwi_p (max_adasize))
-       max_unitsize
-         = size_binop (CEIL_DIV_EXPR,
-                       round_up (max_adasize, TYPE_ALIGN (gnu_type)),
-                       bitsize_unit_node);
+      /* For record types, see what we can get from TYPE_ADA_SIZE.  */
+      if (RECORD_OR_UNION_TYPE_P (gnu_type)
+         && !TYPE_FAT_POINTER_P (gnu_type)
+         && TYPE_ADA_SIZE (gnu_type))
+       {
+         tree max_adasize = max_size (TYPE_ADA_SIZE (gnu_type), true);
+
+         /* If we have succeeded in finding a constant, round it up to the
+            type's alignment and return the result in units.  */
+         if (tree_fits_uhwi_p (max_adasize))
+           max_unitsize
+             = size_binop (CEIL_DIV_EXPR,
+                           round_up (max_adasize, TYPE_ALIGN (gnu_type)),
+                           bitsize_unit_node);
+       }
+
+      /* For array types, see what we can get from TYPE_INDEX_TYPE.  */
+      else if (TREE_CODE (gnu_type) == ARRAY_TYPE
+              && TYPE_INDEX_TYPE (TYPE_DOMAIN (gnu_type))
+              && tree_fits_uhwi_p (TYPE_SIZE_UNIT (TREE_TYPE (gnu_type))))
+       {
+         tree lb = TYPE_MIN_VALUE (TYPE_INDEX_TYPE (TYPE_DOMAIN (gnu_type)));
+         tree hb = TYPE_MAX_VALUE (TYPE_INDEX_TYPE (TYPE_DOMAIN (gnu_type)));
+         if (TREE_CODE (lb) != INTEGER_CST
+             && TYPE_RM_SIZE (TREE_TYPE (lb))
+             && compare_tree_int (TYPE_RM_SIZE (TREE_TYPE (lb)), 16) <= 0)
+           lb = TYPE_MIN_VALUE (TREE_TYPE (lb));
+         if (TREE_CODE (hb) != INTEGER_CST
+             && TYPE_RM_SIZE (TREE_TYPE (hb))
+             && compare_tree_int (TYPE_RM_SIZE (TREE_TYPE (hb)), 16) <= 0)
+           hb = TYPE_MAX_VALUE (TREE_TYPE (hb));
+         if (TREE_CODE (lb) == INTEGER_CST && TREE_CODE (hb) == INTEGER_CST)
+           {
+             tree ctype = get_base_type (TREE_TYPE (lb));
+             lb = fold_convert (ctype, lb);
+             hb = fold_convert (ctype, hb);
+             if (tree_int_cst_le (lb, hb))
+               {
+                 tree length
+                   = fold_build2 (PLUS_EXPR, ctype,
+                                  fold_build2 (MINUS_EXPR, ctype, hb, lb),
+                                  build_int_cst (ctype, 1));
+                 max_unitsize
+                   = fold_build2 (MULT_EXPR, sizetype,
+                                  fold_convert (sizetype, length),
+                                  TYPE_SIZE_UNIT (TREE_TYPE (gnu_type)));
+               }
+           }
+       }
     }
 
   return max_unitsize;
index 33a37cea2f6b0c90c6a511a00b29bff73e5cb892..0f4d8a4b2e63e5316648ac17cd3a743269a2f022 100644 (file)
@@ -3534,6 +3534,7 @@ max_size (tree exp, bool max_p)
 {
   enum tree_code code = TREE_CODE (exp);
   tree type = TREE_TYPE (exp);
+  tree op0, op1, op2;
 
   switch (TREE_CODE_CLASS (code))
     {
@@ -3575,15 +3576,19 @@ max_size (tree exp, bool max_p)
       return exp;
 
     case tcc_comparison:
-      return max_p ? size_one_node : size_zero_node;
+      return build_int_cst (type, max_p ? 1 : 0);
 
     case tcc_unary:
       if (code == NON_LVALUE_EXPR)
        return max_size (TREE_OPERAND (exp, 0), max_p);
 
-      return fold_build1 (code, type,
-                         max_size (TREE_OPERAND (exp, 0),
-                                   code == NEGATE_EXPR ? !max_p : max_p));
+      op0 = max_size (TREE_OPERAND (exp, 0),
+                     code == NEGATE_EXPR ? !max_p : max_p);
+
+      if (op0 == TREE_OPERAND (exp, 0))
+       return exp;
+
+      return fold_build1 (code, type, op0);
 
     case tcc_binary:
       {
@@ -3623,6 +3628,9 @@ max_size (tree exp, bool max_p)
            code = PLUS_EXPR;
          }
 
+       if (lhs == TREE_OPERAND (exp, 0) && rhs == TREE_OPERAND (exp, 1))
+         return exp;
+
        /* We need to detect overflows so we call size_binop here.  */
        return size_binop (code, lhs, rhs);
       }
@@ -3634,23 +3642,40 @@ max_size (tree exp, bool max_p)
          if (code == SAVE_EXPR)
            return exp;
 
-         return fold_build1 (code, type,
-                             max_size (TREE_OPERAND (exp, 0),
-                             code == TRUTH_NOT_EXPR ? !max_p : max_p));
+         op0 = max_size (TREE_OPERAND (exp, 0),
+                         code == TRUTH_NOT_EXPR ? !max_p : max_p);
+
+         if (op0 == TREE_OPERAND (exp, 0))
+           return exp;
+
+         return fold_build1 (code, type, op0);
 
        case 2:
          if (code == COMPOUND_EXPR)
            return max_size (TREE_OPERAND (exp, 1), max_p);
 
-         return fold_build2 (code, type,
-                             max_size (TREE_OPERAND (exp, 0), max_p),
-                             max_size (TREE_OPERAND (exp, 1), max_p));
+         op0 = max_size (TREE_OPERAND (exp, 0), max_p);
+         op1 = max_size (TREE_OPERAND (exp, 1), max_p);
+
+         if (op0 == TREE_OPERAND (exp, 0) && op1 == TREE_OPERAND (exp, 1))
+           return exp;
+
+         return fold_build2 (code, type, op0, op1);
 
        case 3:
          if (code == COND_EXPR)
-           return fold_build2 (max_p ? MAX_EXPR : MIN_EXPR, type,
-                               max_size (TREE_OPERAND (exp, 1), max_p),
-                               max_size (TREE_OPERAND (exp, 2), max_p));
+           {
+             op1 = TREE_OPERAND (exp, 1);
+             op2 = TREE_OPERAND (exp, 2);
+
+             if (!op1 || !op2)
+               return exp;
+
+             return
+               fold_build2 (max_p ? MAX_EXPR : MIN_EXPR, type,
+                            max_size (op1, max_p), max_size (op2, max_p));
+           }
+         break;
 
        default:
          break;