From 3b5d86ec77b6bf9cf1c30bffc04343cced3f9497 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 1 Jun 2015 09:03:34 +0000 Subject: [PATCH] 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 --- gcc/ada/ChangeLog | 6 ++++++ gcc/ada/gcc-interface/utils.c | 30 ++++++++++++++++++++++++++++-- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 7c03f7e547e..61fb680ddb0 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,9 @@ +2015-06-01 Pierre-Marie de Rodat + + * gcc-interface/utils.c (scale_by_factor_of): When handling a function + call expression, process the corresponding function body. Also handle + potential addends. + 2015-06-01 Pierre-Marie de Rodat * gcc-interface/decl.c (gnat_to_gnu_entity): Replace pointer types with diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c index 7ec0974f912..77d00b325f3 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 -- 2.30.2