diff options
author | Pierre-Marie de Rodat <derodat@adacore.com> | 2015-06-01 09:03:34 +0000 |
---|---|---|
committer | Eric Botcazou <ebotcazou@gcc.gnu.org> | 2015-06-01 09:03:34 +0000 |
commit | 3b5d86ec77b6bf9cf1c30bffc04343cced3f9497 (patch) | |
tree | 1c81186880e56bb61a4daaa098454c3a378e0a19 /gcc/ada/gcc-interface/utils.c | |
parent | 66dc4b95404311ba09996e37f7a8c0f1472feac7 (diff) | |
download | gcc-3b5d86ec77b6bf9cf1c30bffc04343cced3f9497.zip gcc-3b5d86ec77b6bf9cf1c30bffc04343cced3f9497.tar.gz gcc-3b5d86ec77b6bf9cf1c30bffc04343cced3f9497.tar.bz2 |
utils.c (scale_by_factor_of): When handling a function call expression, process the corresponding function body.
* gcc-interface/utils.c (scale_by_factor_of): When handling a function
call expression, process the corresponding function body. Also handle
potential addends.
From-SVN: r223921
Diffstat (limited to 'gcc/ada/gcc-interface/utils.c')
-rw-r--r-- | gcc/ada/gcc-interface/utils.c | 30 |
1 files changed, 28 insertions, 2 deletions
diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c index 7ec0974..77d00b3 100644 --- a/gcc/ada/gcc-interface/utils.c +++ b/gcc/ada/gcc-interface/utils.c @@ -2908,7 +2908,24 @@ process_deferred_decl_context (bool force) static unsigned int scale_by_factor_of (tree expr, unsigned int value) { + unsigned HOST_WIDE_INT addend = 0; + unsigned HOST_WIDE_INT factor = 1; + + /* Peel conversions around EXPR and try to extract bodies from function + calls: it is possible to get the scale factor from size functions. */ expr = remove_conversions (expr, true); + if (TREE_CODE (expr) == CALL_EXPR) + expr = maybe_inline_call_in_expr (expr); + + /* Sometimes we get PLUS_EXPR (BIT_AND_EXPR (..., X), Y), where Y is a + multiple of the scale factor we are looking for. */ + if (TREE_CODE (expr) == PLUS_EXPR + && TREE_CODE (TREE_OPERAND (expr, 1)) == INTEGER_CST + && tree_fits_uhwi_p (TREE_OPERAND (expr, 1))) + { + addend = TREE_INT_CST_LOW (TREE_OPERAND (expr, 1)); + expr = TREE_OPERAND (expr, 0); + } /* An expression which is a bitwise AND with a mask has a power-of-2 factor corresponding to the number of trailing zeros of the mask. */ @@ -2921,12 +2938,21 @@ scale_by_factor_of (tree expr, unsigned int value) while ((mask & 1) == 0 && i < HOST_BITS_PER_WIDE_INT) { mask >>= 1; - value *= 2; + factor *= 2; i++; } } - return value; + /* If the addend is not a multiple of the factor we found, give up. In + theory we could find a smaller common factor but it's useless for our + needs. This situation arises when dealing with a field F1 with no + alignment requirement but that is following a field F2 with such + requirements. As long as we have F2's offset, we don't need alignment + information to compute F1's. */ + if (addend % factor != 0) + factor = 1; + + return factor * value; } /* Given two consecutive field decls PREV_FIELD and CURR_FIELD, return true |