re PR tree-optimization/33870 (miscompiles sqlite)
authorDiego Novillo <dnovillo@google.com>
Thu, 8 Nov 2007 00:01:38 +0000 (19:01 -0500)
committerDiego Novillo <dnovillo@gcc.gnu.org>
Thu, 8 Nov 2007 00:01:38 +0000 (19:01 -0500)
PR 33870
* tree.h (struct tree_struct_field_tag): Add field in_nested_struct.
(SFT_IN_NESTED_STRUCT): Define.
* tree-dfa.c (dump_subvars_for): Show offset of each
sub-var.
* tree-flow.h (struct fieldoff): Add field in_nested_struct.
* tree-ssa-structalias.c (struct variable_info): Likewise.
(push_fields_onto_fieldstack): If OFFSET is positive,
set in_nested_struct.
(create_variable_info_for): Copy setting of
in_nested_struct from the field offset object.
(set_uids_in_ptset): Set SFT_IN_NESTED_STRUCT from the
variable info object.
* tree-ssa-operands.c (add_vars_for_offset): If VAR
belongs to a nested structure, adjust OFFSET by
SFT_OFFSET(VAR).

testsuite/ChangeLog

* gcc.c-torture/execute/pr33870.x: Remove.

From-SVN: r129976

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/pr33870.x [deleted file]
gcc/tree-dfa.c
gcc/tree-flow.h
gcc/tree-ssa-operands.c
gcc/tree-ssa-structalias.c
gcc/tree.h

index 7cbf17f..efc6293 100644 (file)
@@ -1,3 +1,22 @@
+2007-11-07  Diego Novillo  <dnovillo@google.com>
+
+       PR 33870
+       * tree.h (struct tree_struct_field_tag): Add field in_nested_struct.
+       (SFT_IN_NESTED_STRUCT): Define.
+       * tree-dfa.c (dump_subvars_for): Show offset of each
+       sub-var.
+       * tree-flow.h (struct fieldoff): Add field in_nested_struct.
+       * tree-ssa-structalias.c (struct variable_info): Likewise.
+       (push_fields_onto_fieldstack): If OFFSET is positive,
+       set in_nested_struct.
+       (create_variable_info_for): Copy setting of
+       in_nested_struct from the field offset object.
+       (set_uids_in_ptset): Set SFT_IN_NESTED_STRUCT from the
+       variable info object.
+       * tree-ssa-operands.c (add_vars_for_offset): If VAR
+       belongs to a nested structure, adjust OFFSET by
+       SFT_OFFSET(VAR).
+
 2007-11-07  Eric Botcazou  <ebotcazou@libertysurf.fr>
 
        PR rtl-optimization/33737
index 063d20f..2a863b9 100644 (file)
@@ -1,3 +1,8 @@
+2007-11-07  Diego Novillo  <dnovillo@google.com>
+
+       PR 33870
+       * gcc.c-torture/execute/pr33870.x: Remove.
+
 2007-11-07  Douglas Gregor  <doug.gregor@gmail.com>
 
        PR c++/33045
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr33870.x b/gcc/testsuite/gcc.c-torture/execute/pr33870.x
deleted file mode 100644 (file)
index fbf8aae..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-# The test breaks because of wrong alias info for -O2 and -Os
-
-set torture_eval_before_compile {
-  if {[string match {*-O[2s]*} "$option"]} {
-     set torture_execute_xfail "*-*-*"
-  }
-}
-
-return 0
index 1ec0264..6ee90d7 100644 (file)
@@ -287,7 +287,7 @@ dump_subvars_for (FILE *file, tree var)
   for (i = 0; VEC_iterate (tree, sv, i, subvar); ++i)
     {
       print_generic_expr (file, subvar, dump_flags);
-      fprintf (file, " ");
+      fprintf (file, "@" HOST_WIDE_INT_PRINT_UNSIGNED " ", SFT_OFFSET (subvar));
     }
 
   fprintf (file, "}");
index 3421c14..1b63e95 100644 (file)
@@ -1159,6 +1159,10 @@ struct fieldoff
   /* Field.  */
   tree decl;
 
+  /* True if this field is inside a structure nested inside the base
+     containing object.  */
+  unsigned int in_nested_struct : 1;
+
   /* Offset from the base of the base containing object to this field.  */
   HOST_WIDE_INT offset;  
 
index 9ce133d..87eec74 100644 (file)
@@ -1397,8 +1397,48 @@ add_vars_for_offset (tree var, unsigned HOST_WIDE_INT offset,
   subvar_t sv;
   unsigned int i;
 
-  /* Adjust offset by the pointed-to location.  */
-  offset += SFT_OFFSET (var);
+  if (SFT_IN_NESTED_STRUCT (var))
+    {
+      /* Since VAR is an SFT inside a nested structure, the OFFSET
+        computed by get_ref_base_and_extent is the offset from the
+        start of the immediately containing structure.  However, to
+        find out what other SFTs are affected by this reference, we
+        need to know the offsets starting at the root structure in
+        the nesting hierarchy.
+
+        For instance, given the following structure:
+
+               struct X {
+                 int a;
+                 struct Y {
+                   int b;
+                   struct Z {
+                     int c[3];
+                   } d;
+                 } e;
+               } m;
+
+        and the following address expression:
+
+               p_1 = &m.e.d;
+
+        This structure will receive 5 SFTs, namely 2 for fields 'a'
+        and 'b' and 3 for the array 'c' in struct Z.  So, the
+        reference p_1->c[2] and m.e.d.c[2] access the exact same
+        memory location (ie, SFT.5).
+
+        Now, alias analysis computed the points-to set for pointer
+        p_1 as  { SFT.3 } because that is the first field that p_1
+        actually points to.  When the expression p_1->c[2] is
+        analyzed, get_ref_base_and_extent will return an offset of 96
+        because we are accessing the third element of the array.  But
+        the SFT we are looking for is actually at offset 160,
+        counting from the top of struct X.
+
+        Therefore, we adjust OFFSET by the offset of VAR so that we
+        can get at all the fields starting at VAR.  */
+      offset += SFT_OFFSET (var);
+    }
 
   /* Add all subvars of var that overlap with the access.
      Binary search for the first relevant SFT.  */
index 0212499..2d3a40a 100644 (file)
@@ -253,6 +253,15 @@ struct variable_info
      variable.  This is used for C++ placement new.  */
   unsigned int no_tbaa_pruning : 1;
 
+  /* True if this variable is inside a structure nested in the
+     structure for the base variable.  For instance, in 
+     struct X { int a; struct Y { int b; int c; } }, the variables for
+     fields 'b' and 'c' are inside a nested structure.  We are not
+     interested in tracking how many levels of nesting, just whether
+     there is nesting at all.  This is later used to adjust offsets
+     for pointers pointing into sub-structures.  */
+  unsigned int in_nested_struct : 1;
+
   /* Points-to set for this variable.  */
   bitmap solution;
 
@@ -4133,6 +4142,12 @@ push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack,
                pair->alias_set = get_alias_set (addressable_type);
              else
                pair->alias_set = -1;
+
+             /* If the base offset is positive, this field belongs to
+                a structure nested inside the base structure.  */
+             if (offset > 0)
+               pair->in_nested_struct = true;
+
              count++;
            }
          else
@@ -4181,6 +4196,12 @@ push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack,
              pair->alias_set = get_alias_set (addressable_type);
            else
              pair->alias_set = -1;
+
+           /* If the base offset is positive, this field belongs to
+              a structure nested inside the base structure.  */
+           if (offset > 0)
+             pair->in_nested_struct = true;
+
            count++;
          }
        else
@@ -4491,6 +4512,7 @@ create_variable_info_for (tree decl, const char *name)
          newvi->offset = fo->offset;
          newvi->size = TREE_INT_CST_LOW (fo->size);
          newvi->fullsize = vi->fullsize;
+         newvi->in_nested_struct = fo->in_nested_struct;
          insert_into_field_list (vi, newvi);
          VEC_safe_push (varinfo_t, heap, varmap, newvi);
          if (is_global && (!flag_whole_program || !in_ipa_mode))
@@ -4743,6 +4765,7 @@ set_uids_in_ptset (tree ptr, bitmap into, bitmap from, bool is_derefed,
                      || (!is_derefed && !vi->directly_dereferenced)
                      || alias_sets_conflict_p (ptr_alias_set, var_alias_set))
                    bitmap_set_bit (into, DECL_UID (sft));
+                 SFT_IN_NESTED_STRUCT (sft) = vi->in_nested_struct;
                }
            }
          else
@@ -4946,7 +4969,6 @@ find_what_p_points_to (tree p)
            }
 
          /* Share the final set of variables when possible.  */
-
          finished_solution = BITMAP_GGC_ALLOC ();
          stats.points_to_sets_created++;
 
index ede0cd8..d82ce85 100644 (file)
@@ -2573,15 +2573,21 @@ struct tree_struct_field_tag GTY(())
   /* Size of the field.  */
   unsigned HOST_WIDE_INT size;
 
+  /* True if this SFT is for a field in a nested structure.  */
+  unsigned int in_nested_struct : 1;
+
   /* Alias set for a DECL_NONADDRESSABLE_P field.  Otherwise -1.  */
   alias_set_type alias_set;
 };
+
 #define SFT_PARENT_VAR(NODE) (STRUCT_FIELD_TAG_CHECK (NODE)->sft.parent_var)
 #define SFT_OFFSET(NODE) (STRUCT_FIELD_TAG_CHECK (NODE)->sft.offset)
 #define SFT_SIZE(NODE) (STRUCT_FIELD_TAG_CHECK (NODE)->sft.size)
 #define SFT_NONADDRESSABLE_P(NODE) \
   (STRUCT_FIELD_TAG_CHECK (NODE)->sft.alias_set != -1)
 #define SFT_ALIAS_SET(NODE) (STRUCT_FIELD_TAG_CHECK (NODE)->sft.alias_set)
+#define SFT_IN_NESTED_STRUCT(NODE) \
+  (STRUCT_FIELD_TAG_CHECK (NODE)->sft.in_nested_struct)
 
 /* Memory Partition Tags (MPTs) group memory symbols under one
    common name for the purposes of placing memory PHI nodes.  */