From: Eric Botcazou Date: Fri, 24 Feb 2017 10:00:04 +0000 (+0000) Subject: misc.c (gnat_type_max_size): Try to return a meaningful value for array types with... X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=bf6b72928e7a8d1734e14ef075dc9c985a4902fe;p=gcc.git misc.c (gnat_type_max_size): Try to return a meaningful value for array types with TYPE_INDEX_TYPE set on... * 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 --- diff --git a/gcc/ada/gcc-interface/misc.c b/gcc/ada/gcc-interface/misc.c index 1fed72a0520..cdabfec09d4 100644 --- a/gcc/ada/gcc-interface/misc.c +++ b/gcc/ada/gcc-interface/misc.c @@ -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; diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c index 33a37cea2f6..0f4d8a4b2e6 100644 --- a/gcc/ada/gcc-interface/utils.c +++ b/gcc/ada/gcc-interface/utils.c @@ -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;