aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/gcc-interface/utils.c
diff options
context:
space:
mode:
authorPierre-Marie de Rodat <derodat@adacore.com>2015-06-01 09:03:34 +0000
committerEric Botcazou <ebotcazou@gcc.gnu.org>2015-06-01 09:03:34 +0000
commit3b5d86ec77b6bf9cf1c30bffc04343cced3f9497 (patch)
tree1c81186880e56bb61a4daaa098454c3a378e0a19 /gcc/ada/gcc-interface/utils.c
parent66dc4b95404311ba09996e37f7a8c0f1472feac7 (diff)
downloadgcc-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.c30
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