public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r14-4130] ada: Refine upper array bound for bit packed array
@ 2023-09-19 11:27 Marc Poulhi?s
  0 siblings, 0 replies; only message in thread
From: Marc Poulhi?s @ 2023-09-19 11:27 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:047269320d433e4024fcb3580f638bcb2aca7664

commit r14-4130-g047269320d433e4024fcb3580f638bcb2aca7664
Author: Marc Poulhiès <poulhies@adacore.com>
Date:   Fri Sep 8 15:15:48 2023 +0000

    ada: Refine upper array bound for bit packed array
    
    When using bit-packed arrays, the compiler creates new array subtypes of
    1-bit component indexed by integers. The existing routine checks the
    index subtype to find the min/max values. Bit-packed arrays being
    indexed by integers, the routines gives up as returning the maximum
    possible integer carries no useful information.
    
    This change adds a simple max_value routine that can evaluate very
    simple expressions by substituting variables by their min/max value.
    Bit-packed array subtypes are currently declared as:
    
      subtype bp_array is packed_bytes1 (0 .. integer((1 * Var +  7) / 8 - 1));
    
    The simple max_value evaluator handles the bare minimum for this
    expression pattern.
    
    gcc/ada/ChangeLog:
    
            * gcc-interface/utils.cc (max_value): New.
            * gcc-interface/gigi.h (max_value): New.
            * gcc-interface/decl.cc (gnat_to_gnu_entity) <E_Array_Subtype>:
            When computing gnu_min/gnu_max, try to use max_value if there is
            an initial expression.

Diff:
---
 gcc/ada/gcc-interface/decl.cc  | 22 ++++++++++
 gcc/ada/gcc-interface/gigi.h   |  6 +++
 gcc/ada/gcc-interface/utils.cc | 95 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 123 insertions(+)

diff --git a/gcc/ada/gcc-interface/decl.cc b/gcc/ada/gcc-interface/decl.cc
index 0cf7d3cee60..5e16b56217c 100644
--- a/gcc/ada/gcc-interface/decl.cc
+++ b/gcc/ada/gcc-interface/decl.cc
@@ -2551,6 +2551,17 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
 		  else
 		    gnu_min = gnu_orig_min;
 
+		  if (DECL_P (gnu_min)
+		      && DECL_INITIAL (gnu_min) != NULL_TREE
+		      && (TREE_CODE (gnu_min) != INTEGER_CST
+			  || TREE_OVERFLOW (gnu_min)))
+		    {
+		      tree tmp = max_value (DECL_INITIAL(gnu_min), false);
+		      if (TREE_CODE (tmp) == INTEGER_CST
+			  && !TREE_OVERFLOW (tmp))
+			gnu_min = tmp;
+		    }
+
 		  if (TREE_CODE (gnu_min) != INTEGER_CST
 		      || TREE_OVERFLOW (gnu_min))
 		    gnu_min = TYPE_MIN_VALUE (TREE_TYPE (gnu_min));
@@ -2560,6 +2571,17 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
 		  else
 		    gnu_max = gnu_orig_max;
 
+		  if (DECL_P (gnu_max)
+		      && DECL_INITIAL (gnu_max) != NULL_TREE
+		      && (TREE_CODE (gnu_max) != INTEGER_CST
+			  || TREE_OVERFLOW (gnu_max)))
+		    {
+		      tree tmp = max_value (DECL_INITIAL(gnu_max), true);
+		      if (TREE_CODE (tmp) == INTEGER_CST
+			  && !TREE_OVERFLOW (tmp))
+			gnu_max = tmp;
+		    }
+
 		  if (TREE_CODE (gnu_max) != INTEGER_CST
 		      || TREE_OVERFLOW (gnu_max))
 		    gnu_max = TYPE_MAX_VALUE (TREE_TYPE (gnu_max));
diff --git a/gcc/ada/gcc-interface/gigi.h b/gcc/ada/gcc-interface/gigi.h
index ec85ce44bc3..eb5496f50db 100644
--- a/gcc/ada/gcc-interface/gigi.h
+++ b/gcc/ada/gcc-interface/gigi.h
@@ -763,6 +763,12 @@ extern void update_pointer_to (tree old_type, tree new_type);
    minimum (if !MAX_P) possible value of the discriminant.  */
 extern tree max_size (tree exp, bool max_p);
 
+/* Try to compute the maximum (if MAX_P) or minimum (if !MAX_P) value for the
+   expression EXP, for very simple expressions.  Substitute variable references
+   with their respective type's min/max values.  Return the computed value if
+   any, or EXP if no value can be computed. */
+extern tree max_value (tree exp, bool max_p);
+
 /* Remove all conversions that are done in EXP.  This includes converting
    from a padded type or to a left-justified modular type.  If TRUE_ADDRESS
    is true, always return the address of the containing object even if
diff --git a/gcc/ada/gcc-interface/utils.cc b/gcc/ada/gcc-interface/utils.cc
index f720f3a3b4a..4e2ed173fbe 100644
--- a/gcc/ada/gcc-interface/utils.cc
+++ b/gcc/ada/gcc-interface/utils.cc
@@ -3830,6 +3830,100 @@ fntype_same_flags_p (const_tree t, tree cico_list, bool return_by_direct_ref_p,
 	 && TREE_ADDRESSABLE (t) == return_by_invisi_ref_p;
 }
 
+/* Try to compute the maximum (if MAX_P) or minimum (if !MAX_P) value for the
+   expression EXP, for very simple expressions.  Substitute variable references
+   with their respective type's min/max values.  Return the computed value if
+   any, or EXP if no value can be computed. */
+
+tree
+max_value (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))
+    {
+    case tcc_declaration:
+      if (VAR_P (exp))
+        return fold_convert (type,
+                             max_p
+                             ? TYPE_MAX_VALUE (type) : TYPE_MIN_VALUE (type));
+      break;
+
+    case tcc_vl_exp:
+      if (code == CALL_EXPR)
+	{
+          tree t;
+
+          t = maybe_inline_call_in_expr (exp);
+          if (t)
+            return max_value (t, max_p);
+        }
+      break;
+
+    case tcc_comparison:
+      return build_int_cst (type, max_p ? 1 : 0);
+
+    case tcc_unary:
+      op0 = TREE_OPERAND (exp, 0);
+
+      if (code == NON_LVALUE_EXPR)
+        return max_value (op0, max_p);
+
+      if (code == NEGATE_EXPR)
+        return max_value (op0, !max_p);
+
+      if (code == NOP_EXPR)
+	return fold_convert (type, max_value (op0, max_p));
+
+      break;
+
+    case tcc_binary:
+      op0 = TREE_OPERAND (exp, 0);
+      op1 = TREE_OPERAND (exp, 1);
+
+      switch (code) {
+      case PLUS_EXPR:
+      case MULT_EXPR:
+        return fold_build2 (code, type, max_value(op0, max_p),
+                            max_value (op1, max_p));
+      case MINUS_EXPR:
+      case TRUNC_DIV_EXPR:
+        return fold_build2 (code, type, max_value(op0, max_p),
+                            max_value (op1, !max_p));
+      default:
+        break;
+      }
+      break;
+
+    case tcc_expression:
+      if (code == COND_EXPR)
+        {
+          op0 = TREE_OPERAND (exp, 0);
+          op1 = TREE_OPERAND (exp, 1);
+          op2 = TREE_OPERAND (exp, 2);
+
+          if (!op1 || !op2)
+            break;
+
+          op1 = max_value (op1, max_p);
+          op2 = max_value (op2, max_p);
+
+          if (op1 == TREE_OPERAND (exp, 1) && op2 == TREE_OPERAND (exp, 2))
+            break;
+
+          return fold_build2 (max_p ? MAX_EXPR : MIN_EXPR, type, op1, op2);
+	}
+      break;
+
+    default:
+      break;
+    }
+  return exp;
+}
+
+
 /* EXP is an expression for the size of an object.  If this size contains
    discriminant references, replace them with the maximum (if MAX_P) or
    minimum (if !MAX_P) possible value of the discriminant.
@@ -3867,6 +3961,7 @@ max_size (tree exp, bool max_p)
 	  n = call_expr_nargs (exp);
 	  gcc_assert (n > 0);
 	  argarray = XALLOCAVEC (tree, n);
+	  /* This is used to remove possible placeholder in call args.  */
 	  for (i = 0; i < n; i++)
 	    argarray[i] = max_size (CALL_EXPR_ARG (exp, i), max_p);
 	  return build_call_array (type, CALL_EXPR_FN (exp), n, argarray);

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2023-09-19 11:27 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-09-19 11:27 [gcc r14-4130] ada: Refine upper array bound for bit packed array Marc Poulhi?s

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).