diff options
-rw-r--r-- | gcc/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/fold-const.c | 129 |
2 files changed, 22 insertions, 114 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 536ef54..12452b5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2007-10-15 Richard Guenther <rguenther@suse.de> + + * fold-const.c (extract_array_ref): Remove. + (fold_comparison): Handle POINTER_PLUS_EXPR with the + generic address expression comparison folding. Remove + the folding that used extract_array_ref. + 2007-10-15 Maxim Kuvyrkov <maxim@codesourcery.com> PR target/33133 diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 4a8153c..fd5a708 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -6322,76 +6322,6 @@ constant_boolean_node (int value, tree type) } -/* Return true if expr looks like an ARRAY_REF and set base and - offset to the appropriate trees. If there is no offset, - offset is set to NULL_TREE. Base will be canonicalized to - something you can get the element type from using - TREE_TYPE (TREE_TYPE (base)). Offset will be the offset - in bytes to the base in sizetype. */ - -static bool -extract_array_ref (tree expr, tree *base, tree *offset) -{ - /* One canonical form is a PLUS_EXPR with the first - argument being an ADDR_EXPR with a possible NOP_EXPR - attached. */ - if (TREE_CODE (expr) == POINTER_PLUS_EXPR) - { - tree op0 = TREE_OPERAND (expr, 0); - tree inner_base, dummy1; - /* Strip NOP_EXPRs here because the C frontends and/or - folders present us (int *)&x.a p+ 4 possibly. */ - STRIP_NOPS (op0); - if (extract_array_ref (op0, &inner_base, &dummy1)) - { - *base = inner_base; - *offset = fold_convert (sizetype, TREE_OPERAND (expr, 1)); - if (dummy1 != NULL_TREE) - *offset = fold_build2 (PLUS_EXPR, sizetype, - dummy1, *offset); - return true; - } - } - /* Other canonical form is an ADDR_EXPR of an ARRAY_REF, - which we transform into an ADDR_EXPR with appropriate - offset. For other arguments to the ADDR_EXPR we assume - zero offset and as such do not care about the ADDR_EXPR - type and strip possible nops from it. */ - else if (TREE_CODE (expr) == ADDR_EXPR) - { - tree op0 = TREE_OPERAND (expr, 0); - if (TREE_CODE (op0) == ARRAY_REF) - { - tree idx = TREE_OPERAND (op0, 1); - *base = TREE_OPERAND (op0, 0); - *offset = fold_build2 (MULT_EXPR, TREE_TYPE (idx), idx, - array_ref_element_size (op0)); - *offset = fold_convert (sizetype, *offset); - } - else - { - /* Handle array-to-pointer decay as &a. */ - if (TREE_CODE (TREE_TYPE (op0)) == ARRAY_TYPE) - *base = TREE_OPERAND (expr, 0); - else - *base = expr; - *offset = NULL_TREE; - } - return true; - } - /* The next canonical form is a VAR_DECL with POINTER_TYPE. */ - else if (SSA_VAR_P (expr) - && TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE) - { - *base = expr; - *offset = NULL_TREE; - return true; - } - - return false; -} - - /* Transform `a + (b ? x : y)' into `b ? (a + x) : (a + y)'. Transform, `a + (x < y)' into `(x < y) ? (a + 1) : (a + 0)'. Here CODE corresponds to the `+', COND to the `(b ? x : y)' or `(x < y)' @@ -8802,11 +8732,13 @@ fold_comparison (enum tree_code code, tree type, tree op0, tree op1) /* For comparisons of pointers we can decompose it to a compile time comparison of the base objects and the offsets into the object. - This requires at least one operand being an ADDR_EXPR to do more - than the operand_equal_p test below. */ + This requires at least one operand being an ADDR_EXPR or a + POINTER_PLUS_EXPR to do more than the operand_equal_p test below. */ if (POINTER_TYPE_P (TREE_TYPE (arg0)) && (TREE_CODE (arg0) == ADDR_EXPR - || TREE_CODE (arg1) == ADDR_EXPR)) + || TREE_CODE (arg1) == ADDR_EXPR + || TREE_CODE (arg0) == POINTER_PLUS_EXPR + || TREE_CODE (arg1) == POINTER_PLUS_EXPR)) { tree base0, base1, offset0 = NULL_TREE, offset1 = NULL_TREE; HOST_WIDE_INT bitsize, bitpos0 = 0, bitpos1 = 0; @@ -8828,6 +8760,11 @@ fold_comparison (enum tree_code code, tree type, tree op0, tree op1) else indirect_base0 = true; } + else if (TREE_CODE (arg0) == POINTER_PLUS_EXPR) + { + base0 = TREE_OPERAND (arg0, 0); + offset0 = TREE_OPERAND (arg0, 1); + } base1 = arg1; if (TREE_CODE (arg1) == ADDR_EXPR) @@ -8843,6 +8780,11 @@ fold_comparison (enum tree_code code, tree type, tree op0, tree op1) else if (!indirect_base0) base1 = NULL_TREE; } + else if (TREE_CODE (arg1) == POINTER_PLUS_EXPR) + { + base1 = TREE_OPERAND (arg1, 0); + offset1 = TREE_OPERAND (arg1, 1); + } else if (indirect_base0) base1 = NULL_TREE; @@ -8904,47 +8846,6 @@ fold_comparison (enum tree_code code, tree type, tree op0, tree op1) } } - /* If this is a comparison of two exprs that look like an ARRAY_REF of the - same object, then we can fold this to a comparison of the two offsets in - signed size type. This is possible because pointer arithmetic is - restricted to retain within an object and overflow on pointer differences - is undefined as of 6.5.6/8 and /9 with respect to the signed ptrdiff_t. - - We check flag_wrapv directly because pointers types are unsigned, - and therefore TYPE_OVERFLOW_WRAPS returns true for them. That is - normally what we want to avoid certain odd overflow cases, but - not here. */ - if (POINTER_TYPE_P (TREE_TYPE (arg0)) - && !flag_wrapv - && !TYPE_OVERFLOW_TRAPS (TREE_TYPE (arg0))) - { - tree base0, offset0, base1, offset1; - - if (extract_array_ref (arg0, &base0, &offset0) - && extract_array_ref (arg1, &base1, &offset1) - && operand_equal_p (base0, base1, 0)) - { - tree signed_size_type_node; - signed_size_type_node = signed_type_for (size_type_node); - - /* By converting to signed size type we cover middle-end pointer - arithmetic which operates on unsigned pointer types of size - type size and ARRAY_REF offsets which are properly sign or - zero extended from their type in case it is narrower than - size type. */ - if (offset0 == NULL_TREE) - offset0 = build_int_cst (signed_size_type_node, 0); - else - offset0 = fold_convert (signed_size_type_node, offset0); - if (offset1 == NULL_TREE) - offset1 = build_int_cst (signed_size_type_node, 0); - else - offset1 = fold_convert (signed_size_type_node, offset1); - - return fold_build2 (code, type, offset0, offset1); - } - } - /* Transform comparisons of the form X +- C1 CMP Y +- C2 to X CMP Y +- C2 +- C1 for signed X, Y. This is valid if the resulting offset is smaller in absolute value than the |