From 2614034eead349c8ae65e7f106bdce4212e9b71a Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Thu, 23 Dec 2004 14:02:33 +0100 Subject: [PATCH] re PR middle-end/17746 (ICE when building the Ada RTS) PR middle-end/17746 * expr.c (get_inner_reference): Add 'keep_aligning' parameter. Break on aligning VIEW_CONVERT_EXPR nodes on STRICT_ALIGNMENT platforms only if keep_aligning is true. (expand_assignment): Adjust call to get_inner_reference. (expand_expr_addr_expr_1): Likewise. (expand_expr_real_1): Likewise. * dojump.c (do_jump): Likewise. * dwarf2out.c (loc_descriptor_from_tree_1): Likewise. * fold-const.c (optimize_bit_field_compare): Likewise. (decode_field_reference): Likewise. (split_address_to_core_and_offset): Likewise. * tree-ssa-loop-ivopts.c (split_address_cost): Likewise. * expr.h (get_inner_reference): Adjust prototype. ada/ * trans.c (Attribute_to_gnu): Adjust call to get_inner_reference. * utils2.c (build_unary_op): Likewise. From-SVN: r92549 --- gcc/ChangeLog | 17 +++++++++++++++++ gcc/ada/ChangeLog | 5 +++++ gcc/ada/trans.c | 2 +- gcc/ada/utils2.c | 2 +- gcc/dojump.c | 2 +- gcc/dwarf2out.c | 2 +- gcc/expr.c | 37 ++++++++++++++++++++++++++----------- gcc/fold-const.c | 9 +++++---- gcc/tree-ssa-loop-ivopts.c | 2 +- 9 files changed, 58 insertions(+), 20 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0872bf6..78879a7 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,20 @@ +2004-12-23 Eric Botcazou + + PR middle-end/17746 + * expr.c (get_inner_reference): Add 'keep_aligning' parameter. + Break on aligning VIEW_CONVERT_EXPR nodes on STRICT_ALIGNMENT + platforms only if keep_aligning is true. + (expand_assignment): Adjust call to get_inner_reference. + (expand_expr_addr_expr_1): Likewise. + (expand_expr_real_1): Likewise. + * dojump.c (do_jump): Likewise. + * dwarf2out.c (loc_descriptor_from_tree_1): Likewise. + * fold-const.c (optimize_bit_field_compare): Likewise. + (decode_field_reference): Likewise. + (split_address_to_core_and_offset): Likewise. + * tree-ssa-loop-ivopts.c (split_address_cost): Likewise. + * expr.h (get_inner_reference): Adjust prototype. + 2004-12-23 Richard Henderson * config/i386/i386.c (override_options): Revert last change diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 479443a..792ddcd 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2004-12-23 Eric Botcazou + + * trans.c (Attribute_to_gnu): Adjust call to get_inner_reference. + * utils2.c (build_unary_op): Likewise. + 2004-12-22 Richard Kenner * trans.c (mark_visited): Set TYPE_SIZES_GIMPLIFIED. diff --git a/gcc/ada/trans.c b/gcc/ada/trans.c index 0db1709..a93ff5d 100644 --- a/gcc/ada/trans.c +++ b/gcc/ada/trans.c @@ -932,7 +932,7 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute) && TREE_CODE (gnu_prefix) == FIELD_DECL)); get_inner_reference (gnu_prefix, &bitsize, &bitpos, &gnu_offset, - &mode, &unsignedp, &volatilep); + &mode, &unsignedp, &volatilep, false); if (TREE_CODE (gnu_prefix) == COMPONENT_REF) { diff --git a/gcc/ada/utils2.c b/gcc/ada/utils2.c index 3727ce4..04ab0cb 100644 --- a/gcc/ada/utils2.c +++ b/gcc/ada/utils2.c @@ -1087,7 +1087,7 @@ build_unary_op (enum tree_code op_code, tree result_type, tree operand) int unsignedp, volatilep; inner = get_inner_reference (operand, &bitsize, &bitpos, &offset, - &mode, &unsignedp, &volatilep); + &mode, &unsignedp, &volatilep, false); /* If INNER is a padding type whose field has a self-referential size, convert to that inner type. We know the offset is zero diff --git a/gcc/dojump.c b/gcc/dojump.c index b1e17ec..0dc826b 100644 --- a/gcc/dojump.c +++ b/gcc/dojump.c @@ -315,7 +315,7 @@ do_jump (tree exp, rtx if_false_label, rtx if_true_label) /* Get description of this reference. We don't actually care about the underlying object here. */ get_inner_reference (exp, &bitsize, &bitpos, &offset, &mode, - &unsignedp, &volatilep); + &unsignedp, &volatilep, false); type = lang_hooks.types.type_for_size (bitsize, unsignedp); if (! SLOW_BYTE_ACCESS diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 74303c2..beed56b 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -8965,7 +8965,7 @@ loc_descriptor_from_tree_1 (tree loc, int want_address) int volatilep; obj = get_inner_reference (loc, &bitsize, &bitpos, &offset, &mode, - &unsignedp, &volatilep); + &unsignedp, &volatilep, false); if (obj == loc) return 0; diff --git a/gcc/expr.c b/gcc/expr.c index d69a8df..f602306 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -3788,7 +3788,7 @@ expand_assignment (tree to, tree from) push_temp_slots (); tem = get_inner_reference (to, &bitsize, &bitpos, &offset, &mode1, - &unsignedp, &volatilep); + &unsignedp, &volatilep, true); /* If we are going to use store_bit_field and extract_bit_field, make sure to_rtx will be safe for multiple use. */ @@ -5244,13 +5244,27 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos, If the field describes a variable-sized object, *PMODE is set to VOIDmode and *PBITSIZE is set to -1. An access cannot be made in - this case, but the address of the object can be found. */ + this case, but the address of the object can be found. + + If KEEP_ALIGNING is true and the target is STRICT_ALIGNMENT, we don't + look through nodes that serve as markers of a greater alignment than + the one that can be deduced from the expression. These nodes make it + possible for front-ends to prevent temporaries from being created by + the middle-end on alignment considerations. For that purpose, the + normal operating mode at high-level is to always pass FALSE so that + the ultimate containing object is really returned; moreover, the + associated predicate handled_component_p will always return TRUE + on these nodes, thus indicating that they are essentially handled + by get_inner_reference. TRUE should only be passed when the caller + is scanning the expression in order to build another representation + and specifically knows how to handle these nodes; as such, this is + the normal operating mode in the RTL expanders. */ tree get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize, HOST_WIDE_INT *pbitpos, tree *poffset, enum machine_mode *pmode, int *punsignedp, - int *pvolatilep) + int *pvolatilep, bool keep_aligning) { tree size_tree = 0; enum machine_mode mode = VOIDmode; @@ -5352,14 +5366,10 @@ get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize, bitsize_int (*pbitsize)); break; - /* We can go inside most conversions: all NON_VALUE_EXPRs, all normal - conversions that don't change the mode, and all view conversions - except those that need to "step up" the alignment. */ - case VIEW_CONVERT_EXPR: - if ((TYPE_ALIGN (TREE_TYPE (exp)) + if (keep_aligning && STRICT_ALIGNMENT + && (TYPE_ALIGN (TREE_TYPE (exp)) > TYPE_ALIGN (TREE_TYPE (TREE_OPERAND (exp, 0)))) - && STRICT_ALIGNMENT && (TYPE_ALIGN (TREE_TYPE (TREE_OPERAND (exp, 0))) < BIGGEST_ALIGNMENT) && (TYPE_ALIGN_OK (TREE_TYPE (exp)) @@ -6082,8 +6092,13 @@ expand_expr_addr_expr_1 (tree exp, rtx target, enum machine_mode tmode, return result; } + /* Pass FALSE as the last argument to get_inner_reference although + we are expanding to RTL. The rationale is that we know how to + handle "aligning nodes" here: we can just bypass them because + they won't change the final object whose address will be returned + (they actually exist only for that purpose). */ inner = get_inner_reference (exp, &bitsize, &bitpos, &offset, - &mode1, &unsignedp, &volatilep); + &mode1, &unsignedp, &volatilep, false); break; } @@ -6908,7 +6923,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, tree offset; int volatilep = 0; tree tem = get_inner_reference (exp, &bitsize, &bitpos, &offset, - &mode1, &unsignedp, &volatilep); + &mode1, &unsignedp, &volatilep, true); rtx orig_op0; /* If we got back the original object, something is wrong. Perhaps diff --git a/gcc/fold-const.c b/gcc/fold-const.c index d249f75..8f8624c 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -3102,7 +3102,7 @@ optimize_bit_field_compare (enum tree_code code, tree compare_type, do anything if the inner expression is a PLACEHOLDER_EXPR since we then will no longer be able to replace it. */ linner = get_inner_reference (lhs, &lbitsize, &lbitpos, &offset, &lmode, - &lunsignedp, &lvolatilep); + &lunsignedp, &lvolatilep, false); if (linner == lhs || lbitsize == GET_MODE_BITSIZE (lmode) || lbitsize < 0 || offset != 0 || TREE_CODE (linner) == PLACEHOLDER_EXPR) return 0; @@ -3112,7 +3112,7 @@ optimize_bit_field_compare (enum tree_code code, tree compare_type, /* If this is not a constant, we can only do something if bit positions, sizes, and signedness are the same. */ rinner = get_inner_reference (rhs, &rbitsize, &rbitpos, &offset, &rmode, - &runsignedp, &rvolatilep); + &runsignedp, &rvolatilep, false); if (rinner == rhs || lbitpos != rbitpos || lbitsize != rbitsize || lunsignedp != runsignedp || offset != 0 @@ -3288,7 +3288,7 @@ decode_field_reference (tree exp, HOST_WIDE_INT *pbitsize, } inner = get_inner_reference (exp, pbitsize, pbitpos, &offset, pmode, - punsignedp, pvolatilep); + punsignedp, pvolatilep, false); if ((inner == exp && and_mask == 0) || *pbitsize < 0 || offset != 0 || TREE_CODE (inner) == PLACEHOLDER_EXPR) @@ -11018,7 +11018,8 @@ split_address_to_core_and_offset (tree exp, if (TREE_CODE (exp) == ADDR_EXPR) { core = get_inner_reference (TREE_OPERAND (exp, 0), &bitsize, pbitpos, - poffset, &mode, &unsignedp, &volatilep); + poffset, &mode, &unsignedp, &volatilep, + false); if (TREE_CODE (core) == INDIRECT_REF) core = TREE_OPERAND (core, 0); diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c index 6935cf5..d1a1bdd 100644 --- a/gcc/tree-ssa-loop-ivopts.c +++ b/gcc/tree-ssa-loop-ivopts.c @@ -2829,7 +2829,7 @@ split_address_cost (struct ivopts_data *data, int unsignedp, volatilep; core = get_inner_reference (addr, &bitsize, &bitpos, &toffset, &mode, - &unsignedp, &volatilep); + &unsignedp, &volatilep, false); if (toffset != 0 || bitpos % BITS_PER_UNIT != 0 -- 2.7.4