[Bug fortran/57297] FAIL: gfortran.dg/select_type_4.f90 -O2 execution test

rguenth at gcc dot gnu.org gcc-bugzilla@gcc.gnu.org
Thu May 16 10:14:00 GMT 2013


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57297

Richard Biener <rguenth at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |NEW
   Last reconfirmed|                            |2013-05-16
                 CC|                            |jamborm at gcc dot gnu.org
     Ever confirmed|0                           |1

--- Comment #2 from Richard Biener <rguenth at gcc dot gnu.org> ---
This

  MEM[(struct __class_poly_list_Node_type_p *)&node] = node_17;
  MEM[(struct __class_poly_list_Node_type_p *)&node + 4B] =
&__vtab_poly_list_Node_type;
  MEM[(struct node_type *)integer_node_4].next = VIEW_CONVERT_EXPR<struct
__class_poly_list_Node_type_p>(MEM[(struct __class_poly_list_Node_type
&)&node]);

certainly looks suspicious - we store to node with alias type
(struct __class_poly_list_Node_type_p *) and load from the same location
with alias type (struct __class_poly_list_Node_type &).

Now, the frontend generated code doesn't have the above as it appears only
via some inlining:

append_node (struct list_type & restrict list, struct
__class_poly_list_Node_type & new_node)
{
...
  _9 = list_4(D)->tail._data;
  _9->next = VIEW_CONVERT_EXPR<struct
__class_poly_list_Node_type_p>(*new_node_6(D));

and
  _19 = __builtin_malloc (16);
  node._data = _19;
...
  _26 = node._data;
  __builtin_memset (_26, 0, 16);
  node._vptr = &__vtab_poly_list_Node_type;
  _29 = node._vptr;
  _30 = _29->_size;
  _31 = (unsigned long) _30;
  _32 = node._vptr;
  _33 = _32->_def_init;
  _34 = node._data;
  __builtin_memcpy (_34, _33, _31);
  append_node (&list, &node);

It is early SRA that re-materializes in that way before the aggregate
copy:

  MEM[(struct __class_poly_list_Node_type_p *)&node] = node$_data_28;
  MEM[(struct __class_poly_list_Node_type_p *)&node + 8B] = node$_vptr_20;
  list.head = VIEW_CONVERT_EXPR<struct
__class_poly_list_Node_type_p>(MEM[(struct __class_poly_list_Node_type
&)&node]);

Access trees for node (UID: 1941):
access { base = (1941)'node', offset = 0, size = 128, expr = node, type =
struct __class_poly_list_Node_type_p, grp_read = 1, grp_write = 1,
grp_assignment_read = 1, grp_assignment_write = 1, grp_scalar_read = 0,
grp_scalar_write = 0, grp_total_scalarization = 1, grp_hint = 1, grp_covered =
1, grp_unscalarizable_region = 0, grp_unscalarized_data = 0, grp_partial_lhs =
0, grp_to_be_replaced = 0, grp_to_be_debug_replaced = 0, grp_maybe_modified =
0, grp_not_necessarilly_dereferenced = 0
* access { base = (1941)'node', offset = 0, size = 64, expr = node._data, type
= struct node_type *, grp_read = 1, grp_write = 1, grp_assignment_read = 1,
grp_assignment_write = 1, grp_scalar_read = 1, grp_scalar_write = 1,
grp_total_scalarization = 1, grp_hint = 1, grp_covered = 1,
grp_unscalarizable_region = 0, grp_unscalarized_data = 0, grp_partial_lhs = 0,
grp_to_be_replaced = 1, grp_to_be_debug_replaced = 0, grp_maybe_modified = 0,
grp_not_necessarilly_dereferenced = 0
* access { base = (1941)'node', offset = 64, size = 64, expr = node._vptr, type
= struct __vtype_poly_list_Node_type * {ref-all}, grp_read = 1, grp_write = 1,
grp_assignment_read = 1, grp_assignment_write = 1, grp_scalar_read = 1,
grp_scalar_write = 1, grp_total_scalarization = 1, grp_hint = 1, grp_covered =
1, grp_unscalarizable_region = 0, grp_unscalarized_data = 0, grp_partial_lhs =
0, grp_to_be_replaced = 1, grp_to_be_debug_replaced = 0, grp_maybe_modified =
0, grp_not_necessarilly_dereferenced = 0

that replacement is not 100% correct.  Coming from

     Therefore, I specially handle a fourth case, happening when there is a
     specific type cast or it is impossible to locate a scalarized subaccess on
     the other side of the expression.  If that happens, I simply "refresh" the
     RHS by storing in it is scalarized components leave the original statement
     there to do the copying and then load the scalar replacements of the LHS.
     This is what the first branch does.  */

  if (modify_this_stmt
      || gimple_has_volatile_ops (*stmt)
      || contains_vce_or_bfcref_p (rhs)
      || contains_vce_or_bfcref_p (lhs))
    {

with

list.head = VIEW_CONVERT_EXPR<struct __class_poly_list_Node_type_p>(MEM[(struct
__class_poly_list_Node_type &)&node]);

build_ref_for_offset ends up creating a MEM_REF with different alias pointer
type than "the original" (note that there may be multiple originals and
AFAIK we don't make any attempt to "merge" them conservatively).

Re-materializing the original variable will always be hard.  I believe that

Index: gcc/tree-sra.c
===================================================================
--- gcc/tree-sra.c      (revision 198420)
+++ gcc/tree-sra.c      (working copy)
@@ -3158,7 +3158,7 @@ sra_modify_assign (gimple *stmt, gimple_

   if (modify_this_stmt
       || gimple_has_volatile_ops (*stmt)
-      || contains_vce_or_bfcref_p (rhs)
+      || contains_bitfld_comp_ref_p (rhs)
       || contains_vce_or_bfcref_p (lhs))
     {
       if (access_has_children_p (racc))

should work.

But note that the frontend already geneated wrong-code with the above
assignment

list.head = VIEW_CONVERT_EXPR<struct __class_poly_list_Node_type_p>(MEM[(struct
__class_poly_list_Node_type &)&node]);

which comes from

  _9->next = VIEW_CONVERT_EXPR<struct
__class_poly_list_Node_type_p>(*new_node_6(D));

as this is reading from 'node' with a different alias set than was stored
to (via the simple component-refs).  But SRA is likely required to expose
this situation to the scheduler.

Confirmed as a frontend issue.

I can see a difference with the proposed Frontend patch but the alias
sets are unchanged.



More information about the Gcc-bugs mailing list