public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* Fix PR 33870
@ 2007-11-08  0:24 Diego Novillo
  2007-11-08  0:35 ` Jakub Jelinek
  2007-11-08 10:45 ` Richard Guenther
  0 siblings, 2 replies; 18+ messages in thread
From: Diego Novillo @ 2007-11-08  0:24 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 3397 bytes --]

This patch fixes PR 33870.  There were a couple of things at play here
related to the way we compute sub-variables for structures and arrays.
 Particularly in the presence of nesting.

When alias analysis computes points-to information for a structure for
which we have sub-variables, it never adds all the variables to the
set.  It only adds the first SFT reachable by the pointer.

So, if we have a pointer p_1 pointing into some structure and we
dereference a field with p_1->fld, we can find out what offset to use
by calling get_base_ref_and_extent.  However, if that field is 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 need to adjust the offset given by
get_base_ref_and_extent by the offset of VAR so that we can get at all
the fields starting at VAR.

Notice that this adjustment is ONLY necessary if the pointer is
pointing inside a nested structure.  If p_1 is pointing at the base
structure of the nesting hierarchy, then no adjustment is necessary.

Since this adjustment was being applied with every field reference, we
were failing to add SFTs when some of the SFTs in the structure had
been partitioned away into an MPT.

In the specific case of PR 33870, there was a single field 'pDirty'
inside a large structure that was being referenced with a pointer and
with a regular variable.  The field had the subvariable SFT.12
associated with it, with an offset of X bytes.

Since SFT.12 was the only field that had not been partitioned away,
when we were adding SFTs in the operand scanner, we would blindly
adjust the offset of SFT.12 by X bytes and then trying to see if there
was any SFT at offset X + X.

There wasn't any, of course, and so no VOP was added to the memory
load expression, which was then taken out of the loop because it was
thought to be loop independent.  Leading to the runtime failure.

The only reason this didn't occur if partitioning was disabled was
that the same blind offset adjustment was adding SFT.12 because it had
ajdusted the offset of an SFT that was X bytes earlier in the
structure.  So, it was working by chance.

By recognizing that this offset adjustment is only required for nested
structures, we do not need to blindly adjust every offset and so we
don't end up adding SFTs by accident.

Tested on x86_64.  Committed.

[-- Attachment #2: 20071107-33870.diff.txt --]
[-- Type: text/plain, Size: 7676 bytes --]

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

testsuite/ChangeLog

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

Index: tree.h
===================================================================
--- tree.h	(revision 129956)
+++ tree.h	(working copy)
@@ -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.  */
Index: testsuite/gcc.c-torture/execute/pr33870.x
===================================================================
--- testsuite/gcc.c-torture/execute/pr33870.x	(revision 129956)
+++ testsuite/gcc.c-torture/execute/pr33870.x	(working copy)
@@ -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: tree-dfa.c
===================================================================
--- tree-dfa.c	(revision 129956)
+++ tree-dfa.c	(working copy)
@@ -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: tree-flow.h
===================================================================
--- tree-flow.h	(revision 129956)
+++ tree-flow.h	(working copy)
@@ -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: tree-ssa-structalias.c
===================================================================
--- tree-ssa-structalias.c	(revision 129956)
+++ tree-ssa-structalias.c	(working copy)
@@ -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, 
 		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, 
 	      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, con
 	  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
 		      || (!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: tree-ssa-operands.c
===================================================================
--- tree-ssa-operands.c	(revision 129956)
+++ tree-ssa-operands.c	(working copy)
@@ -1397,8 +1397,48 @@ add_vars_for_offset (tree var, unsigned 
   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.  */

^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2007-11-15 13:37 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-11-08  0:24 Fix PR 33870 Diego Novillo
2007-11-08  0:35 ` Jakub Jelinek
2007-11-08  2:20   ` Diego Novillo
2007-11-08 10:45 ` Richard Guenther
2007-11-13 16:30   ` Diego Novillo
2007-11-13 16:47     ` Richard Guenther
2007-11-14 12:36       ` Richard Guenther
2007-11-14 12:41         ` Richard Guenther
2007-11-14 13:01           ` Diego Novillo
2007-11-14 13:18             ` Richard Guenther
2007-11-14 13:59               ` Diego Novillo
2007-11-14 14:07                 ` Richard Guenther
2007-11-14 14:09                   ` Diego Novillo
2007-11-14 14:22                     ` Richard Guenther
2007-11-14 15:29                       ` Richard Guenther
2007-11-14 15:30                         ` Diego Novillo
2007-11-15 13:55                           ` Richard Guenther
2007-11-15 15:47                             ` Richard Guenther

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).