[RFC] Should SRA stop producing COMPONENT_REF for non-bit-fields (again)?

Martin Jambor mjambor@suse.cz
Thu Apr 12 16:07:00 GMT 2012


Hi,

On Wed, Apr 04, 2012 at 04:42:05PM +0200, Richard Guenther wrote:
> On Wed, 4 Apr 2012, Martin Jambor wrote:
> 
> > Hi everyone, especially Richi and Eric,
> > 
> > I'd like to know what is your attitude to changing SRA's
> > build_ref_for_model to what it once looked like, so that it produces
> > COMPONENT_REFs only for bit-fields.  The non-bit field handling was
> > added in order to work-around problems when expanding non-aligned
> > MEM_REFs on strict-alignment targets but that should not be a problem
> > now and my experiments confirm that.  Last week I successfully
> > bootstrapped and tested this patch on sparc64-linux (with the
> > temporary MEM_EXPR patch, not including Java), ia64-linux (without
> > Ada), x86_64-linux, i686-linux and tested it on hppa-linux (only C and
> > C++).

...

> > 
> > 2012-03-20 Martin Jambor <mjambor@suse.cz>
> > 
> > 	* tree-sra.c (build_ref_for_model): Create COMPONENT_REFs only for
> > 	bit-fields.
> > 
> > Index: src/gcc/tree-sra.c
> > ===================================================================
> > *** src.orig/gcc/tree-sra.c
> > --- src/gcc/tree-sra.c
> > *************** build_ref_for_offset (location_t loc, tr
> > *** 1489,1558 ****
> >     return fold_build2_loc (loc, MEM_REF, exp_type, base, off);
> >   }
> >   
> > - DEF_VEC_ALLOC_P_STACK (tree);
> > - #define VEC_tree_stack_alloc(alloc) VEC_stack_alloc (tree, alloc)
> > - 
> >   /* Construct a memory reference to a part of an aggregate BASE at the given
> > !    OFFSET and of the type of MODEL.  In case this is a chain of references
> > !    to component, the function will replicate the chain of COMPONENT_REFs of
> > !    the expression of MODEL to access it.  GSI and INSERT_AFTER have the same
> > !    meaning as in build_ref_for_offset.  */
> >   
> >   static tree
> >   build_ref_for_model (location_t loc, tree base, HOST_WIDE_INT offset,
> >   		     struct access *model, gimple_stmt_iterator *gsi,
> >   		     bool insert_after)
> >   {
> > !   tree type = model->type, t;
> > !   VEC(tree,stack) *cr_stack = NULL;
> > ! 
> > !   if (TREE_CODE (model->expr) == COMPONENT_REF)
> >       {
> > !       tree expr = model->expr;
> > ! 
> > !       /* Create a stack of the COMPONENT_REFs so later we can walk them in
> > ! 	 order from inner to outer.  */
> > !       cr_stack = VEC_alloc (tree, stack, 6);
> > ! 
> > !       do {
> > ! 	tree field = TREE_OPERAND (expr, 1);
> > ! 	tree cr_offset = component_ref_field_offset (expr);
> > ! 	HOST_WIDE_INT bit_pos
> > ! 	  = tree_low_cst (cr_offset, 1) * BITS_PER_UNIT
> > ! 	      + TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field));
> >   
> > ! 	/* We can be called with a model different from the one associated
> > ! 	   with BASE so we need to avoid going up the chain too far.  */
> > ! 	if (offset - bit_pos < 0)
> > ! 	  break;
> > ! 
> > ! 	offset -= bit_pos;
> > ! 	VEC_safe_push (tree, stack, cr_stack, expr);
> > ! 
> > ! 	expr = TREE_OPERAND (expr, 0);
> > ! 	type = TREE_TYPE (expr);
> > !       } while (TREE_CODE (expr) == COMPONENT_REF);
> >       }
> > ! 
> > !   t = build_ref_for_offset (loc, base, offset, type, gsi, insert_after);
> > ! 
> > !   if (TREE_CODE (model->expr) == COMPONENT_REF)
> > !     {
> > !       unsigned i;
> > !       tree expr;
> > ! 
> > !       /* Now replicate the chain of COMPONENT_REFs from inner to outer.  */
> > !       FOR_EACH_VEC_ELT_REVERSE (tree, cr_stack, i, expr)
> > ! 	{
> > ! 	  tree field = TREE_OPERAND (expr, 1);
> > ! 	  t = fold_build3_loc (loc, COMPONENT_REF, TREE_TYPE (field), t, field,
> > ! 			       TREE_OPERAND (expr, 2));
> > ! 	}
> > ! 
> > !       VEC_free (tree, stack, cr_stack);
> > !     }
> > ! 
> > !   return t;
> >   }
> >   
> >   /* Construct a memory reference consisting of component_refs and array_refs to
> > --- 1489,1520 ----
> >     return fold_build2_loc (loc, MEM_REF, exp_type, base, off);
> >   }
> >   
> >   /* Construct a memory reference to a part of an aggregate BASE at the given
> > !    OFFSET and of the same type as MODEL.  In case this is a reference to a
> > !    bit-field, the function will replicate the last component_ref of model's
> > !    expr to access it.  GSI and INSERT_AFTER have the same meaning as in
> > !    build_ref_for_offset.  */
> >   
> >   static tree
> >   build_ref_for_model (location_t loc, tree base, HOST_WIDE_INT offset,
> >   		     struct access *model, gimple_stmt_iterator *gsi,
> >   		     bool insert_after)
> >   {
> > !   if (TREE_CODE (model->expr) == COMPONENT_REF
> > !       && DECL_BIT_FIELD (TREE_OPERAND (model->expr, 1)))
> 
> I think you need to test DECL_BIT_FIELD_TYPE here

I have no problems changing that but in between revisions 164280 and
166730 this test worked fine.  What exactly is the difference?

> 
> >       {
> > !       /* This access represents a bit-field.  */
> > !       tree t, exp_type;
> >   
> > !       offset -= int_bit_position (TREE_OPERAND (model->expr, 1));
> 
> I'm not sure that offset is now byte-aligned for all the funny Ada
> bit-layouted records.  But maybe we don't even try to SRA those?

Aggregates containing aggregate fields which start at position
straddling byte boundary are not considered candidates for SRA.

> 
> > !       exp_type = TREE_TYPE (TREE_OPERAND (model->expr, 0));
> > !       t = build_ref_for_offset (loc, base, offset, exp_type, gsi, insert_after);
> > !       return fold_build3_loc (loc, COMPONENT_REF, model->type, t,
> > ! 			      TREE_OPERAND (model->expr, 1), NULL_TREE);
> >       }
> > !   else
> > !     return build_ref_for_offset (loc, base, offset, model->type,
> > ! 				 gsi, insert_after);
> >   }
> >   
> >   /* Construct a memory reference consisting of component_refs and array_refs to
> 
> Otherwise I'm all for doing this change.  I'd even go one step further
> and lower bitfield accesses here in SRA - if the FIELD_DECL of the
> bitfield COMPONENT_REF has a DECL_BIT_FIELD_REPRESENTATIVE access
> that and extract the requested bits via a BIT_FIELD_REF on the RHS
> (or do a RMW cycle for stores).
> 
> That would have been my first place to "lower" bitfield accesses anyway,
> and maybe get rid of some restrictions of SRA that way.

I was also considering that when I saw the representatives patch but
then I wondered why we'd only lower bit-field accesses to
non-addressable structures... but I admit I have not really thought it
through, I guess that can also present some problems.

Anyway, the patch I posted previously would risk re-introducing PR
50386 and PR 50326, even though they are very unlikely with just
bit-fields.  So my current working version is the following, but it
causes failure of libmudflap.c++/pass55-frag.cxx execution test so I'm
not actually proposing it yet (sigh).

Thanks,

Martin


2012-04-11  Martin Jambor  <mjambor@suse.cz>

	* tree-sra.c (build_ref_for_model): Create COMPONENT_REFs only for
	bit-fields.

Index: src/gcc/tree-sra.c
===================================================================
*** src.orig/gcc/tree-sra.c
--- src/gcc/tree-sra.c
*************** build_ref_for_offset (location_t loc, tr
*** 1489,1558 ****
    return fold_build2_loc (loc, MEM_REF, exp_type, base, off);
  }
  
- DEF_VEC_ALLOC_P_STACK (tree);
- #define VEC_tree_stack_alloc(alloc) VEC_stack_alloc (tree, alloc)
- 
  /* Construct a memory reference to a part of an aggregate BASE at the given
!    OFFSET and of the type of MODEL.  In case this is a chain of references
!    to component, the function will replicate the chain of COMPONENT_REFs of
!    the expression of MODEL to access it.  GSI and INSERT_AFTER have the same
!    meaning as in build_ref_for_offset.  */
  
  static tree
  build_ref_for_model (location_t loc, tree base, HOST_WIDE_INT offset,
  		     struct access *model, gimple_stmt_iterator *gsi,
  		     bool insert_after)
  {
!   tree type = model->type, t;
!   VEC(tree,stack) *cr_stack = NULL;
! 
!   if (TREE_CODE (model->expr) == COMPONENT_REF)
      {
!       tree expr = model->expr;
! 
!       /* Create a stack of the COMPONENT_REFs so later we can walk them in
! 	 order from inner to outer.  */
!       cr_stack = VEC_alloc (tree, stack, 6);
! 
!       do {
! 	tree field = TREE_OPERAND (expr, 1);
! 	tree cr_offset = component_ref_field_offset (expr);
! 	HOST_WIDE_INT bit_pos
! 	  = tree_low_cst (cr_offset, 1) * BITS_PER_UNIT
! 	      + TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field));
  
! 	/* We can be called with a model different from the one associated
! 	   with BASE so we need to avoid going up the chain too far.  */
! 	if (offset - bit_pos < 0)
! 	  break;
! 
! 	offset -= bit_pos;
! 	VEC_safe_push (tree, stack, cr_stack, expr);
! 
! 	expr = TREE_OPERAND (expr, 0);
! 	type = TREE_TYPE (expr);
!       } while (TREE_CODE (expr) == COMPONENT_REF);
      }
! 
!   t = build_ref_for_offset (loc, base, offset, type, gsi, insert_after);
! 
!   if (TREE_CODE (model->expr) == COMPONENT_REF)
!     {
!       unsigned i;
!       tree expr;
! 
!       /* Now replicate the chain of COMPONENT_REFs from inner to outer.  */
!       FOR_EACH_VEC_ELT_REVERSE (tree, cr_stack, i, expr)
! 	{
! 	  tree field = TREE_OPERAND (expr, 1);
! 	  t = fold_build3_loc (loc, COMPONENT_REF, TREE_TYPE (field), t, field,
! 			       TREE_OPERAND (expr, 2));
! 	}
! 
!       VEC_free (tree, stack, cr_stack);
!     }
! 
!   return t;
  }
  
  /* Construct a memory reference consisting of component_refs and array_refs to
--- 1489,1520 ----
    return fold_build2_loc (loc, MEM_REF, exp_type, base, off);
  }
  
  /* Construct a memory reference to a part of an aggregate BASE at the given
!    OFFSET and of the same type as MODEL.  In case this is a reference to a
!    bit-field, the function will replicate the last component_ref of model's
!    expr to access it.  GSI and INSERT_AFTER have the same meaning as in
!    build_ref_for_offset.  */
  
  static tree
  build_ref_for_model (location_t loc, tree base, HOST_WIDE_INT offset,
  		     struct access *model, gimple_stmt_iterator *gsi,
  		     bool insert_after)
  {
!   if (TREE_CODE (model->expr) == COMPONENT_REF
!       && DECL_BIT_FIELD (TREE_OPERAND (model->expr, 1)))
      {
!       /* This access represents a bit-field.  */
!       tree t, exp_type, fld = TREE_OPERAND (model->expr, 1);
  
!       offset -= int_bit_position (fld);
!       exp_type = TREE_TYPE (TREE_OPERAND (model->expr, 0));
!       t = build_ref_for_offset (loc, base, offset, exp_type, gsi, insert_after);
!       return fold_build3_loc (loc, COMPONENT_REF, TREE_TYPE (fld), t, fld,
! 			      NULL_TREE);
      }
!   else
!     return build_ref_for_offset (loc, base, offset, model->type,
! 				 gsi, insert_after);
  }
  
  /* Construct a memory reference consisting of component_refs and array_refs to



More information about the Gcc-patches mailing list