public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] Final followup patch for PR33870
@ 2007-11-16 13:45 Richard Guenther
  2007-11-16 16:49 ` Diego Novillo
  0 siblings, 1 reply; 2+ messages in thread
From: Richard Guenther @ 2007-11-16 13:45 UTC (permalink / raw)
  To: gcc-patches; +Cc: dnovillo


This is the final followup patch for PR33870, it replaces 
SFT_NESTING_LEVEL with a SFT_BASE_FOR_COMPONENTS_P flag which is set
for all SFTs that mark the beginning of a part with sub-SFTs.
In the operand scanner we can avoid searching for sub-SFTs for pointed-to
SFTs that do not serve as a base, but only need to add these SFTs if
the access overlaps with it.  (Though unfortunately this doesn't
significantly lower the compile-time regression seen with tramp3d)

The gcc.dg/torture/pr33870.c testcase still fails without this patch.

Bootstrapped and tested on x86_64-unknown-linux-gnu.

Ok for mainline?

Thanks,
Richard.

2007-11-14  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/33870
	* tree.h (struct tree_memory_tag): Add base_for_components flag.
	(struct tree_struct_field_tag): Remove nesting_level field.
	(SFT_NESTING_LEVEL): Remove.
	(SFT_BASE_FOR_COMPONENTS_P): Add.
	* tree-flow.h (struct fieldoff): Remove nesting_level field.  Add
	base_for_components flag.
	(push_fields_onto_fieldstack): Remove nesting_level parameter.
	* tree-ssa-alias.c (create_sft): Likewise.  Add base_for_components
	parameter.
	(create_overlap_variables_for): Deal with it.
	* tree-dfa.c (dump_subvars_for): Likewise.
	(dump_variable): Likewise.
	* tree-ssa-structalias.c (push_fields_onto_fieldstack): Likewise.
	Set base_for_components for first elements of sub-structures.
	(create_variable_info_for): Handle base_for_components.
	(set_uids_in_ptset): Always set SFT_UNPARTITIONABLE_P for
	pointed-to SFTs if SFT_BASE_FOR_COMPONENTS_P is set.
	* tree-ssa-operands.c (ref_nesting_level): Remove.
	(add_vars_for_offset): Remove full_ref parameter, always add
	the offset of the pointed-to SFT.
	(add_virtual_operand): Adjust for changed signature of
	add_vars_for_offset.

	* gcc.dg/torture/pr33870.c: New testcase.
	

Index: tree.h
===================================================================
*** tree.h	(revision 130174)
--- tree.h	(working copy)
*************** struct tree_memory_tag GTY(())
*** 2557,2562 ****
--- 2557,2565 ----
    /* True if this tag has global scope.  */
    unsigned int is_global : 1;
  
+   /* True if this tag can be a base for component accesses.  */
+   unsigned int base_for_components : 1;
+ 
    /* True if this tag should not be grouped into a memory partition.  */
    unsigned int unpartitionable : 1;
  };
*************** struct tree_struct_field_tag GTY(())
*** 2579,2601 ****
  
    /* Alias set for a DECL_NONADDRESSABLE_P field.  Otherwise -1.  */
    alias_set_type alias_set;
- 
-   /* Nesting level for this subvariable.  This indicates how many
-      structures are wrapping this field.  Fields at the top level have
-      a nesting level of 0.  */
-   unsigned int nesting_level;
  };
- 
  #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_NESTING_LEVEL(NODE) \
-   (STRUCT_FIELD_TAG_CHECK (NODE)->sft.nesting_level)
  #define SFT_UNPARTITIONABLE_P(NODE) \
    (STRUCT_FIELD_TAG_CHECK (NODE)->sft.common.unpartitionable)
  
  /* Memory Partition Tags (MPTs) group memory symbols under one
     common name for the purposes of placing memory PHI nodes.  */
--- 2582,2598 ----
  
    /* 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_UNPARTITIONABLE_P(NODE) \
    (STRUCT_FIELD_TAG_CHECK (NODE)->sft.common.unpartitionable)
+ #define SFT_BASE_FOR_COMPONENTS_P(NODE) \
+   (STRUCT_FIELD_TAG_CHECK (NODE)->sft.common.base_for_components)
  
  /* Memory Partition Tags (MPTs) group memory symbols under one
     common name for the purposes of placing memory PHI nodes.  */
Index: testsuite/gcc.dg/torture/pr33870.c
===================================================================
*** testsuite/gcc.dg/torture/pr33870.c	(revision 0)
--- testsuite/gcc.dg/torture/pr33870.c	(revision 0)
***************
*** 0 ****
--- 1,30 ----
+ /* { dg-do run } */
+ /* { dg-options "--param max-aliased-vops=1" } */
+ 
+ struct X {
+   int i;
+   int a[4];
+ } m;
+ 
+ int a[4];
+ 
+ int __attribute__((noinline)) foo(int b)
+ {
+   int (*p)[4] = b ? &a : &m.a;
+   a[3] = 0;
+   (*p)[3] = 1;
+   return (*p)[3] + (*p)[2] + (*p)[1] + a[0] + a[3];
+ }
+ 
+ extern void abort (void);
+ 
+ int main()
+ {
+   int i;
+   for (i = 0; i < 4; ++i)
+     a[i] = 0;
+   if (foo(1) != 2)
+     abort ();
+   return 0;
+ }
+ 
Index: tree-dfa.c
===================================================================
*** tree-dfa.c	(revision 130174)
--- tree-dfa.c	(working copy)
*************** dump_subvars_for (FILE *file, tree var)
*** 287,294 ****
    for (i = 0; VEC_iterate (tree, sv, i, subvar); ++i)
      {
        print_generic_expr (file, subvar, dump_flags);
        fprintf (file, "@" HOST_WIDE_INT_PRINT_UNSIGNED, SFT_OFFSET (subvar));
-       fprintf (file, "[%u]", SFT_NESTING_LEVEL (subvar));
        fprintf (file, " ");
      }
  
--- 287,295 ----
    for (i = 0; VEC_iterate (tree, sv, i, subvar); ++i)
      {
        print_generic_expr (file, subvar, dump_flags);
+       if (SFT_BASE_FOR_COMPONENTS_P (subvar))
+         fprintf (file, "@");
        fprintf (file, "@" HOST_WIDE_INT_PRINT_UNSIGNED, SFT_OFFSET (subvar));
        fprintf (file, " ");
      }
  
*************** dump_variable (FILE *file, tree var)
*** 424,430 ****
  	{
  	  fprintf (file, ", offset: " HOST_WIDE_INT_PRINT_UNSIGNED,
  		   SFT_OFFSET (var));
! 	  fprintf (file, ", nesting: %u", SFT_NESTING_LEVEL (var));
  	  fprintf (file, ", partitionable: %s",
  		   SFT_UNPARTITIONABLE_P (var) ? "NO" : "YES");
  	}
--- 425,432 ----
  	{
  	  fprintf (file, ", offset: " HOST_WIDE_INT_PRINT_UNSIGNED,
  		   SFT_OFFSET (var));
! 	  fprintf (file, ", base for components: %s",
! 		   SFT_BASE_FOR_COMPONENTS_P (var) ? "NO" : "YES");
  	  fprintf (file, ", partitionable: %s",
  		   SFT_UNPARTITIONABLE_P (var) ? "NO" : "YES");
  	}
Index: tree-flow.h
===================================================================
*** tree-flow.h	(revision 130174)
--- tree-flow.h	(working copy)
*************** struct fieldoff
*** 1159,1180 ****
    /* Field.  */
    tree decl;
  
-   /* Nesting level.  This number represents how many structures are
-      wrapping this field.  */
-   unsigned nesting_level;
- 
    /* Offset from the base of the base containing object to this field.  */
    HOST_WIDE_INT offset;  
  
    /* Alias set for the field.  */
    alias_set_type alias_set;
  };
  typedef struct fieldoff fieldoff_s;
  
  DEF_VEC_O(fieldoff_s);
  DEF_VEC_ALLOC_O(fieldoff_s,heap);
! int push_fields_onto_fieldstack (tree, VEC(fieldoff_s,heap) **, HOST_WIDE_INT,
! 				 bool *, tree, unsigned);
  void sort_fieldstack (VEC(fieldoff_s,heap) *);
  
  void init_alias_heapvars (void);
--- 1159,1179 ----
    /* Field.  */
    tree decl;
  
    /* Offset from the base of the base containing object to this field.  */
    HOST_WIDE_INT offset;  
  
    /* Alias set for the field.  */
    alias_set_type alias_set;
+ 
+   /* True, if this offset can be a base for further component accesses.  */
+   unsigned base_for_components : 1;
  };
  typedef struct fieldoff fieldoff_s;
  
  DEF_VEC_O(fieldoff_s);
  DEF_VEC_ALLOC_O(fieldoff_s,heap);
! int push_fields_onto_fieldstack (tree, VEC(fieldoff_s,heap) **,
! 				 HOST_WIDE_INT, bool *, tree);
  void sort_fieldstack (VEC(fieldoff_s,heap) *);
  
  void init_alias_heapvars (void);
Index: tree-ssa-structalias.c
===================================================================
*** tree-ssa-structalias.c	(revision 130174)
--- tree-ssa-structalias.c	(working copy)
*************** sort_fieldstack (VEC(fieldoff_s,heap) *f
*** 4053,4071 ****
     TYPE.
  
     ADDRESSABLE_TYPE is the type of the outermost object that could
!    have its address taken.
! 
!    NESTING_LEVEL indicates whether TYPE is a structure nested inside
!    another, it starts at 0 and it is incremented by one on every
!    structure recursed into.  */
  
  int
  push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack,
  			     HOST_WIDE_INT offset, bool *has_union,
! 			     tree addressable_type, unsigned nesting_level)
  {
    tree field;
    int count = 0;
  
    if (TREE_CODE (type) == COMPLEX_TYPE)
      {
--- 4053,4068 ----
     TYPE.
  
     ADDRESSABLE_TYPE is the type of the outermost object that could
!    have its address taken.  */
  
  int
  push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack,
  			     HOST_WIDE_INT offset, bool *has_union,
! 			     tree addressable_type)
  {
    tree field;
    int count = 0;
+   int first_element = VEC_length (fieldoff_s, *fieldstack);
  
    if (TREE_CODE (type) == COMPLEX_TYPE)
      {
*************** push_fields_onto_fieldstack (tree type, 
*** 4076,4081 ****
--- 4073,4079 ----
        real_part->offset = offset;
        real_part->decl = NULL_TREE;
        real_part->alias_set = -1;
+       real_part->base_for_components = false;
  
        img_part = VEC_safe_push (fieldoff_s, heap, *fieldstack, NULL);
        img_part->type = TREE_TYPE (type);
*************** push_fields_onto_fieldstack (tree type, 
*** 4083,4093 ****
        img_part->offset = offset + TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (type)));
        img_part->decl = NULL_TREE;
        img_part->alias_set = -1;
  
!       return 2;
      }
  
!   if (TREE_CODE (type) == ARRAY_TYPE)
      {
        tree sz = TYPE_SIZE (type);
        tree elsz = TYPE_SIZE (TREE_TYPE (type));
--- 4081,4092 ----
        img_part->offset = offset + TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (type)));
        img_part->decl = NULL_TREE;
        img_part->alias_set = -1;
+       img_part->base_for_components = false;
  
!       count = 2;
      }
  
!   else if (TREE_CODE (type) == ARRAY_TYPE)
      {
        tree sz = TYPE_SIZE (type);
        tree elsz = TYPE_SIZE (TREE_TYPE (type));
*************** push_fields_onto_fieldstack (tree type, 
*** 4125,4132 ****
  		      has_union,
  		      (TYPE_NONALIASED_COMPONENT (type)
  		       ? addressable_type
! 		       : TREE_TYPE (type)),
! 		      nesting_level + 1)))
  	    /* Empty structures may have actual size, like in C++. So
  	       see if we didn't push any subfields and the size is
  	       nonzero, push the field onto the stack */
--- 4124,4130 ----
  		      has_union,
  		      (TYPE_NONALIASED_COMPONENT (type)
  		       ? addressable_type
! 		       : TREE_TYPE (type)))))
  	    /* Empty structures may have actual size, like in C++. So
  	       see if we didn't push any subfields and the size is
  	       nonzero, push the field onto the stack */
*************** push_fields_onto_fieldstack (tree type, 
*** 4145,4160 ****
  		pair->alias_set = get_alias_set (addressable_type);
  	      else
  		pair->alias_set = -1;
! 	      pair->nesting_level = nesting_level;
  	      count++;
  	    }
  	  else
  	    count += pushed;
  	}
- 
-       return count;
      }
  
    for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
      if (TREE_CODE (field) == FIELD_DECL)
        {
--- 4143,4158 ----
  		pair->alias_set = get_alias_set (addressable_type);
  	      else
  		pair->alias_set = -1;
! 	      pair->base_for_components = false;
  	      count++;
  	    }
  	  else
  	    count += pushed;
  	}
      }
  
+   else
+     {
    for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
      if (TREE_CODE (field) == FIELD_DECL)
        {
*************** push_fields_onto_fieldstack (tree type, 
*** 4175,4182 ****
  		    has_union,
  		    (DECL_NONADDRESSABLE_P (field)
  		     ? addressable_type
! 		     : TREE_TYPE (field)),
! 		    nesting_level + 1))
  		 && DECL_SIZE (field)
  		 && !integer_zerop (DECL_SIZE (field)))
  	  /* Empty structures may have actual size, like in C++. So
--- 4173,4179 ----
  		    has_union,
  		    (DECL_NONADDRESSABLE_P (field)
  		     ? addressable_type
! 		     : TREE_TYPE (field))))
  		 && DECL_SIZE (field)
  		 && !integer_zerop (DECL_SIZE (field)))
  	  /* Empty structures may have actual size, like in C++. So
*************** push_fields_onto_fieldstack (tree type, 
*** 4197,4208 ****
  	      pair->alias_set = get_alias_set (addressable_type);
  	    else
  	      pair->alias_set = -1;
! 	    pair->nesting_level = nesting_level;
  	    count++;
  	  }
  	else
  	  count += pushed;
        }
  
    return count;
  }
--- 4194,4211 ----
  	      pair->alias_set = get_alias_set (addressable_type);
  	    else
  	      pair->alias_set = -1;
! 	    pair->base_for_components = false;
  	    count++;
  	  }
  	else
  	  count += pushed;
        }
+     }
+ 
+   /* Make sure the first pushed field is marked as eligible for
+      being a base for component references.  */
+   if (count > 0)
+     VEC_index (fieldoff_s, *fieldstack, first_element)->base_for_components = true;
  
    return count;
  }
*************** create_variable_info_for (tree decl, con
*** 4397,4403 ****
    if (var_can_have_subvars (decl) && use_field_sensitive && !hasunion)
      {
        push_fields_onto_fieldstack (decltype, &fieldstack, 0, &hasunion,
! 				   decltype, 0);
        if (hasunion)
  	{
  	  VEC_free (fieldoff_s, heap, fieldstack);
--- 4400,4406 ----
    if (var_can_have_subvars (decl) && use_field_sensitive && !hasunion)
      {
        push_fields_onto_fieldstack (decltype, &fieldstack, 0, &hasunion,
! 				   decltype);
        if (hasunion)
  	{
  	  VEC_free (fieldoff_s, heap, fieldstack);
*************** set_uids_in_ptset (tree ptr, bitmap into
*** 4762,4776 ****
  		    {
  		      bitmap_set_bit (into, DECL_UID (sft));
  		      
! 		      /* If SFT is inside a nested structure, it will
! 			 be needed by the operand scanner to adjust
! 			 offsets when adding operands to memory
  			 expressions that dereference PTR.  This means
  			 that memory partitioning may not partition
  			 this SFT because the operand scanner will not
  			 be able to find the other SFTs next to this
! 			 one.  */
! 		      if (SFT_NESTING_LEVEL (sft) > 0)
  			SFT_UNPARTITIONABLE_P (sft) = true;
  		    }
  		}
--- 4765,4779 ----
  		    {
  		      bitmap_set_bit (into, DECL_UID (sft));
  		      
! 		      /* Pointed-to SFTs are needed by the operand scanner
! 			 to adjust offsets when adding operands to memory
  			 expressions that dereference PTR.  This means
  			 that memory partitioning may not partition
  			 this SFT because the operand scanner will not
  			 be able to find the other SFTs next to this
! 			 one.  But we only need to do this if the pointed
! 			 to type is aggregate.  */
! 		      if (SFT_BASE_FOR_COMPONENTS_P (sft))
  			SFT_UNPARTITIONABLE_P (sft) = true;
  		    }
  		}
Index: tree-ssa-alias.c
===================================================================
*** tree-ssa-alias.c	(revision 130197)
--- tree-ssa-alias.c	(working copy)
*************** get_or_create_used_part_for (size_t uid)
*** 3791,3797 ****
  static tree
  create_sft (tree var, tree field, unsigned HOST_WIDE_INT offset,
  	    unsigned HOST_WIDE_INT size, alias_set_type alias_set,
! 	    unsigned nesting_level)
  {
    tree subvar = create_tag_raw (STRUCT_FIELD_TAG, field, "SFT");
  
--- 3791,3797 ----
  static tree
  create_sft (tree var, tree field, unsigned HOST_WIDE_INT offset,
  	    unsigned HOST_WIDE_INT size, alias_set_type alias_set,
! 	    bool base_for_components)
  {
    tree subvar = create_tag_raw (STRUCT_FIELD_TAG, field, "SFT");
  
*************** create_sft (tree var, tree field, unsign
*** 3811,3817 ****
    SFT_OFFSET (subvar) = offset;
    SFT_SIZE (subvar) = size;
    SFT_ALIAS_SET (subvar) = alias_set;
!   SFT_NESTING_LEVEL (subvar) = nesting_level;
  
    return subvar;
  }
--- 3811,3818 ----
    SFT_OFFSET (subvar) = offset;
    SFT_SIZE (subvar) = size;
    SFT_ALIAS_SET (subvar) = alias_set;
!   SFT_BASE_FOR_COMPONENTS_P (subvar) = base_for_components;
!   SFT_UNPARTITIONABLE_P (subvar) = false;
  
    return subvar;
  }
*************** create_overlap_variables_for (tree var)
*** 3833,3839 ****
      return;
  
    push_fields_onto_fieldstack (TREE_TYPE (var), &fieldstack, 0, NULL,
! 			       TREE_TYPE (var), 0);
    /* Make sure to not create SFTs for structs we won't generate variable
       infos for.  See tree-ssa-structalias.c:create_variable_info_for ().  */
    if (VEC_length (fieldoff_s, fieldstack) != 0
--- 3834,3840 ----
      return;
  
    push_fields_onto_fieldstack (TREE_TYPE (var), &fieldstack, 0, NULL,
! 			       TREE_TYPE (var));
    /* Make sure to not create SFTs for structs we won't generate variable
       infos for.  See tree-ssa-structalias.c:create_variable_info_for ().  */
    if (VEC_length (fieldoff_s, fieldstack) != 0
*************** create_overlap_variables_for (tree var)
*** 3919,3924 ****
--- 3920,3926 ----
  	     field, skip it.  Note that we always need the field at
  	     offset 0 so we can properly handle pointers to the
  	     structure.  */
+ 
  	  if ((fo->offset != 0
  	       && ((fo->offset <= up->minused
  		    && fo->offset + fosize <= up->minused)
*************** create_overlap_variables_for (tree var)
*** 3927,3935 ****
  		  && fosize == lastfosize
  		  && currfotype == lastfotype))
  	    continue;
! 
! 	  subvar = create_sft (var, fo->type, fo->offset, fosize,
! 			       fo->alias_set, fo->nesting_level);
  	  VEC_quick_push (tree, *subvars, subvar);
  
  	  if (dump_file)
--- 3929,3936 ----
  		  && fosize == lastfosize
  		  && currfotype == lastfotype))
  	    continue;
! 	  subvar = create_sft (var, fo->type, fo->offset,
! 			       fosize, fo->alias_set, fo->base_for_components);
  	  VEC_quick_push (tree, *subvars, subvar);
  
  	  if (dump_file)
*************** create_overlap_variables_for (tree var)
*** 3940,3947 ****
  		       SFT_OFFSET (subvar));
  	      fprintf (dump_file, " size " HOST_WIDE_INT_PRINT_DEC,
  		       SFT_SIZE (subvar));
! 	      fprintf (dump_file, " nesting level %d\n",
! 		       SFT_NESTING_LEVEL (subvar));
  	    }
  	  
  	  lastfotype = currfotype;
--- 3941,3947 ----
  		       SFT_OFFSET (subvar));
  	      fprintf (dump_file, " size " HOST_WIDE_INT_PRINT_DEC,
  		       SFT_SIZE (subvar));
! 	      fprintf (dump_file, "\n");
  	    }
  	  
  	  lastfotype = currfotype;
Index: tree-ssa-operands.c
===================================================================
*** tree-ssa-operands.c	(revision 130221)
--- tree-ssa-operands.c	(working copy)
*************** access_can_touch_variable (tree ref, tre
*** 1367,1399 ****
    return true;
  }
  
- 
- /* Given an aggregate expression FULL_REF, return the number of
-    aggregates that are containing FULL_REF.  So, given a structure
-    reference a.b.c.d, the nesting level for this expression is 2 (the
-    number of '.' in the expression minus 1).  */
- 
- static unsigned
- ref_nesting_level (tree full_ref)
- {
-   unsigned nesting_level = 0;
- 
-   if (!handled_component_p (full_ref))
-     return 0;
- 
-   full_ref = TREE_OPERAND (full_ref, 0);
-   while (handled_component_p (full_ref))
-     {
-       nesting_level++;
-       full_ref = TREE_OPERAND (full_ref, 0);
-     }
- 
-   return nesting_level;
- }
- 
- 
  /* Add the actual variables FULL_REF can access, given a member of
!    FULL_REF's points-to set VAR, where FULL_REF is an access of SIZE at
     OFFSET from var. IS_CALL_SITE is true if this is a call, and IS_DEF
     is true if this is supposed to be a vdef, and false if this should
     be a VUSE.
--- 1367,1374 ----
    return true;
  }
  
  /* Add the actual variables FULL_REF can access, given a member of
!    full_ref's points-to set VAR, where FULL_REF is an access of SIZE at
     OFFSET from var. IS_CALL_SITE is true if this is a call, and IS_DEF
     is true if this is supposed to be a vdef, and false if this should
     be a VUSE.
*************** ref_nesting_level (tree full_ref)
*** 1411,1422 ****
     This is necessary because foop only actually points to foo's first
     member, so that is all the points-to set contains.  However, an access
     to foop->a may be touching some single SFT if we have created some
!    SFT's for a structure.
! 
!    FULL_REF is the original memory expression being analyzed.  */
  
  static bool
! add_vars_for_offset (tree full_ref, tree var, unsigned HOST_WIDE_INT offset,
  		     unsigned HOST_WIDE_INT size, bool is_def)
  {
    bool added = false;
--- 1386,1395 ----
     This is necessary because foop only actually points to foo's first
     member, so that is all the points-to set contains.  However, an access
     to foop->a may be touching some single SFT if we have created some
!    SFT's for a structure.  */
  
  static bool
! add_vars_for_offset (tree var, unsigned HOST_WIDE_INT offset,
  		     unsigned HOST_WIDE_INT size, bool is_def)
  {
    bool added = false;
*************** add_vars_for_offset (tree full_ref, tree
*** 1424,1478 ****
    subvar_t sv;
    unsigned int i;
  
!   if (full_ref
!       && SFT_NESTING_LEVEL (var) > 0
!       && ref_nesting_level (full_ref) < SFT_NESTING_LEVEL (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.  If VAR is an
! 	 SFT inside a nested structure, then FULL_REF may be a
! 	 reference to the structure immediately enclosing SFT, and so
! 	 OFFSET will be the offset from the start of the immediately
! 	 enclosing 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.  */
--- 1397,1404 ----
    subvar_t sv;
    unsigned int i;
  
!   /* Adjust offset by the pointed-to location.  */
!   offset += SFT_OFFSET (var);
  
    /* Add all subvars of var that overlap with the access.
       Binary search for the first relevant SFT.  */
*************** add_virtual_operand (tree var, stmt_ann_
*** 1575,1582 ****
  	     if it is a potential points-to location.  */
  	  if (TREE_CODE (al) == STRUCT_FIELD_TAG
  	      && TREE_CODE (var) == NAME_MEMORY_TAG)
! 	    none_added &= !add_vars_for_offset (full_ref, al, offset, size,
! 					        flags & opf_def);
  	  else
  	    {
  	      /* Call-clobbered tags may have non-call-clobbered
--- 1501,1522 ----
  	     if it is a potential points-to location.  */
  	  if (TREE_CODE (al) == STRUCT_FIELD_TAG
  	      && TREE_CODE (var) == NAME_MEMORY_TAG)
! 	    {
! 	      if (SFT_BASE_FOR_COMPONENTS_P (al))
! 		none_added &= !add_vars_for_offset (al, offset, size,
! 						    flags & opf_def);
! 	      /* If this is a SFT that cannot be used as a base for
! 	         component references, we only need to consider it 
! 	         if [offset, size[ is within its extent.  */
! 	      else if ((unsigned HOST_WIDE_INT)offset < SFT_SIZE (al))
! 		{
! 		  if (flags & opf_def)
! 		    append_vdef (al);
! 		  else
! 		    append_vuse (al);
! 		  none_added = false;
! 		}
! 	    }
  	  else
  	    {
  	      /* Call-clobbered tags may have non-call-clobbered

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

* Re: [PATCH] Final followup patch for PR33870
  2007-11-16 13:45 [PATCH] Final followup patch for PR33870 Richard Guenther
@ 2007-11-16 16:49 ` Diego Novillo
  0 siblings, 0 replies; 2+ messages in thread
From: Diego Novillo @ 2007-11-16 16:49 UTC (permalink / raw)
  To: Richard Guenther; +Cc: gcc-patches

Richard Guenther wrote:

> (Though unfortunately this doesn't
> significantly lower the compile-time regression seen with tramp3d)

If you can't track the compile-time regression to operand scanning, then 
it's unlikely that this patch will help.  Partitioning mainly affects 
operand scanning and all the other optimizers that need to visit virtual 
operands.


> 	PR tree-optimization/33870
> 	* tree.h (struct tree_memory_tag): Add base_for_components flag.
> 	(struct tree_struct_field_tag): Remove nesting_level field.
> 	(SFT_NESTING_LEVEL): Remove.
> 	(SFT_BASE_FOR_COMPONENTS_P): Add.
> 	* tree-flow.h (struct fieldoff): Remove nesting_level field.  Add
> 	base_for_components flag.
> 	(push_fields_onto_fieldstack): Remove nesting_level parameter.
> 	* tree-ssa-alias.c (create_sft): Likewise.  Add base_for_components
> 	parameter.
> 	(create_overlap_variables_for): Deal with it.
> 	* tree-dfa.c (dump_subvars_for): Likewise.
> 	(dump_variable): Likewise.
> 	* tree-ssa-structalias.c (push_fields_onto_fieldstack): Likewise.
> 	Set base_for_components for first elements of sub-structures.
> 	(create_variable_info_for): Handle base_for_components.
> 	(set_uids_in_ptset): Always set SFT_UNPARTITIONABLE_P for
> 	pointed-to SFTs if SFT_BASE_FOR_COMPONENTS_P is set.
> 	* tree-ssa-operands.c (ref_nesting_level): Remove.
> 	(add_vars_for_offset): Remove full_ref parameter, always add
> 	the offset of the pointed-to SFT.
> 	(add_virtual_operand): Adjust for changed signature of
> 	add_vars_for_offset.
> 
> 	* gcc.dg/torture/pr33870.c: New testcase.

Much better than the idea of nesting, thanks!

Minor nits:


>     /* True if this tag has global scope.  */
>     unsigned int is_global : 1;
>   
> +   /* True if this tag can be a base for component accesses.  */
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                           is the first field of an aggregate type that 
can be used to find adjacent SFTs belonging to the same aggregate.

>     for (i = 0; VEC_iterate (tree, sv, i, subvar); ++i)
>       {
>         print_generic_expr (file, subvar, dump_flags);
> +       if (SFT_BASE_FOR_COMPONENTS_P (subvar))
> +         fprintf (file, "@");
>         fprintf (file, "@" HOST_WIDE_INT_PRINT_UNSIGNED, SFT_OFFSET (subvar));

Instead of printing SFT.xx@@999, I find SFT.xx@999[B] easier to scan 
visually in a dump.

>   /* Add the actual variables FULL_REF can access, given a member of
> !    full_ref's points-to set VAR, where FULL_REF is an access of SIZE at
>      OFFSET from var. IS_CALL_SITE is true if this is a call, and IS_DEF
>      is true if this is supposed to be a vdef, and false if this should
>      be a VUSE.

This comment is now out of sync.  You removed the argument FULL_REF.


> ! 	      if (SFT_BASE_FOR_COMPONENTS_P (al))
                 {
                /* If AL is the first SFT of a component, it can be used
                  to find other SFTs at [offset, size] adjacent to it. */

> ! 		none_added &= !add_vars_for_offset (al, offset, size,
> ! 						    flags & opf_def);
                 }
> ! 	      else if ((unsigned HOST_WIDE_INT)offset < SFT_SIZE (al))
> ! 		{

And move this comment inside the braces:

		/* Otherwise, we only need to consider it
                    if [offset, size] overlaps with AL.  */
> ! 		  if (flags & opf_def)
> ! 		    append_vdef (al);
> ! 		  else
> ! 		    append_vuse (al);
> ! 		  none_added = false;
> ! 		}
> ! 	    }


OK with those changes.


Diego.

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

end of thread, other threads:[~2007-11-16 14:03 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-11-16 13:45 [PATCH] Final followup patch for PR33870 Richard Guenther
2007-11-16 16:49 ` Diego Novillo

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