Bug 13768 - Incoherent behaviour in instantiation between -funit-at-a-time and -fno-unit-at-a-time
Summary: Incoherent behaviour in instantiation between -funit-at-a-time and -fno-unit-...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 3.4.0
: P2 normal
Target Milestone: 4.0.0
Assignee: Not yet assigned to anyone
URL:
Keywords:
: 13942 (view as bug list)
Depends on:
Blocks:
 
Reported: 2004-01-20 11:00 UTC by Ivan Godard
Modified: 2004-10-07 23:42 UTC (History)
5 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail: 3.3.3 3.4.0 4.0.0 3.1 2.95.3
Last reconfirmed: 2004-01-20 17:18:22


Attachments
Compiler output (-v -save-temps) *with no -O2* (619 bytes, text/plain)
2004-01-20 11:01 UTC, Ivan Godard
Details
Compiler output (-v -save-temps) *with -O2* (694 bytes, text/plain)
2004-01-20 11:02 UTC, Ivan Godard
Details
Source code (-save-temps) *with no -O2* (92.07 KB, text/plain)
2004-01-20 11:03 UTC, Ivan Godard
Details
Source code (-save-temps) *with -O2* (92.72 KB, text/plain)
2004-01-20 11:05 UTC, Ivan Godard
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Ivan Godard 2004-01-20 11:00:41 UTC
Bogus-looking syntax error when compiled -O2; no error if not. Expansion files (.ii) differ with/without too.
Comment 1 Ivan Godard 2004-01-20 11:01:44 UTC
Created attachment 5531 [details]
Compiler output (-v -save-temps)  *with no -O2*
Comment 2 Ivan Godard 2004-01-20 11:02:40 UTC
Created attachment 5532 [details]
Compiler output (-v -save-temps) *with -O2*
Comment 3 Ivan Godard 2004-01-20 11:03:54 UTC
Created attachment 5533 [details]
Source code (-save-temps) *with no -O2*
Comment 4 Ivan Godard 2004-01-20 11:05:05 UTC
Created attachment 5534 [details]
Source code (-save-temps) *with -O2*
Comment 5 Andrew Pinski 2004-01-20 15:49:46 UTC
I need a good C++ person here but the difference happens only with -funit-at-a-time, looks like 
unit at a time is instainating different templates.
Comment 6 Wolfgang Bangerth 2004-01-20 17:18:16 UTC
Here is a reduced testcase: 
--------------------------- 
template <typename T> struct X { 
    virtual void foo() const { 
      T::foo(1); 
    } 
}; 
 
template<typename T> 
void bar(T v) { 
  throw X<T>(); 
} 
 
inline void bar() { 
  bar(1); 
} 
--------------------------------- 
The testcase is illegal, since there is no int::foo function, but we 
get this: 
 
g/x> /home/bangerth/bin/gcc-3.4-pre/bin/c++ -c x.cc 
g/x> /home/bangerth/bin/gcc-3.4-pre/bin/c++ -c x.cc -funit-at-a-time 
x.cc: In member function `void X<T>::foo() const [with T = int]': 
x.cc:13:   instantiated from here 
x.cc:3: error: `foo' is not a member of `int' 
 
In other words, with -funit-at-a-time, gcc tries to lay down a copy of 
bar(), where it doesn't do that without that flag. Since there is no 
reason to do that, this is a bug, I guess. 
 
W. 
Comment 7 Andrew Pinski 2004-01-21 03:26:55 UTC
Mark, I think bug should be closed as will not fix as the code is invalid but compiling without 
-funit-at-a-time does not reject unless you want to keep it open for that in which case this is not a 
regression at all.
Comment 8 Ivan Godard 2004-01-21 05:22:43 UTC
Beg pardon, but code is *not* invalid. Standard clearly states that unused template functions are not compiled and may be invalid for particular template arguments. In the reduced example the template function is invoked from a non-inline function, but in the original the template is invoked from another template that is not itself instantiated. I think :-)

Even in the reduced - what's the point of "inline" if it causes unused template intantiations to clutter the executable with template bodies that cannot be called? If the standard required that the template be syntax checked just because it appears in an (uncalled) inline, then syntax check it - but don't instantiate it and clutter the executable.

Comment 9 Andrew Pinski 2004-01-21 07:44:27 UTC
(In reply to comment #8)
> Beg pardon, but code is *not* invalid. Standard clearly states that unused template functions are 
not compiled and may be invalid for particular template arguments. In the reduced example the 
template function is invoked from a non-inline function, but in the original the template is invoked 
from another template that is not itself instantiated. I think :-)
The above is correct but note the the function is virtual.

> Even in the reduced - what's the point of "inline" if it causes unused template intantiations to 
clutter the executable with template bodies that cannot be called? If the standard required that the 
template be syntax checked just because it appears in an (uncalled) inline, then syntax check it - 
but don't instantiate it and clutter the executable.

I could not find any where in my reading of the standard which says that inline functions are just
syntax checked and not done the full name lookup and such.  Note nothing ever gets emitted for 
code that is corrected.
Comment 10 Wolfgang Bangerth 2004-01-21 13:37:47 UTC
I think the validity of the test is immaterial -- the testcase shows 
a deficiency in the implementation of -funit-at-a-time. This is 
certainly not a big deal, but it's a bug that we should eventually 
get around to fixing. I concede that it should be lower priority 
than most of our bugs, and shouldn't block a release. 
 
W. 
Comment 11 Andrew Pinski 2004-01-31 18:22:29 UTC
*** Bug 13942 has been marked as a duplicate of this bug. ***
Comment 12 Eric Botcazou 2004-02-03 08:38:41 UTC
With -funit-at-a-time, the C++ front-end (decl2.c:maybe_emit_vtables) emits the
vtable for struct X, while it doesn't do so without -funit-at-a-time.

The difference in the behaviour boils down to this macro in cp-tree.h:

/* DECL_NEEDED_P holds of a declaration when we need to emit its
   definition.  This is true when the back-end tells us that
   the symbol has been referenced in the generated code.  If, however,
   we are not generating code, then it is also true when a symbol has
   just been used somewhere, even if it's not really needed.  We need
   anything that isn't comdat, but we don't know for sure whether or
   not something is comdat until end-of-file.  */
#define DECL_NEEDED_P(DECL)					\
  ((at_eof && TREE_PUBLIC (DECL) && !DECL_COMDAT (DECL))	\
   || (DECL_ASSEMBLER_NAME_SET_P (DECL)				\
       && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (DECL)))	\
   || (((flag_syntax_only || flag_unit_at_a_time) && TREE_USED (DECL))))


According to the comment, it seems that -funit-at-a-time behaves like
-fsyntax-only, that is it may emit DECLs that are not really needed.
Comment 13 Mark Mitchell 2004-02-03 09:25:28 UTC
The code is indeed invalid.

When a complete object of type X<int> is created, the compiler is allowed to
emit the vtable for X, and that permits instantiating the virtual functions.

However, this is an optimization deficiency in -funit-at-a-time.

I've therefore assigned the bug to Jan.
Comment 14 Jan Hubicka 2004-02-03 11:00:39 UTC
Subject: Re:  [3.4/3.5 Regression] -funit-at-a-time compiles unused inline function

> 
> ------- Additional Comments From mmitchel at gcc dot gnu dot org  2004-02-03 09:25 -------
> The code is indeed invalid.
> 
> When a complete object of type X<int> is created, the compiler is allowed to
> emit the vtable for X, and that permits instantiating the virtual functions.
> 
> However, this is an optimization deficiency in -funit-at-a-time.

Yes, the problem is that all dependencies are resolved before
optimization is done.  I am planning to address this by doing early pass
of tree-ssa optimization before inlining and cgraph construction.  That
way we should catch majority of cases.
I also plan to deffer output of datastrctures to the very end of
compilation and use information about what was really used by backend.

Honza
> 
> I've therefore assigned the bug to Jan.
> 
> -- 
>            What    |Removed                     |Added
> ----------------------------------------------------------------------------
>          AssignedTo|unassigned at gcc dot gnu   |jh at suse dot cz
>                    |dot org                     |
>              Status|NEW                         |ASSIGNED
> 
> 
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=13768
> 
> ------- You are receiving this mail because: -------
> You are on the CC list for the bug, or are watching someone who is.
Comment 15 Mark Mitchell 2004-02-03 15:46:42 UTC
Subject: Re:  [3.4/3.5 Regression] -funit-at-a-time compiles
 unused inline function

hubicka at ucw dot cz wrote:

>------- Additional Comments From hubicka at ucw dot cz  2004-02-03 11:00 -------
>Subject: Re:  [3.4/3.5 Regression] -funit-at-a-time compiles unused inline function
>
>  
>
>>------- Additional Comments From mmitchel at gcc dot gnu dot org  2004-02-03 09:25 -------
>>The code is indeed invalid.
>>
>>When a complete object of type X<int> is created, the compiler is allowed to
>>emit the vtable for X, and that permits instantiating the virtual functions.
>>
>>However, this is an optimization deficiency in -funit-at-a-time.
>>    
>>
>
>Yes, the problem is that all dependencies are resolved before
>optimization is done.  I am planning to address this by doing early pass
>of tree-ssa optimization before inlining and cgraph construction.  That
>way we should catch majority of cases.
>I also plan to deffer output of datastrctures to the very end of
>compilation and use information about what was really used by backend.
>
>Honza
>
What do you suggest, if anything, for GCC 3.4?

(This is potentially a regression with respect to the size of the 
generated code.  There is lots of code with trivial constructors that, 
after inlining, will be eliminated.)

Comment 16 Jan Hubicka 2004-02-03 15:53:28 UTC
Subject: Re:  [3.4/3.5 Regression] -funit-at-a-time compiles unused inline function

> 
> ------- Additional Comments From mark at codesourcery dot com  2004-02-03 15:46 -------
> Subject: Re:  [3.4/3.5 Regression] -funit-at-a-time compiles
>  unused inline function
> 
> hubicka at ucw dot cz wrote:
> 
> >------- Additional Comments From hubicka at ucw dot cz  2004-02-03 11:00 -------
> >Subject: Re:  [3.4/3.5 Regression] -funit-at-a-time compiles unused inline function
> >
> >  
> >
> >>------- Additional Comments From mmitchel at gcc dot gnu dot org  2004-02-03 09:25 -------
> >>The code is indeed invalid.
> >>
> >>When a complete object of type X<int> is created, the compiler is allowed to
> >>emit the vtable for X, and that permits instantiating the virtual functions.
> >>
> >>However, this is an optimization deficiency in -funit-at-a-time.
> >>    
> >>
> >
> >Yes, the problem is that all dependencies are resolved before
> >optimization is done.  I am planning to address this by doing early pass
> >of tree-ssa optimization before inlining and cgraph construction.  That
> >way we should catch majority of cases.
> >I also plan to deffer output of datastrctures to the very end of
> >compilation and use information about what was really used by backend.
> >
> >Honza
> >
> What do you suggest, if anything, for GCC 3.4?
> 
> (This is potentially a regression with respect to the size of the 
> generated code.  There is lots of code with trivial constructors that, 
> after inlining, will be eliminated.)

I think we can keep it as it is now.  I did quite huge amount of
measuring and the unit-at-a-time is a win for majority of C++ programs,
so I think the other benefits outweight it.
It is quite dificult to solve with current framework, unforutnately,
since we discover such facts only during RTL expansion pass and because
we mix analysis and optimization, we want to order things in a way so
calees are compiled first and thus we can't take them back.  My CFG
transparent expansion/inlining project is all about getting this
chicken-egg problem broken up.

Note that if the constructor get inlined to all call sites, it's out of
line copy will be elliminated.  We only lose in the case the
constructor is not inlined for whatever reason and then the call site is
removed later, for instance because the code turns out to be dead.  This
don't seems to be terribly common in real code from what I've seen.

Another problem is that we don't have ability to elliminate static
cosntructors when static variable turns out to be unnecesary.  Richard
did some work on this, but didn't finished it, I plan to look into it
after tree-SSA merge.

Honza
> 
> 
> 
> -- 
> 
> 
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=13768
> 
> ------- You are receiving this mail because: -------
> You are the assignee for the bug, or are watching the assignee.
Comment 17 Jan Hubicka 2004-02-03 15:59:32 UTC
Subject: Re:  [3.4/3.5 Regression] -funit-at-a-time compiles unused inline function

> 
> ------- Additional Comments From jh at suse dot cz  2004-02-03 15:53 -------
> Subject: Re:  [3.4/3.5 Regression] -funit-at-a-time compiles unused inline function
> 
> > 
> > ------- Additional Comments From mark at codesourcery dot com  2004-02-03 15:46 -------
> > Subject: Re:  [3.4/3.5 Regression] -funit-at-a-time compiles
> >  unused inline function
> > 
> > hubicka at ucw dot cz wrote:
> > 
> > >------- Additional Comments From hubicka at ucw dot cz  2004-02-03 11:00 -------
> > >Subject: Re:  [3.4/3.5 Regression] -funit-at-a-time compiles unused inline function
> > >
> > >  
> > >
> > >>------- Additional Comments From mmitchel at gcc dot gnu dot org  2004-02-03 09:25 -------
> > >>The code is indeed invalid.
> > >>
> > >>When a complete object of type X<int> is created, the compiler is allowed to
> > >>emit the vtable for X, and that permits instantiating the virtual functions.
> > >>
> > >>However, this is an optimization deficiency in -funit-at-a-time.
> > >>    
> > >>
> > >
> > >Yes, the problem is that all dependencies are resolved before
> > >optimization is done.  I am planning to address this by doing early pass
> > >of tree-ssa optimization before inlining and cgraph construction.  That
> > >way we should catch majority of cases.
> > >I also plan to deffer output of datastrctures to the very end of
> > >compilation and use information about what was really used by backend.
> > >
> > >Honza
> > >
> > What do you suggest, if anything, for GCC 3.4?
> > 
> > (This is potentially a regression with respect to the size of the 
> > generated code.  There is lots of code with trivial constructors that, 
> > after inlining, will be eliminated.)
> 
> I think we can keep it as it is now.  I did quite huge amount of
> measuring and the unit-at-a-time is a win for majority of C++ programs,
> so I think the other benefits outweight it.
> It is quite dificult to solve with current framework, unforutnately,
> since we discover such facts only during RTL expansion pass and because
> we mix analysis and optimization, we want to order things in a way so
> calees are compiled first and thus we can't take them back.  My CFG
> transparent expansion/inlining project is all about getting this
> chicken-egg problem broken up.
> 
> Note that if the constructor get inlined to all call sites, it's out of
> line copy will be elliminated.  We only lose in the case the
> constructor is not inlined for whatever reason and then the call site is
> removed later, for instance because the code turns out to be dead.  This
> don't seems to be terribly common in real code from what I've seen.
> 
> Another problem is that we don't have ability to elliminate static
> cosntructors when static variable turns out to be unnecesary.  Richard
> did some work on this, but didn't finished it, I plan to look into it
> after tree-SSA merge.

Actually looking deeper into this specific testcase,  I believe that if
the source program was correct, unit-at-a-time would emit empty file
too, since there is no entry point from where the call in question can
be reached, so it just builds the program representation in memory prior
optimizing it.
This is because of your request to change C++ frontend that way (my
initial patch didn't force instantiation of all TREE_USED templates).

I think this is correct thing - GCC should error out on this testcase.
Why it is considered a bug at first place?

Honza
> 
> Honza
> > 
> > 
> > 
> > -- 
> > 
> > 
> > http://gcc.gnu.org/bugzilla/show_bug.cgi?id=13768
> > 
> > ------- You are receiving this mail because: -------
> > You are the assignee for the bug, or are watching the assignee.
> 
> 
> -- 
> 
> 
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=13768
> 
> ------- You are receiving this mail because: -------
> You are the assignee for the bug, or are watching the assignee.
Comment 18 Mark Mitchell 2004-02-03 16:02:26 UTC
Jan believes that this is (a) hard to fix, and (b) not critical based on
measurements of real code, so I've postponed this until GCC 3.5.
Comment 19 Jan Hubicka 2004-02-03 16:04:24 UTC
Subject: Re:  [3.4/3.5 Regression] -funit-at-a-time compiles unused inline function

> 
> ------- Additional Comments From mmitchel at gcc dot gnu dot org  2004-02-03 16:02 -------
> Jan believes that this is (a) hard to fix, and (b) not critical based on
> measurements of real code, so I've postponed this until GCC 3.5.

Actually I think this bugreport shall be closed (or maintained as bug
about accepting illegal code in non-unit-at-a-time compilation mode),
see me other mail.

Honza
> 
> -- 
>            What    |Removed                     |Added
> ----------------------------------------------------------------------------
>    Target Milestone|3.4.0                       |3.5.0
> 
> 
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=13768
> 
> ------- You are receiving this mail because: -------
> You are on the CC list for the bug, or are watching someone who is.
Comment 20 Mark Mitchell 2004-02-03 17:22:49 UTC
Subject: Re:  [3.4/3.5 Regression] -funit-at-a-time compiles
 unused inline function


>Actually looking deeper into this specific testcase,  I believe that if
>the source program was correct, unit-at-a-time would emit empty file
>too, since there is no entry point from where the call in question can
>be reached, so it just builds the program representation in memory prior
>optimizing it.
>This is because of your request to change C++ frontend that way (my
>initial patch didn't force instantiation of all TREE_USED templates).
>
>I think this is correct thing - GCC should error out on this testcase.
>Why it is considered a bug at first place?
>  
>
If the vtable will not actually be emitted to the object file, then this 
is not a bug, and you can close it.

Comment 21 Andrew Pinski 2004-02-05 17:14:29 UTC
Resummizing and changing the target.
Comment 22 Giovanni Bajo 2004-02-05 17:23:10 UTC
No, sorry, the code is not invalid per-se. It's just unspecified, so both the 
unit-at-a-time and the function-at-a-time behaviours are correct. Mark is 
asking if the vtable is emitted or not. If it's not emitted, then it's correct 
that the function is not instantiated, and the bug is invalid.
Comment 23 Ivan Godard 2004-02-05 20:04:06 UTC
Whether it's valid, invalid or unspecified, the user's mental model of the compilation process expects that the set of syntax errors reported should not depend on the optimization level on the command line. I suggest (for general user happiness and fewer nuisance reports) that the behavior be made invariant - whatever behavior is chosen.

Ivan
Comment 24 Jan Hubicka 2004-05-05 20:25:21 UTC
Making the behaviour consistent across function-at-a-time and unit-at-a-time is 
almost impossible in this testcase without major reorganization of 
function-at-a-time.  I would rather vote to drop function-at-a-time on some of 
future releases. 
 
Honza 
Comment 25 Andrew Pinski 2004-08-03 06:03:19 UTC
Fixed by:
2004-07-29  Mark Mitchell  <mark@codesourcery.com>

        * cp-tree.h (IDENTIFIER_REPO_CHOSEN): Define.
        (lang_decl_flags): Narrow the width of "languages".  Add
        repo_available_p.
        (DECL_NEEDED_P): Remove.
        (FOR_EACH_CLONE): New macro.
        (DECL_REPO_AVAILABLE_P): Likewise.
        ......