From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 7871) id 5F0593858281; Tue, 19 Sep 2023 11:27:13 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 5F0593858281 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1695122833; bh=md9N/l9JN1/S3UXfYWggTmC4BiEYhFfxFazrTABeAQM=; h=From:To:Subject:Date:From; b=DWgHAjD+iDEc3Mnn8vrKnGkYPODEpMOhKyVZa1Ayk9ihANR6Q6zneb/oZ2kCuMhHZ 0hTif/LXPZ4h9lIJPjiTD20a8PK/3oxgeRwElTGMOXGcS+mF1bCPkZHrQ7DGztkTbY 9Zq9dm01EeWdW73nux3U0XxWS5l+iRXll1w4Myf4= MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset="utf-8" From: Marc Poulhi?s To: gcc-cvs@gcc.gnu.org Subject: [gcc r14-4130] ada: Refine upper array bound for bit packed array X-Act-Checkin: gcc X-Git-Author: =?utf-8?q?Marc_Poulhi=C3=A8s?= X-Git-Refname: refs/heads/master X-Git-Oldrev: 54c16824f0f05313bfc7df5e625f108b4ff7c636 X-Git-Newrev: 047269320d433e4024fcb3580f638bcb2aca7664 Message-Id: <20230919112713.5F0593858281@sourceware.org> Date: Tue, 19 Sep 2023 11:27:13 +0000 (GMT) List-Id: https://gcc.gnu.org/g:047269320d433e4024fcb3580f638bcb2aca7664 commit r14-4130-g047269320d433e4024fcb3580f638bcb2aca7664 Author: Marc Poulhiès 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) : 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);