This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix PR24851 (2nd version)
On Tue, 15 Nov 2005, Richard Guenther wrote:
> I have a patch along Andrews that fixes both testcases. I'll post it as
> soon as testing finishes.
Here it is. It fixes fold and fold_stmt to use signed division in
recombining pointer + offset to an ARRAY_REF. I'm not sure this is
a correct fix, but it passes bootstrap and regtesting (32 and 64 bit)
on x86_64-unknown-linux-gnu for all default languages.
What do you think?
Richard.
2005-11-15 Richard Guenther <rguenther@suse.de>
PR middle-end/24851
* fold-const.c (try_move_mult_to_index): Make sure to
use a signed division for ptr-offset / element-size.
* tree-ssa-ccp.c (maybe_fold_offset_to_array_ref): Likewise.
* gcc.c-torture/execute/pr24851.c: New testcase.
Index: fold-const.c
===================================================================
--- fold-const.c (revision 106944)
+++ fold-const.c (working copy)
@@ -6450,11 +6450,16 @@ try_move_mult_to_index (enum tree_code c
}
else
{
- /* Try if delta is a multiple of step. */
- tree tmp = div_if_zero_remainder (EXACT_DIV_EXPR, delta, step);
+ /* Try if delta is a multiple of step. Make sure to
+ use a signed division to correctly handle addition of
+ -4B which is represented as unsigned 4294967292B.
+ ??? This may break deliberate use of such large
+ unsigned offsets. */
+ tree sdelta = fold_convert (signed_type_for (TREE_TYPE (step)), delta);
+ tree tmp = div_if_zero_remainder (EXACT_DIV_EXPR, sdelta, step);
if (! tmp)
continue;
- delta = tmp;
+ delta = fold_convert (TREE_TYPE (delta), tmp);
}
break;
Index: tree-ssa-ccp.c
===================================================================
--- tree-ssa-ccp.c (revision 106944)
+++ tree-ssa-ccp.c (working copy)
@@ -1522,18 +1522,24 @@ maybe_fold_offset_to_array_ref (tree bas
{
unsigned HOST_WIDE_INT lquo, lrem;
HOST_WIDE_INT hquo, hrem;
+ tree stype = signed_type_for (TREE_TYPE (elt_size));
+ tree soffset = fold_convert (stype, offset);
+ /* Make sure we do the divide in a singed mode to handle
+ negative offsets represented as unsigned, like -4B.
+ ??? This may break deliberate use of such large
+ unsigned offsets. */
if (TREE_CODE (elt_size) != INTEGER_CST
- || div_and_round_double (TRUNC_DIV_EXPR, 1,
- TREE_INT_CST_LOW (offset),
- TREE_INT_CST_HIGH (offset),
+ || div_and_round_double (TRUNC_DIV_EXPR, 0,
+ TREE_INT_CST_LOW (soffset),
+ TREE_INT_CST_HIGH (soffset),
TREE_INT_CST_LOW (elt_size),
TREE_INT_CST_HIGH (elt_size),
&lquo, &hquo, &lrem, &hrem)
|| lrem || hrem)
return NULL_TREE;
- idx = build_int_cst_wide (NULL_TREE, lquo, hquo);
+ idx = build_int_cst_wide (stype, lquo, hquo);
}
/* Assume the low bound is zero. If there is a domain type, get the
/* We used to handle pointer addition wrongly
at the time of recombining to an ARRAY_REF
in the case of
p + -4B
where -4B is represented as unsigned. */
void abort(void);
int main()
{
int a[10], *p, *q;
q = &a[1];
p = &q[-1];
if (p >= &a[9])
abort ();
return 0;
}