re PR tree-optimization/33870 (miscompiles sqlite)
authorRichard Guenther <rguenther@suse.de>
Sat, 27 Oct 2007 11:10:09 +0000 (11:10 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Sat, 27 Oct 2007 11:10:09 +0000 (11:10 +0000)
2007-10-27  Richard Guenther  <rguenther@suse.de>

PR tree-optimization/33870
* tree-ssa-operands.c (add_vars_for_offset): Reduce code
duplication.  Remove redundant call to access_can_touch_variable.
(add_vars_for_bitmap): New helper for recursing over MPT contents.
(add_virtual_operand): Use it.

* gcc.dg/tree-ssa/alias-15.c: New testcase.
* gcc.c-torture/execute/pr33870.c: Likewise.

From-SVN: r129675

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/pr33870.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/alias-15.c [new file with mode: 0644]
gcc/tree-ssa-operands.c

index 89fe24d575b956a44f87c5319167b4671d1d19f4..78bb02d48f64e71c904dd681899543c5a5ff6c2e 100644 (file)
@@ -1,3 +1,11 @@
+2007-10-27  Richard Guenther  <rguenther@suse.de>
+
+       PR tree-optimization/33870
+       * tree-ssa-operands.c (add_vars_for_offset): Reduce code
+       duplication.  Remove redundant call to access_can_touch_variable.
+       (add_vars_for_bitmap): New helper for recursing over MPT contents.
+       (add_virtual_operand): Use it.
+
 2007-10-26  John David Anglin  <dave.anglin@nrc-cnrc.gc.ca>
 
        PR fortran/31608
index 6e21d3f741231d9f9b2e3f19d5cd3b4ae4145a9b..6d69fa1776b403a976bd2ea953890022db944a59 100644 (file)
@@ -1,3 +1,9 @@
+2007-10-27  Richard Guenther  <rguenther@suse.de>
+
+       PR tree-optimization/33870
+       * gcc.dg/tree-ssa/alias-15.c: New testcase.
+       * gcc.c-torture/execute/pr33870.c: Likewise.
+
 2007-10-26  Jerry DeLisle  <jvdelisle@gcc.gnu.org>
 
        PR fortran/33162
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr33870.c b/gcc/testsuite/gcc.c-torture/execute/pr33870.c
new file mode 100644 (file)
index 0000000..9189b4a
--- /dev/null
@@ -0,0 +1,87 @@
+extern void abort (void);
+
+typedef struct PgHdr PgHdr;
+typedef unsigned char u8;
+struct PgHdr {
+  unsigned int pgno;
+  PgHdr *pNextHash, *pPrevHash;
+  PgHdr *pNextFree, *pPrevFree;
+  PgHdr *pNextAll;
+  u8 inJournal;
+  short int nRef;
+  PgHdr *pDirty, *pPrevDirty;
+  unsigned int notUsed;
+};
+
+static inline PgHdr *merge_pagelist(PgHdr *pA, PgHdr *pB)
+{
+  PgHdr result;
+  PgHdr *pTail;
+  pTail = &result;
+  while( pA && pB ){
+    if( pA->pgno<pB->pgno ){
+      pTail->pDirty = pA;
+      pTail = pA;
+      pA = pA->pDirty;
+    }else{
+      pTail->pDirty = pB;
+      pTail = pB;
+      pB = pB->pDirty;
+    }
+  }
+  if( pA ){
+    pTail->pDirty = pA;
+  }else if( pB ){
+    pTail->pDirty = pB;
+  }else{
+    pTail->pDirty = 0;
+  }
+  return result.pDirty;
+}
+
+PgHdr * __attribute__((noinline)) sort_pagelist(PgHdr *pIn)
+{
+  PgHdr *a[25], *p;
+  int i;
+  __builtin_memset (a, 0, sizeof (a));
+  while( pIn ){
+    p = pIn;
+    pIn = p->pDirty;
+    p->pDirty = 0;
+    for(i=0; i<25 -1; i++){
+      if( a[i]==0 ){
+        a[i] = p;
+        break;
+      }else{
+        p = merge_pagelist(a[i], p);
+        a[i] = 0;
+      }
+    }
+    if( i==25 -1 ){
+      a[i] = merge_pagelist(a[i], p);
+    }
+  }
+  p = a[0];
+  for(i=1; i<25; i++){
+    p = merge_pagelist (p, a[i]);
+  }
+  return p;
+}
+
+int main()
+{
+  PgHdr a[5];
+  PgHdr *p;
+  a[0].pgno = 5;
+  a[0].pDirty = &a[1];
+  a[1].pgno = 4;
+  a[1].pDirty = &a[2];
+  a[2].pgno = 1;
+  a[2].pDirty = &a[3];
+  a[3].pgno = 3;
+  a[3].pDirty = 0;
+  p = sort_pagelist (&a[0]);
+  if (p->pDirty == p)
+    abort ();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-15.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-15.c
new file mode 100644 (file)
index 0000000..9e409f0
--- /dev/null
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fno-early-inlining -fdump-tree-salias-vops-details" } */
+
+struct foo {
+  int a;
+  struct X {
+    int b[4];
+  } b;
+} m;
+static inline struct X *wrap(struct X *p) { return p; }
+int test2(void)
+{
+  struct X *p = wrap(&m.b);
+  /* Both memory references need to alias the same SFT.  */
+  return p->b[3] - m.b.b[3];
+}
+
+/* { dg-final { scan-tree-dump "SFT.1 created for var m offset 128" "salias" } } */
+/* { dg-final { scan-tree-dump-times "VUSE <SFT.1_" 2 "salias" } } */
+/* { dg-final { cleanup-tree-dump "salias" } } */
index 3a944efa0b364f886d7fbfa920acc507e413070d..206c04bd484ddc6e6c855582baf4c24b237299ef 100644 (file)
@@ -1419,55 +1419,57 @@ add_vars_for_offset (tree full_ref, tree var, HOST_WIDE_INT offset,
     }
   else if (TREE_CODE (var) == STRUCT_FIELD_TAG)
     {      
-      if (size == -1)
+      bool added = false;
+      subvar_t sv = get_subvars_for_var (SFT_PARENT_VAR (var));
+      for (; sv; sv = sv->next)
        {
-         bool added = false;
-         subvar_t sv = get_subvars_for_var (SFT_PARENT_VAR (var));
-         for (; sv; sv = sv->next)
-           {
-             if (overlap_subvar (SFT_OFFSET (var) + offset, size,
-                                 sv->var, NULL)
-                 && access_can_touch_variable (full_ref, sv->var,
-                                               offset, size))
-               {
-                 added = true;
-                 if (is_def)
-                   append_vdef (sv->var);
-                 else
-                   append_vuse (sv->var);
-               }
-           }
-         return added;
-       }
-      else
-       {
-         bool added = false;
-         subvar_t sv = get_subvars_for_var (SFT_PARENT_VAR (var));
-         for (; sv; sv = sv->next)
+         /* Once we hit the end of the parts that could touch,
+            stop looking.  */
+         if (size != -1
+             && SFT_OFFSET (var) + offset + size <= SFT_OFFSET (sv->var))
+           break;
+         if (overlap_subvar (SFT_OFFSET (var) + offset, size, sv->var, NULL))
            {
-             /* Once we hit the end of the parts that could touch,
-                stop looking.  */
-             if (SFT_OFFSET (var) + offset + size <= SFT_OFFSET (sv->var))
-               break;
-             if (overlap_subvar (SFT_OFFSET (var) + offset, size,
-                                 sv->var, NULL)
-                 && access_can_touch_variable (full_ref, sv->var, offset, 
-                                               size))
-               {
-                 added = true;
-                 if (is_def)
-                   append_vdef (sv->var);
-                 else
-                   append_vuse (sv->var);
-               }
+             added = true;
+             if (is_def)
+               append_vdef (sv->var);
+             else
+               append_vuse (sv->var);
            }
-         return added;
        }
+      return added;
     }
   
   return false;
 }
 
+/* Add all aliases from ALIASES as virtual operands for the access
+   FULL_REF at OFFSET and size SIZE.  IS_CALL_SITE is true if the
+   stmt of the reference is a call.  IS_DEF is true if we should add
+   VDEF virtual operands, otherwise we'll add VUSEs.  *NONE_ADDED
+   is set to false once the first virtual operand was added.  */
+
+static void
+add_vars_for_bitmap (bitmap aliases, tree full_ref,
+                    HOST_WIDE_INT offset, HOST_WIDE_INT size,
+                    bool is_call_site, bool is_def, bool *none_added)
+{
+  bitmap_iterator bi;
+  unsigned int i;
+
+  EXECUTE_IF_SET_IN_BITMAP (aliases, 0, i, bi)
+    {
+      tree al = referenced_var (i);
+
+      if (TREE_CODE (al) == MEMORY_PARTITION_TAG)
+       add_vars_for_bitmap (MPT_SYMBOLS (al), full_ref,
+                            offset, size, is_call_site, is_def, none_added);
+      else
+       *none_added &= !add_vars_for_offset (full_ref, al, offset, size,
+                                            is_call_site, is_def);
+    }
+}
+
 /* Add VAR to the virtual operands array.  FLAGS is as in
    get_expr_operands.  FULL_REF is a tree that contains the entire
    pointer dereference expression, if available, or NULL otherwise.
@@ -1530,24 +1532,17 @@ add_virtual_operand (tree var, stmt_ann_t s_ann, int flags,
     }
   else
     {
-      bitmap_iterator bi;
-      unsigned int i;
-      tree al;
+      bool none_added = true;
       
       /* The variable is aliased.  Add its aliases to the virtual
         operands.  */
       gcc_assert (!bitmap_empty_p (aliases));
-      
+
+      add_vars_for_bitmap (aliases, full_ref, offset, size,
+                          is_call_site, flags & opf_def, &none_added);
+
       if (flags & opf_def)
        {
-         bool none_added = true;
-         EXECUTE_IF_SET_IN_BITMAP (aliases, 0, i, bi)
-           {
-             al = referenced_var (i);
-             none_added &= !add_vars_for_offset (full_ref, al, offset, size,
-                                                 is_call_site, true);
-           }
-
          /* If the variable is also an alias tag, add a virtual
             operand for it, otherwise we will miss representing
             references to the members of the variable's alias set.          
@@ -1566,15 +1561,6 @@ add_virtual_operand (tree var, stmt_ann_t s_ann, int flags,
        }
       else
        {
-         bool none_added = true;
-         EXECUTE_IF_SET_IN_BITMAP (aliases, 0, i, bi)
-           {
-             al = referenced_var (i);
-             none_added &= !add_vars_for_offset (full_ref, al, offset, size,
-                                                 is_call_site, false);
-             
-           }
-         
          /* Even if no aliases have been added, we still need to
             establish def-use and use-def chains, lest
             transformations think that this is not a memory