Topic: inline ignored on vararg fns??


Author: Edward Diener <eddielee@abraxis.com>
Date: 1997/10/02
Raw View
My guess is that the code that picks up the various vararg parameters is lengthy
and therefore these compilers choose not to inline it. I don't believe that
according to the C++ standard the "inline" keyowrd forces the compiler to inline
code but is just a suggestion to the compiler. In these case the compiler
rejects the suggestion on the basis that inline functions should be short and
sweet.

Paul, Bossi[SMTP:bossi@primenet.com] wrote:

> I've viewed the disassemblies from the latest version 5.0 Microsoft =
> Visual C++ compiler for Win32 and from the version 11 CodeWarrior C++ =
> compiler for Mac and in both cases if I declare an inline function with =
> variable arguments it is *never* inlined.  Also in both cases, if I =
> simply remove the ellipsis arg the function always is inlined.
>
> The fact that this behavior happens on two widely used and relatively =
> conformant C++ compilers leads me to believe that there's something in =
> the standard that either condones or forces it.  Is that true?  If so, =
> what?
>
> // file test.cpp
>
> // compile and view disassemblies to test on your system.
>
> inline void MyInlineFn(char* psz, ...) {} // *does not* get inlined
> //inline void MyInlineFn(char* psz) {}    // *does* get inlined
>
> void test()
> {
>         MyInlineFn( "hello" );
> }
>
> -- Paul
> ---
> [ comp.std.c++ is moderated.  To submit articles: Try just posting with your
>                 newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
>   comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
>   Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
>   Comments? mailto:std-c++-request@ncar.ucar.edu
> ]
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: "Paul Bossi" <bossi@primenet.com>
Date: 1997/10/08
Raw View
Sorry for the delay in replying, I've been busy.

In article <342c37ac.27200290@engnews1.eng>,
  stephen.clamage_nospam@eng.sun.com (Steve Clamage) wrote:
>
> Nothing in the standard suggests that any particular kind of function
> should not be inlined.

Thanks, this is what I was looking for, since judging from your posts
on this newsgroup you are an expert on the standard.  I do take issue
with the rest of your post though.

> But practical matters of implementation
> sometimes mean that some functions are just not going to be inlined.
>
> A variadic function needs to use the <stdarg.h> facilities to get at
> or pass along its arguments. (And it doesn't make sense to base
> compiler optimizations on pathological cases like variadic functions
> that ignore their arguments.) Those facilities in turn depend on

Well, you are talking about assumptions regarding the complexity of
the *content* of the variadic function (the first time I read this
I actually thought you were referring to requirements of the compiler
itself, which I would take seriously).  For some reason, you think it
legitimate to make assumptions regarding these contents in the variadic
case even when the function is declared inline.

I'd argue it's not pathological for a function to ignore arguments, and
moreover that even compiler writers recognize this, albeit obviously not
quite enough in the variadic situation.  Case in point re: non-
pathological:  debug-only code.  A debug-only print function will
always totally ignore arguments in the release world.  It so happens
that this is exactly what I was working on when the lack of variadic
inlining came to my attention.  I was trying to replace the sick, old
#define-based way of doing debug-only tracing with a set of C++ template
classes (which I had already created in a project that did run-time
tracing).  I anticipated that I could easily modify these classes to do
debug-only tracing.  In fact I couldn't because of the problem I've
outlined.  You'll excuse me if I don't consider trying to do debug-only
tracing a pathological case.  I consider it virtually universal.

If compiler writers thought it pathological for functions not to use
their arguments, then they would create space in the executable image
for the string "xxx" in the following code, because after all according
to your argument the following represents an optimization based on
a "pathological" case.

  inline void MyInlineFn( const char* psz ) {}

  void MyNonInlineFn()
  {
    MyInlineFn( "xxx" );
      // not a single compiler generated the "xxx" string in the
      //  executable image.
  }

Why should a compiler writer consider it more legitimate for a
non-variadic function to ignore its arguments than for a variadic?

> details of the stack frame, and depend on finding particular arguments
> at particular offsets. If the function is inlined, it may not be
> possible to ensure those arguments appear at the right place, since in
> general the inline function body will be mixed with the calling
> expression.
>

Certainly you can't inline a function that is actually using the
stdarg.h facilities as part of its content.  Having an inline variadic
function whose content *relies on* stdarg.h is pointless -- it is in
fact a contradiction in terms, and I recognize this; however, that is not
the example I presented so I don't really know why you (and a couple
others)
are countering me on this basis.  My point here is not that I want the
compiler to perform inlining for extremely complicated situations as
you are presenting.  Completely the opposite, my point is that any decent
compiler should inline in certain situations that are about as easy to
identify as any can be.

I have always thought that any decent compiler should
be smart enough to *not* ignore the inline hint in at least two
situations:

1)  Empty function.  The compiler simply does nothing.

2)  Simple return statement, e.g. return 2 + 2;

A related situation that I think a decent compiler should inline is,

3)  if statement based on constant value. e.g.
 const int k_bDebug = 0;
 if ( k_bDebug ) myostream << "something got printed";

Perhaps compiler writers don't think they need to bother with even
these simple cases in the case of variadic functions for the
"instinctual" reasons you present.

Again, the issue here is why are you defending the legitimacy of a
compiler writer to make assumptions about the *content* of a routine
in one case (the variadic) that they don't make in another, as shown
above.

> Thus, in order to inline a variadic function, you would need to turn
> off optimizations that would result in mixing the inlined function
> body with the expression surrounding the call, and take steps to force
> the inline function's arguments onto the stack in a way that simulates
> a function call, possibly also needing to create an actual stack
> frame. It seems very unlikely that you would get any net benefit
> compared to not inlining the function, but it would greatly complicate
> the compiler.
>

This is a world of ether that has nothing to do with my example or my
question.

As a C++ supporter, I like to see more functionality being done from the
language itself.  I'd point out that in the Java O'Reilly book as a
thrust against C and C++, they emphasize how precompilers are
unnecessary for virtually all commonly encountered scenarios because
of the fact that Java compilers handle case 3 above.  Again, I bring
this point up because I think it's a shortcoming in C++ that I can't
do more things at the *language level* which is what I'm trying to do
here, again debug-only tracing which is currently relegated to #defines.

> On some particular platform it might be the case that inlining a
> variadic function imposes no special considerations. In that case,
> they would be more likely to be inlined. But also consider that a
> variadic function typically contains a loop and sometimes also a
> switch statement, and it is common for compilers to refuse to inline a
> function containing either of those constructs.
>

Again, not what I'm saying...


-- Paul
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: stephen.clamage_nospam@eng.sun.com (Steve Clamage)
Date: 1997/10/10
Raw View
On 08 Oct 97 14:28:54 GMT, "Paul Bossi" <bossi@primenet.com> wrote:

>> But practical matters of implementation
>> sometimes mean that some functions are just not going to be inlined.
>>
>> A variadic function needs to use the <stdarg.h> facilities to get at
>> or pass along its arguments. (And it doesn't make sense to base
>> compiler optimizations on pathological cases like variadic functions
>> that ignore their arguments.) Those facilities in turn depend on ...
>
>Well, you are talking about assumptions regarding the complexity of
>the *content* of the variadic function (the first time I read this
>I actually thought you were referring to requirements of the compiler
>itself, which I would take seriously).  For some reason, you think it
>legitimate to make assumptions regarding these contents in the variadic
>case even when the function is declared inline.

We are in any case talking about compiler optimizations, not
correctness of generated code. We require that the code be correct,
optimized or not. I was explaining why a compiler implementor might
choose not to inline variadic functions. The arguments were about
simple economics. Let's look at that topic in more detail.

Suppose you are a compiler implementor. If you have infinite resources
(people, time, money) you can create a compiler that generates the
most efficient possible code for every program. Of course, resources
are always constrained, and time is often a very significant factor.

Thus, in the real world, compiler implementors must choose where to
spend their resources, and in particular, what cases to optimize.
Apart from the time to design and write the compiler code to perform
an optimization, every optimization added to the compiler means more
opportunity for error, and more cases to test. It makes sense to
choose those optimizations that yield measurable benefits, and ignore
those that do not. (Or put them on a "maybe someday" list.)

Variadic functions are rare in C, and even less common in C++. (There
are not a lot of good reasons to use variadic functions in delivered
production code in C, and far fewer reasons in C++. C++ provides good
alternatives.) On that basis alone, it doesn't pay to devote resources
to optimizing variadic functions. Optimizing variadic functions means
that some other more common case doesn't get optimized, given limited
resources.

The C++ language definition neither forbids nor requires actually
inlining any function. Inlining, along with other code improvements,
falls into the "quality of implementation" realm. If you are unhappy
with the quality of a compiler you use, talk to the vendor or look for
another one that does what you want.

---
Steve Clamage, stephen.clamage_nospam@eng.sun.com
( Note: remove "_nospam" when replying )
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: Paul Bossi[SMTP:bossi@primenet.com]
Date: 1997/09/25
Raw View
I've viewed the disassemblies from the latest version 5.0 Microsoft =
Visual C++ compiler for Win32 and from the version 11 CodeWarrior C++ =
compiler for Mac and in both cases if I declare an inline function with =
variable arguments it is *never* inlined.  Also in both cases, if I =
simply remove the ellipsis arg the function always is inlined.

The fact that this behavior happens on two widely used and relatively =
conformant C++ compilers leads me to believe that there's something in =
the standard that either condones or forces it.  Is that true?  If so, =
what?


// file test.cpp

// compile and view disassemblies to test on your system.

inline void MyInlineFn(char* psz, ...) {} // *does not* get inlined
//inline void MyInlineFn(char* psz) {}    // *does* get inlined

void test()
{
 MyInlineFn( "hello" );
}


-- Paul
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: stephen.clamage_nospam@eng.sun.com (Steve Clamage)
Date: 1997/09/27
Raw View
On 25 Sep 1997 17:44:31 PDT, Paul Bossi[SMTP:bossi@primenet.com]
wrote:

> ... if I declare an inline function with
>variable arguments it is *never* inlined.  Also in both cases, if I
>simply remove the ellipsis arg the function always is inlined.
>
>The fact that this behavior happens on two widely used and relatively
>conformant C++ compilers leads me to believe that there's something in
>the standard that either condones or forces it.

Nothing in the standard suggests that any particular kind of function
should not be inlined. But practical matters of implementation
sometimes mean that some functions are just not going to be inlined.

A variadic function needs to use the <stdarg.h> facilities to get at
or pass along its arguments. (And it doesn't make sense to base
compiler optimizations on pathological cases like variadic functions
that ignore their arguments.) Those facilities in turn depend on
details of the stack frame, and depend on finding particular arguments
at particular offsets. If the function is inlined, it may not be
possible to ensure those arguments appear at the right place, since in
general the inline function body will be mixed with the calling
expression.

Thus, in order to inline a variadic function, you would need to turn
off optimizations that would result in mixing the inlined function
body with the expression surrounding the call, and take steps to force
the inline function's arguments onto the stack in a way that simulates
a function call, possibly also needing to create an actual stack
frame. It seems very unlikely that you would get any net benefit
compared to not inlining the function, but it would greatly complicate
the compiler.

On some particular platform it might be the case that inlining a
variadic function imposes no special considerations. In that case,
they would be more likely to be inlined. But also consider that a
variadic function typically contains a loop and sometimes also a
switch statement, and it is common for compilers to refuse to inline a
function containing either of those constructs.

---
Steve Clamage, stephen.clamage_nospam@eng.sun.com
( Note: remove "_nospam" when replying )
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: miker3@ix.netcom.com (Mike Rubenstein)
Date: 1997/09/27
Raw View
Paul Bossi[SMTP:bossi@primenet.com] wrote:

> I've viewed the disassemblies from the latest version 5.0 Microsoft =
> Visual C++ compiler for Win32 and from the version 11 CodeWarrior C++ =
> compiler for Mac and in both cases if I declare an inline function with =
> variable arguments it is *never* inlined.  Also in both cases, if I =
> simply remove the ellipsis arg the function always is inlined.
>
> The fact that this behavior happens on two widely used and relatively =
> conformant C++ compilers leads me to believe that there's something in =
> the standard that either condones or forces it.  Is that true?  If so, =
> what?
>
>
> // file test.cpp
>
> // compile and view disassemblies to test on your system.
>
> inline void MyInlineFn(char* psz, ...) {} // *does not* get inlined
> //inline void MyInlineFn(char* psz) {}    // *does* get inlined
>
> void test()
> {
>  MyInlineFn( "hello" );
> }

I can't find any such restriction.  I'm not sure about the Mac, but
the Microsoft implementation of a function with variable arguments
doesn't really lend itself too well to inlining.  It cold be done, of
course, but its easy to see why Microsoft would decide its not worth
the trouble.  I suspect that is true of most architectures.

Note that inline is a hint.  The compiler is neither required to
implment inline functions as inline code nor forbidden from
implementing other functions as inline code.  As long as the required
semantics are provided, a function may be implemented in any way the
implementor sees fit.

Michael M Rubenstein
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]