Bug 57297 - FAIL: gfortran.dg/select_type_4.f90 -O2 execution test
Summary: FAIL: gfortran.dg/select_type_4.f90 -O2 execution test
Status: RESOLVED WORKSFORME
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 4.8.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2013-05-15 17:30 UTC by gretay
Modified: 2019-01-22 17:52 UTC (History)
5 users (show)

See Also:
Host:
Target: arm-none-eabi
Build:
Known to work:
Known to fail:
Last reconfirmed: 2013-05-16 00:00:00


Attachments
reduced test case (859 bytes, text/x-fortran)
2013-05-15 17:30 UTC, gretay
Details
frontend patch, second try (779 bytes, patch)
2013-05-16 22:45 UTC, Mikael Morin
Details | Diff
frontend patch, third try (4.20 KB, patch)
2013-05-19 13:16 UTC, Mikael Morin
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description gretay 2013-05-15 17:30:39 UTC
Created attachment 30126 [details]
reduced test case

I am not sure whether it's target, fortran, or alias analysis problem (or a combination).

I am attaching a reduced testcase. It allocates a list with three nodes, traverses it counting the number of nodes, and then deallocates it. The problem arises from the middle node that has no data (similar to the original test).
The failure manifests itself by finding only one node in the list, instead of three. 

$ /work/builds/fortran/install/bin/arm-none-eabi-gfortran reduced_select_type_4.f90 -O2 -o bad.exe

$ qemu-arm bad.exe
           1
 Done counting

The original test fails on qemu arm-none-eabi using a recent trunk compiler, and it has been failing on trunk since at least September 2012 (and probably long ago). 
The reduced testcase fails in arm mode, but not in thumb mode. 
It does not fail when compiled with -fno-strict-aliasing. 
It also does not fail when compiled with -fno-schedule-insns -fno-schedule-insns2. 
It does not fail when inlining is disabled.

$ /work/builds/fortran/install/bin/arm-none-eabi-gfortran reduced_select_type_4.f90 -O2 -o good.exe -fno-strict-aliasing
greyor01@e103227-lin:/work/tmp/sel/sept$ qemu-arm good.exe
           1
           2
           3
 Done counting

The problem seems to be incorrect aliasing information that gets used by instruction reordering.
It results in the following code slice (bad):
	add	r3, sp, #8	      @ 94	*arm_addsi3/2	[length = 4]
	ldmia	r3, {r0, r1}	@ 104	*ldm2_ia	[length = 4]
	str	r6, [sp, #8]	@ 99	*arm_movsi_vfp/6	[length = 4]
	str	r5, [sp, #12]	@ 101	*arm_movsi_vfp/6	[length = 4]
	stmia	r4, {r0, r1}	@ 105	*stm2_ia	[length = 4]
instead of (good):
	add	r3, sp, #8	      @ 94	*arm_addsi3/2	[length = 4] 
	str	r6, [sp, #8]	@ 99	*arm_movsi_vfp/6	[length = 4]
	str	r5, [sp, #12]	@ 101	*arm_movsi_vfp/6	[length = 4]
	ldmia	r3, {r0, r1}	@ 104	*ldm2_ia	[length = 4]
	stmia	r4, {r0, r1}	@ 105	*stm2_ia	[length = 4]

The problem is that the load is moved before stores to the same address.
This happens in MAIN, in the code of append that is inlined in MAIN to append the second node to the list.
The fact that the second node has a different type (base node, not integer node) may be playing a role here.

Gimple for this code is (block 11):
  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]);

The stores (rtl insns 99, 101) come from the first two GIMPLE statement, and the load (insn 104) comes from accessing rhs of the third statement. 
Note that the third statement is an object assignment via movmemqi expand pattern calling arm_gen_movmemqi function in arm.c. (Could be a target problem if the alias sets are not handled correctly here, but it seems that they copied as is from Gimple).

In the RTL right after expand, the relevant memory accesses are annotated as follows:

(insn 99)   [3 MEM[(struct __class_poly_list_Node_type_p *)&node]+0 S4 A64]
(insn 104)  [8 MEM[(struct __class_poly_list_Node_type &)&node]+0 S4 A64]

This is not recognized as aliasing and no dependence edge is created by the scheduler. 

In comparison, gimple for block 7 (appending the first node in the list, of type integer) is handled correctly.

  MEM[(struct __class_poly_list_Node_type *)&class.1] = integer_node_4;
  MEM[(struct __class_poly_list_Node_type *)&class.1 + 4B] = &__vtab_main_Integer_node_type;
  _63->next = VIEW_CONVERT_EXPR<struct __class_poly_list_Node_type_p>(class.1);

And the alias sets are: 
(insn 48)   [8 MEM[(struct __class_poly_list_Node_type *)&class.1]
(insn 54)   [8 class.1+0 S4 A64]

and the scheduler knows about the dependency.

It doesn't seem to be target-related, because the mem annotation is exactly the same as in gimple, but I don't see this test failing on other targets. The difference may be that other targets use generic move_mem_by_pieces while arm has expand for movmemqi.

The complete RTL after expand for block 11 is:

;; MEM[(struct __class_poly_list_Node_type_p *)&node] = node_17;

(insn 99 98 0 (set (mem/f/c:SI (plus:SI (reg/f:SI 105 virtual-stack-vars)
                (const_int -376 [0xfffffffffffffe88])) [3 MEM[(struct __class_poly_list_Node_type_p *)&node]+0 S4 A64])
        (reg/f:SI 112 [ node ])) select_type_4.f90:37 -1
     (nil))

;; MEM[(struct __class_poly_list_Node_type_p *)&node + 4B] = &__vtab_poly_list_Node_type;

(insn 100 99 101 (set (reg/f:SI 155)
        (symbol_ref:SI ("*.LANCHOR0") [flags 0x182])) select_type_4.f90:37 -1
     (nil))

(insn 101 100 0 (set (mem/f/c:SI (plus:SI (reg/f:SI 105 virtual-stack-vars)
                (const_int -372 [0xfffffffffffffe8c])) [3 MEM[(struct __class_poly_list_Node_type_p *)&node + 4B]+0 S4 A32])
        (reg/f:SI 155)) select_type_4.f90:37 -1
     (nil))

;; 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]);

(insn 102 101 103 (set (reg:SI 156)
        (reg/v/f:SI 110 [ integer_node ])) select_type_4.f90:37 -1
     (nil))

(insn 103 102 104 (set (reg:SI 157)
        (plus:SI (reg/f:SI 105 virtual-stack-vars)
            (const_int -376 [0xfffffffffffffe88]))) select_type_4.f90:37 -1
     (nil))

(insn 104 103 105 (parallel [
            (set (reg:SI 0 r0)
                (mem/c:SI (reg:SI 157) [8 MEM[(struct __class_poly_list_Node_type &)&node]+0 S4 A64]))
            (set (reg:SI 1 r1)
                (mem/c:SI (plus:SI (reg:SI 157)
                        (const_int 4 [0x4])) [8 MEM[(struct __class_poly_list_Node_type &)&node]+4 S4 A32]))
        ]) select_type_4.f90:37 -1
     (nil))

(insn 105 104 0 (parallel [
            (set (mem:SI (reg:SI 156) [3 MEM[(struct node_type *)integer_node_4].next+0 S4 A32])
                (reg:SI 0 r0))
            (set (mem:SI (plus:SI (reg:SI 156)
                        (const_int 4 [0x4])) [3 MEM[(struct node_type *)integer_node_4].next+4 S4 A32])
                (reg:SI 1 r1))
        ]) select_type_4.f90:37 -1
     (nil))


$ /work/builds/fortran/install/bin/arm-none-eabi-gfortran -v
Using built-in specs.
COLLECT_GCC=/work/builds/fortran/install/bin/arm-none-eabi-gfortran
COLLECT_LTO_WRAPPER=/work/builds/fortran/install/libexec/gcc/arm-none-eabi/4.8.0/lto-wrapper
Target: arm-none-eabi
Configured with: /work/local-checkouts/gcc-git//configure --target=arm-none-eabi --prefix=/work/may-builds/fortran/install --with-sysroot=/work/may-builds/fortran/install/arm-none-eabi --with-newlib --with-gnu-as --with-gnu-ld --enable-languages=c,c++,fortran --disable-shared --disable-nls --disable-threads --disable-lto --disable-plugin --disable-tls --enable-checking=yes --disable-libssp --disable-libgomp --disable-libmudflap --with-cpu=cortex-a15 --with-fpu=neon-vfpv4 --with-float=softfp 
Thread model: single
gcc version 4.8.0 20120912 (experimental) (GCC)
Comment 1 Mikael Morin 2013-05-15 18:35:13 UTC
Thanks for the detailed bug report. It's very informative (even if I don't understand everything ;-) ).
Here is a "shot in the dark" patch (on the fortran side); does it work for you?

Index: class.c
===================================================================
--- class.c	(révision 198085)
+++ class.c	(copie de travail)
@@ -581,10 +581,14 @@ gfc_build_class_symbol (gfc_typespec *ts, symbol_a
     sprintf (name, "__class_%s_%d_%da", tname, rank, (*as)->corank);
   else if ((*as) && attr->pointer)
     sprintf (name, "__class_%s_%d_%dp", tname, rank, (*as)->corank);
+  else if ((*as) && attr->target)
+    sprintf (name, "__class_%s_%d_%dt", tname, rank, (*as)->corank);
   else if ((*as))
     sprintf (name, "__class_%s_%d_%d", tname, rank, (*as)->corank);
   else if (attr->pointer)
     sprintf (name, "__class_%s_p", tname);
+  else if (attr->target)
+    sprintf (name, "__class_%s_t", tname);
   else if (attr->allocatable)
     sprintf (name, "__class_%s_a", tname);
   else
@@ -628,6 +632,7 @@ gfc_build_class_symbol (gfc_typespec *ts, symbol_a
       c->attr.class_pointer = attr->pointer;
       c->attr.pointer = attr->pointer || (attr->dummy && !attr->allocatable)
 			|| attr->select_type_temporary;
+      c->attr.target = attr->target;
       c->attr.allocatable = attr->allocatable;
       c->attr.dimension = attr->dimension;
       c->attr.codimension = attr->codimension;
Comment 2 Richard Biener 2013-05-16 10:14:18 UTC
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.
Comment 3 gretay 2013-05-16 14:55:05 UTC
Thanks a lot for the quick responses! Unfortunately, the frontend patch alone doesn't fix the problem, as Richard pointed out, but it may be needed for other reasons. The tree-sra patch fixes the test failure. 

If this is the right thing to do, can you please commit these changes?

I applied both patches and tested for arm-none-eabi. No regression on qemu.

Thank you,
Greta
Comment 4 Martin Jambor 2013-05-16 17:23:19 UTC
So far I have not attempted to reproduce this myself and so do not
quite follow all the previous comments but...

(In reply to Richard Biener from comment #2)
> 
> 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).

...it looks like the second arguments in 
	generate_subtree_copies (racc->first_child, racc->base, 0, 0, 0,
				 gsi, false, false, loc);
and
	generate_subtree_copies (lacc->first_child, lacc->base, 0, 0, 0,
				 gsi, true, true, loc);

should be the rhs and lhs respectively, rather than [rl]acc->base.
Using rhs/lhs, the generated statements would have the same alias
pointer type as the respective sides of the original statement.  Can
you try that?  We should probably also change accordingly (almost all)
other calls to generate_subtree_copies (this code generally predates
generating MEM_REFs in build_ref_for_offset and this did not matter).

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

Even though relaxing this condition might be a good idea to try to
generate better code, I'd be against fixing bugs this way, if we can
avoid it.  This should be the safe path capable of handling everything
that the latter more sophisticated approaches might choke on.  It
would make the already complex code more difficult to maintain and
sooner or later we'd hit the same problem again (I think it should be
possible use structures with a single field to create a testcase with
a similar problem and modify_this_stmt set to true, for example).
Comment 5 Mikael Morin 2013-05-16 22:45:03 UTC
Created attachment 30138 [details]
frontend patch, second try

This variant reduces the amount of VIEW_CONVERT_EXPR, which should make the code less confusing downstream.
Comment 6 rguenther@suse.de 2013-05-17 07:58:46 UTC
On Thu, 16 May 2013, jamborm at gcc dot gnu.org wrote:

> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57297
> 
> --- Comment #4 from Martin Jambor <jamborm at gcc dot gnu.org> ---
> So far I have not attempted to reproduce this myself and so do not
> quite follow all the previous comments but...
> 
> (In reply to Richard Biener from comment #2)
> > 
> > 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).
> 
> ...it looks like the second arguments in 
>     generate_subtree_copies (racc->first_child, racc->base, 0, 0, 0,
>                  gsi, false, false, loc);
> and
>     generate_subtree_copies (lacc->first_child, lacc->base, 0, 0, 0,
>                  gsi, true, true, loc);
> 
> should be the rhs and lhs respectively, rather than [rl]acc->base.
> Using rhs/lhs, the generated statements would have the same alias
> pointer type as the respective sides of the original statement.  Can
> you try that?  We should probably also change accordingly (almost all)
> other calls to generate_subtree_copies (this code generally predates
> generating MEM_REFs in build_ref_for_offset and this did not matter).

I'm not sure - but yes, that would make sure the re-materialization
uses the same alias set (does it? not sure exactly how
generate_subtree_copies works) as the load that follows.  Note that
the Fortran frontend is where the bug lies here.

I was thinking that the re-materialization for a whole-structure
access could use a new temporary and indeed use the alias-set of
the access we re-materialize it for for re-construction.

Given that if we have

  if (a)
    a.b = 1; <use alias-set 3>
  else
    a.b = 2; <use alias-set 8>

  y = a; <aggregate use>

we cannot re-materialize a before y = a in a way that restore
original runtime behavior (the if or the else path may be never
executed at runtime).  But given that accessing 'a' in the
aggregate copy with an alias-set that does not conflict with
the actual dynamic type of the memory location invokes undefined
behavior we can indeed make sure to re-materialize a before
y = a using stores with the alias-set of that access.

> > 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.
> 
> Even though relaxing this condition might be a good idea to try to
> generate better code, I'd be against fixing bugs this way, if we can
> avoid it.  This should be the safe path capable of handling everything
> that the latter more sophisticated approaches might choke on.  It
> would make the already complex code more difficult to maintain and
> sooner or later we'd hit the same problem again (I think it should be
> possible use structures with a single field to create a testcase with
> a similar problem and modify_this_stmt set to true, for example).

Yeah, it wasn't meant as a fix for the issue at hand.  I remember
we have the VCE special-casing here because, contrary to specification,
VIEW_CONVERT_EXPRs may change the size of the access.

Richard.
Comment 7 gretay 2013-05-17 14:21:10 UTC
(In reply to Mikael Morin from comment #5)
> Created attachment 30138 [details]
> frontend patch, second try
> 
> This variant reduces the amount of VIEW_CONVERT_EXPR, which should make the
> code less confusing downstream.

This patch fixes the failure in this test, but causes ICE in some fortran tests on qemu for arm-none-eabi. For example:

FAIL: gfortran.dg/auto_dealloc_2.f90  -O  (internal compiler error)

Executing on host: /work/apr-builds/pr57297/fortran-fix2/arm-none-eabi/gcc2/gcc/testsuite/gfortran1/../../gfortran -B/work/apr-builds/pr57297/fortran-fix2/arm-none-eabi/gcc2/gcc/testsuite/gfortran1/../../ -B/work/apr-builds/pr57297fortran-fix2/arm-none-eabi/gcc2/arm-none-eabi/./libgfortran/ /work/local-checkouts/gcc-git/gcc/testsuite/gfortran.dg/auto_dealloc_2.f90  -fno-diagnostics-show-caret   -O  -fdump-tree-original -S -specs=rdimon.specs -Wa,-mno-warn-deprecated    -o auto_dealloc_2.s    (timeout = 60)
/work/local-checkouts/gcc-git/gcc/testsuite/gfortran.dg/auto_dealloc_2.f90: In function 'init':
/work/local-checkouts/gcc-git/gcc/testsuite/gfortran.dgauto_dealloc_2.f90:21:0: internal compiler error: Segmentation fault
0x886585 crash_signal
        /work/local-checkouts/gcc-git/gcc/toplev.c:332
0x4c1b2e structure_alloc_comps
        /work/local-checkouts/gcc-git/gcc/fortran/trans-array.c:7444
0x4df6e5 init_intent_out_dt
        /work/local-checkouts/gcc-git/gcc/fortran/trans-decl.c:3519
0x4df6e5 gfc_trans_deferred_vars(gfc_symbol*, gfc_wrapped_block*)
        /work/local-checkouts/gcc-git/gcc/fortran/trans-decl.c:3631
0x4e2c7e gfc_generate_function_code(gfc_namespace*)
        /work/local-checkouts/gcc-git/gcc/fortran/trans-decl.c:5506
0x4e2ef7 gfc_generate_contained_functions
        /work/local-checkouts/gcc-git/gcc/fortran/trans-decl.c:4576
0x4e2ef7 gfc_generate_function_code(gfc_namespace*)
        /work/local-checkouts/gcc-git/gcc/fortran/trans-decl.c:5379
0x476172 translate_all_program_units
        /work/local-checkouts/gcc-git/gcc/fortran/parse.c:4469
0x476172 gfc_parse_file()
        /work/local-checkouts/gcc-git/gcc/fortran/parse.c:4666
0x4b48a5 gfc_be_parse_file
        /work/local-checkouts/gcc-git/gcc/fortran/f95-lang.c:189
Comment 8 Mikael Morin 2013-05-19 13:09:21 UTC
(In reply to gretay from comment #7)
> This patch fixes the failure in this test, but causes ICE in some fortran
> tests on qemu for arm-none-eabi. For example:
> 
> FAIL: gfortran.dg/auto_dealloc_2.f90  -O  (internal compiler error)
> 
I'll need the help from an OOP expert.

Janus, what is the rationale for using so many different types for class containers? It confuses the middle-end when assigning class containers.
For example in the case:
  class_ptr => class_target

class_ptr's container has type '__class_(blah)p' while class_target has type '__class_(blah)', so we can't do the assignment.
However, even if the types are different the types' contents seems to be the same, so they could be merged?
Comment 9 Mikael Morin 2013-05-19 13:16:01 UTC
Created attachment 30148 [details]
frontend patch, third try

Another variant, yet not passing the testsuite.

This one moves the class_pointer attribute from the class container's type to the class container, so that the type can be shared between non-pointer and pointer variants.
It regresses on class_optional_2.f90 (among a few others) because some pointer array specs become of type AS_ASSUMED_SHAPE instead of AS_DEFERRED without the patch.  The reasons for that are beyond my understanding so far.
Comment 10 janus 2013-07-21 21:16:49 UTC
Hi Mikael,

sorry for the very late reply ...


(In reply to Mikael Morin from comment #8)
> I'll need the help from an OOP expert.
> 
> Janus, what is the rationale for using so many different types for class
> containers?

well, actually I think the initial design of the class containers was mainly dreamed up by Paul, so don't blame it all on me ;)

Anyway, the implementation basically follows the idea that the class containers are generated rather early on in the front-end (i.e. directly at parsing stage, if possible). Therefore one needs a way to store the attributes of the original declaration (other than in the original symbol).

Currently the allocatable, pointer, rank and corank attributes are encoded directly in the naming of the class container (cf. gfc_build_class_symbol).

As you have discovered above, it might help to also treat the 'target' attribute (there are a few other PRs which deal with the same issue). In principle there might even be more attributes that need to be treated (not sure about this).


> It confuses the middle-end when assigning class containers.
> For example in the case:
>   class_ptr => class_target
> 
> class_ptr's container has type '__class_(blah)p' while class_target has type
> '__class_(blah)', so we can't do the assignment.
> However, even if the types are different the types' contents seems to be the
> same, so they could be merged?

Possibly, if you manage to keep track of the corresponding attributes in a different way.

Another thing that might help would be to generate the class containers at a later stage (resolution or translation time). Then one could just store the attributes in the straightforward way. I had started working on this at some point, but never fully managed to pull it through.

Unfortunately I have little time for this at the moment, but if you are willing to work on it, I could at least try to give a bit of feedback on the current implementation.

Cheers,
Janus
Comment 11 Dominique d'Humieres 2019-01-14 21:08:36 UTC
Is the problem still present? I cannot reproduce it.
Comment 12 Dominique d'Humieres 2019-01-22 17:52:03 UTC
No feedback, closing as WORKSFORME.