Bug 43986 - [OOP] gfortran.dg/dynamic_dispatch_4.f03 doesn't work on Linux/ia64
[OOP] gfortran.dg/dynamic_dispatch_4.f03 doesn't work on Linux/ia64
Status: RESOLVED FIXED
Product: gcc
Classification: Unclassified
Component: fortran
4.6.0
: P3 normal
: ---
Assigned To: Not yet assigned to anyone
: wrong-code
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2010-05-04 22:10 UTC by H.J. Lu
Modified: 2010-07-19 15:38 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2010-05-16 02:07:01


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description H.J. Lu 2010-05-04 22:10:18 UTC
On Linux/ia64, I got

FAIL: gfortran.dg/dynamic_dispatch_4.f03  -O3 -fomit-frame-pointer -funroll-all-
loops -finline-functions  execution test
FAIL: gfortran.dg/dynamic_dispatch_4.f03  -O3 -fomit-frame-pointer -funroll-loop
s  execution test
Comment 1 janus 2010-05-05 08:12:05 UTC
Works for me on x86_64-unknown-linux-gnu.
Comment 2 janus 2010-05-05 13:07:45 UTC
It also works on x86_64-apple-darwin10.3.0.

Does the failure on ia64 only happen with -O3?
Comment 3 H.J. Lu 2010-05-05 13:28:37 UTC
(In reply to comment #2)
> Does the failure on ia64 only happen with -O3?
> 

It fails with

-O3 -fomit-frame-pointer -funroll-all-loops -finline-functions

and

-O3 -fomit-frame-pointer -funroll-loops

Comment 4 Jim Wilson 2010-05-16 02:07:00 UTC
The testcase fails with -O2 -funroll-loops.  It works with -O2.

The problem occurs in main at line 89, which is the second doit call.  We get a segfault when dereferencing a null pointer.

The code is wrong because of an instruction-scheduling/if-conversion/alias-analysis issue.

In the broken assembly output, we have (over simplified)
        addl r33 = @ltoffx(__s_bar_mod_MOD_vtab$s_bar#), r1
        ld8.mov r29 = [r33], __s_bar_mod_MOD_vtab$s_bar#
        adds r28 = 24, r29
        ld8 r26 = [r28]
        cmp.ne p6, p7 = 0, r31
        (p7) adds r31 = 24, r29
        (p7) addl r30 = @ltoff(@fptr(__s_bar_mod_MOD_doit#)), gp
        (p7) ld8 r30 = [r30]
        (p7) st8 [r31] = r30
        ld8 r27 = [r26], 8
And the last instruction segfaults because r26 is 0 when it should be the address of __s_bar_mod_MOD_doit.  The load from r28 should not have been moved before the group of conditional instructions.  This is correct up to the mach pass, where the IA-64 port runs the second instruction scheduling pass.  The first instruction scheduling pass is before if-conversion, so we still have a branch around a block of instructions there.

I'm seeing different instruction scheduling and bundle filling with -funroll-loops, though it isn't immediately clear why, as there are no loops here.

I'm getting the same code with a x86-linux cross ia64-linux compiler.  Just look for the code using __s_bar_mod_MOD_vtab$s_bar and __s_bar_mod_MOD_doit in main.  So it should be possible to debug this on an x86-linux machine.
Comment 5 Jim Wilson 2010-05-17 20:24:37 UTC
A little more debugging.  I traced through the true_dependence call that is returning 0 when it should return 1.

We end up calling rtx_refs_may_alias_p at the end.  This calls refs_may_alias_p_1, which calls indirect_ref_may_alias_decl_p which discovers that we have different non-overlapping alias sets, and it declares that there is no aliasing here.  This is last-resort TBAA being used here.

We have different alias sets, because one reference is to
    ... arg 0 <var_decl 0xb7d4eba0 vtab$s_bar
        type <record_type 0xb7d4ea80 vtype$s_bar BLK ...
and the other is to
    ... arg 0 <indirect_ref 0xb7d74c94
	type <record_type 0xb7d4e060 vtype$foo BLK ...

It appears that the Fortran front end is deliberately confusing the types here, because in the .003t.original dump file I see
  a.$vptr = (struct vtype$foo *) &vtab$s_bar;
  a.$data = (struct foo *) &c;
  a.$vptr->doit (&a);

So either the fortran front end needs to get the types right, or else the fortran front end needs to explain to the alias code that these apparently unrelated types do alias.  Or maybe the alias code needs to be extended to recognize Fortran OOP types that can alias each other.  I didn't look at this.

Along the way, I did discover another place where it appears that we can solve the problem.  After the get_addr calls in true_dependence, we have
mem_addr
(if_then_else:DI (eq (value:BI 58:4011 @0x8b22b50/0x8b360e0)
        (const_int 0 [0]))
    (plus:DI (value:DI 55:2108434270 @0x8b22b2c/0x8b3608c)
        (const_int 24 [0x18]))
    (value:DI 57:57 @0x8b22b44/0x8b360c4))
insn 103
x_addr
(plus:DI (value:DI 55:2108434270 @0x8b22b2c/0x8b3608c)
    (const_int 24 [0x18]))
These addresses obviously conflict.  Unfortunately, neither memrefs_conflict_p nor rtx_equal_for_memref_p have any support for if_then_else inside an address.  If one of them was modified to check for an if_then_else and then recursively compare against both arms of the if_then_else, then that would solve the problem too.  This would prevent us from falling through to the last-resort TBAA code that isn't work as desired here.

I'm not planning to do any other work on this in the short term, as I have other IA-64 problems I need to try to fix first.
Comment 6 Paul Thomas 2010-07-16 17:35:09 UTC
(In reply to comment #5)

Is this now fixed on trunk?  We had to deal with the TBAA problem with the arrival of mem-ref2.

Paul
Comment 7 Tobias Burnus 2010-07-19 15:05:56 UTC
(In reply to comment #6)
> (In reply to comment #5)
> Is this now fixed on trunk?  We had to deal with the TBAA problem with the
> arrival of mem-ref2.

Seems to be fixed according to the result for
4.6.0 20100716 (experimental) [trunk revision 162264] (GCC) testsuite on ia64-unknown-linux-gnu
Cf.  http://gcc.gnu.org/ml/gcc-testresults/2010-07/msg01612.html
which has as only failures: maxlocval_3.f90 (excess errors) and typebound_proc_15.f03 (ICE, PR 44584).

H.J and Jim: Can we close this PR?
Comment 8 H.J. Lu 2010-07-19 15:38:06 UTC
It disappeared at least since revision 161672.