diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4666f4cbed0..9784a999c5e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2010-07-09 Richard Guenther + + PR tree-optimization/44852 + * tree-ssa-alias.c: Include toplev.h for exact_log2. + (indirect_ref_may_alias_decl_p): Properly handle negative offsets + in MEM_REF. + (indirect_refs_may_alias_p): Likewise. + * Makefile.in (tree-ssa-alias.o): Add $(TOPLEV_H). + 2010-07-09 Richard Guenther PR tree-optimization/44882 diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 5e990066c86..a807e8e9d4a 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -2592,7 +2592,7 @@ tree-ssa-alias.o : tree-ssa-alias.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \ $(TREE_DUMP_H) $(TREE_PASS_H) $(PARAMS_H) $(BASIC_BLOCK_H) $(DIAGNOSTIC_H) \ $(GIMPLE_H) $(VEC_H) \ $(IPA_TYPE_ESCAPE_H) vecprim.h pointer-set.h alloc-pool.h \ - tree-pretty-print.h + tree-pretty-print.h $(TOPLEV_H) tree-ssa-reassoc.o : tree-ssa-reassoc.c $(TREE_FLOW_H) $(CONFIG_H) \ $(SYSTEM_H) $(TREE_H) $(DIAGNOSTIC_H) $(TIMEVAR_H) \ $(TM_H) coretypes.h $(TREE_DUMP_H) $(TREE_PASS_H) $(FLAGS_H) \ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index fc80a9361c6..332664e2bd1 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2010-07-09 Richard Guenther + + PR tree-optimization/44852 + * gcc.c-torture/execute/pr44852.c: New testcase. + 2010-07-09 Rainer Orth * gcc.target/x86_64/abi/asm-support.S (snapshot): Replace diff --git a/gcc/testsuite/gcc.c-torture/execute/pr44852.c b/gcc/testsuite/gcc.c-torture/execute/pr44852.c new file mode 100644 index 00000000000..440653e5f17 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr44852.c @@ -0,0 +1,22 @@ +__attribute__ ((__noinline__)) +char *sf(char *s, char *s0) +{ + asm (""); + while (*--s == '9') + if (s == s0) + { + *s = '0'; + break; + } + ++*s++; + return s; +} + +int main() +{ + char s[] = "999999"; + char *x = sf (s+2, s); + if (x != s+1 || __builtin_strcmp (s, "199999") != 0) + __builtin_abort (); + return 0; +} diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c index 24608048458..d73ff5965f0 100644 --- a/gcc/tree-ssa-alias.c +++ b/gcc/tree-ssa-alias.c @@ -30,6 +30,7 @@ along with GCC; see the file COPYING3. If not see #include "ggc.h" #include "langhooks.h" #include "flags.h" +#include "toplev.h" #include "function.h" #include "tree-pretty-print.h" #include "tree-dump.h" @@ -688,17 +689,29 @@ indirect_ref_may_alias_decl_p (tree ref1 ATTRIBUTE_UNUSED, tree base1, { tree ptr1 = TREE_OPERAND (base1, 0); tree ptrtype1; - HOST_WIDE_INT offset1p = offset1; + HOST_WIDE_INT offset1p = offset1, offset2p = offset2; + /* The offset embedded in MEM_REFs can be negative. Bias them + so that the resulting offset adjustment is positive. */ if (TREE_CODE (base1) == MEM_REF) - offset1p = offset1 + mem_ref_offset (base1).low * BITS_PER_UNIT; + { + double_int moff = mem_ref_offset (base1); + moff = double_int_lshift (moff, + BITS_PER_UNIT == 8 + ? 3 : exact_log2 (BITS_PER_UNIT), + HOST_BITS_PER_DOUBLE_INT, true); + if (double_int_negative_p (moff)) + offset2p += double_int_neg (moff).low; + else + offset1p += moff.low; + } /* If only one reference is based on a variable, they cannot alias if the pointer access is beyond the extent of the variable access. (the pointer base cannot validly point to an offset less than zero of the variable). They also cannot alias if the pointer may not point to the decl. */ - if (!ranges_overlap_p (MAX (0, offset1p), -1, offset2, max_size2)) + if (!ranges_overlap_p (MAX (0, offset1p), -1, offset2p, max_size2)) return false; if (!ptr_deref_may_alias_decl_p (ptr1, base2)) return false; @@ -804,10 +817,32 @@ indirect_refs_may_alias_p (tree ref1 ATTRIBUTE_UNUSED, tree base1, if ((!cfun || gimple_in_ssa_p (cfun)) && operand_equal_p (ptr1, ptr2, 0)) { + /* The offset embedded in MEM_REFs can be negative. Bias them + so that the resulting offset adjustment is positive. */ if (TREE_CODE (base1) == MEM_REF) - offset1 += mem_ref_offset (base1).low * BITS_PER_UNIT; + { + double_int moff = mem_ref_offset (base1); + moff = double_int_lshift (moff, + BITS_PER_UNIT == 8 + ? 3 : exact_log2 (BITS_PER_UNIT), + HOST_BITS_PER_DOUBLE_INT, true); + if (double_int_negative_p (moff)) + offset2 += double_int_neg (moff).low; + else + offset1 += moff.low; + } if (TREE_CODE (base2) == MEM_REF) - offset2 += mem_ref_offset (base2).low * BITS_PER_UNIT; + { + double_int moff = mem_ref_offset (base2); + moff = double_int_lshift (moff, + BITS_PER_UNIT == 8 + ? 3 : exact_log2 (BITS_PER_UNIT), + HOST_BITS_PER_DOUBLE_INT, true); + if (double_int_negative_p (moff)) + offset1 += double_int_neg (moff).low; + else + offset2 += moff.low; + } return ranges_overlap_p (offset1, max_size1, offset2, max_size2); } if (!ptr_derefs_may_alias_p (ptr1, ptr2))