diff options
author | Marc Poulhiès <poulhies@adacore.com> | 2023-09-08 15:15:48 +0000 |
---|---|---|
committer | Marc Poulhiès <poulhies@adacore.com> | 2023-09-19 13:26:42 +0200 |
commit | 047269320d433e4024fcb3580f638bcb2aca7664 (patch) | |
tree | 0734467aac08433e2acd7b56df0b41df00e833ca /gcc/ada/gcc-interface/utils.cc | |
parent | 54c16824f0f05313bfc7df5e625f108b4ff7c636 (diff) | |
download | gcc-047269320d433e4024fcb3580f638bcb2aca7664.zip gcc-047269320d433e4024fcb3580f638bcb2aca7664.tar.gz gcc-047269320d433e4024fcb3580f638bcb2aca7664.tar.bz2 |
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.
Diffstat (limited to 'gcc/ada/gcc-interface/utils.cc')
-rw-r--r-- | gcc/ada/gcc-interface/utils.cc | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/gcc/ada/gcc-interface/utils.cc b/gcc/ada/gcc-interface/utils.cc index f720f3a..4e2ed17 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); |