re PR middle-end/44852 (miscompilation (of e.g. newlib dtoa.c) after mem-ref2 merge)
authorRichard Guenther <rguenther@suse.de>
Fri, 9 Jul 2010 11:24:09 +0000 (11:24 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Fri, 9 Jul 2010 11:24:09 +0000 (11:24 +0000)
2010-07-09  Richard Guenther  <rguenther@suse.de>

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).

* gcc.c-torture/execute/pr44852.c: New testcase.

From-SVN: r161994

gcc/ChangeLog
gcc/Makefile.in
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/pr44852.c [new file with mode: 0644]
gcc/tree-ssa-alias.c

index 4666f4cbed0158eea7ee49089ab6d4f08b8628d2..9784a999c5e01a314fb9b133c360731732ed7cde 100644 (file)
@@ -1,3 +1,12 @@
+2010-07-09  Richard Guenther  <rguenther@suse.de>
+
+       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  <rguenther@suse.de>
 
        PR tree-optimization/44882
index 5e990066c863e733d3785ccff93f13f56a406c03..a807e8e9d4a8a3de721a25d7a518331ebcef03b0 100644 (file)
@@ -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) \
index fc80a9361c6cda6957a20dfed70a9220c7047e6a..332664e2bd1b69b41e3024d7e8185a7ffeeaf5b0 100644 (file)
@@ -1,3 +1,8 @@
+2010-07-09  Richard Guenther  <rguenther@suse.de>
+
+       PR tree-optimization/44852
+       * gcc.c-torture/execute/pr44852.c: New testcase.
+
 2010-07-09  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>
 
        * 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 (file)
index 0000000..440653e
--- /dev/null
@@ -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;
+}
index 2460804845873a6e2c4bbe7275b1957958a5d4aa..d73ff5965f05729c577debf08d67bf6d20283b8a 100644 (file)
@@ -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))