public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* Re: forcing tail/sibling call optimization
@ 2000-11-26 15:46 Robert Dewar
  2000-11-26 16:21 ` Joseph S. Myers
                   ` (2 more replies)
  0 siblings, 3 replies; 64+ messages in thread
From: Robert Dewar @ 2000-11-26 15:46 UTC (permalink / raw)
  To: dewar, fjh; +Cc: bernds, gcc

Note that if you want to make a warning message a formal requirement,
then you must provide a formal definition of what a warning message is,
and I do not think you want to get into that sort of thing :-)

I think there is real merit in providing fairly formal specifications
for GNU C enhancements for three reasons.

1. The attempt to produce a FFS can often reveal difficulties that are
not apparent in a less formal approach.

2. If other C compilers want to copy the feature, which I assume we
welcome, then there is a clear guide.

3. If the ISO committee wants to copy the feature, which I assume
we welcome, then there is a clear guide.

^ permalink raw reply	[flat|nested] 64+ messages in thread
* Re: forcing tail/sibling call optimization
@ 2000-11-29  4:58 Robert Dewar
  0 siblings, 0 replies; 64+ messages in thread
From: Robert Dewar @ 2000-11-29  4:58 UTC (permalink / raw)
  To: fjh, mark; +Cc: gcc

<<  I think we're going to have to agree to disagree here.  It's still
my position that we shouldn't introduce an extension for the tail-call
stuff, because I don't view the translation of functional languages
into C as fundamentally the right way to go.  It would be so much
better to write a Scheme front-end for GCC -- and I would totally
support, then, providing a bit on CALL_EXPRs to force tailcalls.
Presumably, the Scheme front-end would set this bit.
>>

Mark, you might disagree, but the approach of translating into C in cases
like this is VERY well established, and is pretty much a standard 
technique. It is not so terrible to say, sorry, gcc cannot support your
needs, but it seems a bit gratuitious to say, sorry, gcc won't support
your needs, because we think you are doing the wrong thing.

So anyway, add me to the list of disagreers here, but as you say, 
no big deal that people disagree on this :-)

^ permalink raw reply	[flat|nested] 64+ messages in thread
* Re: forcing tail/sibling call optimization
@ 2000-11-27 15:33 Mike Stump
  0 siblings, 0 replies; 64+ messages in thread
From: Mike Stump @ 2000-11-27 15:33 UTC (permalink / raw)
  To: dewar, freitag, law; +Cc: gcc

> To: freitag@alancoxonachip.com, law@redhat.com
> Date: Mon, 27 Nov 2000 11:44:00 -0500 (EST)
> From: dewar@gnat.com (Robert Dewar)

> I think this misses the point

Further, most people are missing the point, it is _NOT_ an
optimization.  Just as a call produces code to call a routine, a
recursive tail call is a direction to produce a goto.

When you think of it this way, you realize, you don't need a warning
when it doesn't apply, because it _must_ apply.  If the abi needs to
be different, then it needs to be different.  If you have to have an
attribute, well, that is the price to pay.  If you have to have it
prototyped in all places, than that is the price to pay.  If varargs
doesn't work with it, well, than that is a documented limitation.

We need to see if what we can come up with is suitable for what people
need from C as an assembler.  I suspect they will just say fine, no
problem, tweak the generation slightly, and presto.

^ permalink raw reply	[flat|nested] 64+ messages in thread
* Re: forcing tail/sibling call optimization
@ 2000-11-27 10:04 Robert Dewar
  0 siblings, 0 replies; 64+ messages in thread
From: Robert Dewar @ 2000-11-27 10:04 UTC (permalink / raw)
  To: dewar, law; +Cc: freitag, gcc

<<In contrast, dependence on this kind of transformation in other languages
might be quite reasonable (and I believe there are languages which explicitly
require these transformations).  Typically those languages have conventions
which significantly ease these kinds of transformations.

We're apparently not communicating well.
>>

Definitely not!

We have a *functional* requirement in the source language to use O(1)
space in these cases.

We want to buidl a translator that translates into a language similar
to C (C-- was mentioned in this context).

GNU-C is *almost* usable as a target, but not quite, because of the
lack of control over sibling call "optimization".

Yes, of course it is terrible for a user program to depend on optimization,
but that has nothing at all to do with the situation here.

It seems quite reasonable to me to consider adding functionality to
GNU-C to support this requirement. Of course it would never be appropriate
for a programmer writing in C to use this feature directly in C code (well
almost never).

I don't see what the big deal is in implementing something useful here,
and it definitely does meet a need.

<<Optimizations can occur across several axis -- execution speed, code density,
stack space, etc etc etc.  This transformation is an optimization in stack
space and sometimes code speed.
>>

No, it is NOT an optimization in stack space, it is a functional feature
that is needed to ensure proper translation of the source program.

^ permalink raw reply	[flat|nested] 64+ messages in thread
* Re: forcing tail/sibling call optimization
@ 2000-11-27  9:39 Geert Bosch
  2000-11-27 12:06 ` Jeffrey A Law
  0 siblings, 1 reply; 64+ messages in thread
From: Geert Bosch @ 2000-11-27  9:39 UTC (permalink / raw)
  To: law; +Cc: gcc

On Mon, 27 Nov 2000 09:26:06 -0700, Jeffrey A Law wrote:

  If you _must_ have tail calls optimized to gotos, then write them that way
  or use a language which guarantees tail calls will turn into gotos.  If
  tail call optimizations are merely convenience, then write them as calls :-)

The original request by Fergus Henderson was:

<<This feature is important for compilers of high-level functional and
  logic programming languages that target C.  For such languages,
  recursion is the primary form of iteration, and it is important that
  sibling calls be optimized.  Often the high-level language compiler has
  more information about when it is safe to do tail calls than gcc has,
  but currently there is no way for the high-level language compiler to
  communicate that to gcc.

  The language C-- (see <www.cminusminus.org>), which is designed to be
  ideal as a target language, provides this feature.  I would like GNU C
  to provide it too.>>

I think that adding extentions to GNU C in order to support the (changing) 
C-- language is a bad idea.  On the other hand, extending GCC to allow 
front-ends to implement such a language seems like a worthwhile goal.  

In order to write a GCC front-end for any language with proper 
tail-recursion,  there should be a way in the tree to represent a tail call. 
If the GCC backend is not able to compile this on a certain architecture,
it abandons the compilation with an error.

  -Geert



^ permalink raw reply	[flat|nested] 64+ messages in thread
* Re: forcing tail/sibling call optimization
@ 2000-11-27  9:08 Robert Dewar
  2000-11-27  9:14 ` Bernd Schmidt
  0 siblings, 1 reply; 64+ messages in thread
From: Robert Dewar @ 2000-11-27  9:08 UTC (permalink / raw)
  To: bernds, freitag; +Cc: gcc, law

<<IMHO we shouldn't encourage users to rely on gcc being able to optimize
tail calls.  It's a nice optimization, but if a program relies on it for
correctness, that program is broken.
>>

That is certainly true in C, but it makes C useless as a target for the
kind of translation being considered here, where the "optimization" is
a fundamental requirement. The discussion on the above subject line,
is all about creating a variant language that WOULD have the required
semantic characteristics.

^ permalink raw reply	[flat|nested] 64+ messages in thread
* Re: forcing tail/sibling call optimization
@ 2000-11-27  8:44 Robert Dewar
  2000-11-27  9:44 ` Jeffrey A Law
  0 siblings, 1 reply; 64+ messages in thread
From: Robert Dewar @ 2000-11-27  8:44 UTC (permalink / raw)
  To: freitag, law; +Cc: gcc

<<Therein lies the first problem -- programmer dependence on specific
optimizations in the compiler.  That's a fundamental mistake.
>>

I think this misses the point, this is not just an optimization, it is
a fundamental functional capability, in other words, we would want the
compiler to do this EVEN IF it slowed down execution. There is a big
difference between an optimization that simply saves some time, and
a fundamental transformation that changes the computational nature
of the program. Changing the amount of storage used from O(who knows
what) to O(1) is not simply an "optimization".

^ permalink raw reply	[flat|nested] 64+ messages in thread
* Re: forcing tail/sibling call optimization
@ 2000-11-26 18:09 Robert Dewar
  0 siblings, 0 replies; 64+ messages in thread
From: Robert Dewar @ 2000-11-26 18:09 UTC (permalink / raw)
  To: dewar, fjh; +Cc: bernds, gcc

<<I happen to think that it would be good for ANSI/ISO language standards
to include requirements for warnings.  However, that is a separate battle,
and for this proposal I'm happy to amend the formal spec so that the
warnings are merely implementation advice rather than requirements.
>>

It is an unwinnable battle I would say, since a formal specification
of what constitutes a warning msg is impossible. Note that not even
the Ada standard *requires* error messages as such (it is just to
hard to define what an error message is). The only formal requirement
in Ada is that certain errors be "be detected prior to run time".

It is a common misconception that making things implementation advice
rather than implementation requirements weakens the "requirement", but
in fact IA is often much stronger, since you can say things in IA
that you could never get away with in formal definitions.

^ permalink raw reply	[flat|nested] 64+ messages in thread
* Re: forcing tail/sibling call optimization
@ 2000-11-26 15:27 Robert Dewar
  2000-11-26 17:56 ` Fergus Henderson
  0 siblings, 1 reply; 64+ messages in thread
From: Robert Dewar @ 2000-11-26 15:27 UTC (permalink / raw)
  To: dewar, fjh; +Cc: bernds, gcc

<<In ANSI/ISO C: no.  But the ANSI/ISO C standard is not a good model
for how to write specifications.
>>

I disagree, it is an EXCELLENT model for how to write *specifications*.


<<In GNU C: yes.  For example, many parts of the GNU C manual say
that if a certain option is enabled, the compiler will issue
certain warnings.  If the GNU C manual is treated as a specification,
these parts of the manual are definitely requirements on the compiler.
>>

The GNU C manual is nowhere near a formal specification, it is fine
for a compiler manual to talk about warnings, but it is not possible
to "treat" the GNU C manual as a specification, it is just not 
precise enough.

So if you want to state what you are proposing as a formal specification,
the "requirement" for a warning should be implementation advice. After all
we expect that GNU C will follow implementation advice for features that
we design :-)

^ permalink raw reply	[flat|nested] 64+ messages in thread
* Re: forcing tail/sibling call optimization
@ 2000-11-26 10:59 Timothy J. Wood
  0 siblings, 0 replies; 64+ messages in thread
From: Timothy J. Wood @ 2000-11-26 10:59 UTC (permalink / raw)
  To: Robert Dewar; +Cc: fjh, gcc

On Sunday, November 26, 2000, at 08:14 AM, Robert Dewar wrote:
>The formal definition seems quite reasonable here, but I must say
>I dislike the syntax, and it is unnecessarily provocative, since
>this really is not semantically a goto at all (e.g. the formal
>denmotational semantics would have nothing to do with the semantics
>of goto). Why not something like "tail return" or perhaps better 
>simply a compiler directive.

  This would introduce a new reserved word, wouldn't it?  This would break existing source code that used 'tail' as a variable, class, etc.


  It seems like rather than telling the compiler to just blindly do a tail return even though a function takes a pointer that it could conceivably store, a 'better' solution would be to add a attribute that could be applied to arguments to specify that the function doesn't hold onto that pointer.  The compiler would then have enough information to decide when it could do a tail call and the compiler could potentially _enforce_ the restriction that the argument cannot be stored anywhere but in a location that is provably part of a stack local.

  The only thing this wouldn't do is to give a warning/error when the developer knows that a tail call must occur to prevent bugs (like stack overflow), but it seems like adding an attribute to the arguments would prevent errors due to someone providing a function that isn't a valid tail call target.

-tim

^ permalink raw reply	[flat|nested] 64+ messages in thread
* Re: forcing tail/sibling call optimization
@ 2000-11-26  9:12 Geert Bosch
  0 siblings, 0 replies; 64+ messages in thread
From: Geert Bosch @ 2000-11-26  9:12 UTC (permalink / raw)
  To: Fergus Henderson, gcc

On Sun, 26 Nov 2000 22:55:56 +1100, Fergus Henderson wrote:

  the compiler won't be able to perform sibling call optimization, since
  it can't be sure that bar() doesn't save the addresses of x and y in
  some storage that is accessible to baz().  I would like some way to
  tell the compiler to go ahead and perform the sibling call
  optimization anyway.

Actually, a similar situation exist with "const" calls.
It is possible to mark a function with __attribute__ ((const)),
but not do this for individual calls. 

When passing arguments by reference, it is not possible to
mark a function const, as the compiler will assume the function
will return the same result if the address of the argument has
not changed, even when the value of the argument has.

The example below shows an instance of this problem. I wonder
what would be involved in allowing front-ends to specify what
calls should be considered const. In GNAT for example, this information
is readily available but it cannot be communicated to the backend
easily.

  -Geert

#include <stdio.h>
int calls = 0; /* Used for counting the actual nr of invocations of len */

__attribute__ ((const)) size_t len (const char *string)
   /* Calls to len should be considered considered to be const iff
    * the actual passed to string is const. So, in fact, it should
    * be possible to define the const attribute on a per call basis */
{  calls++; 
   return strlen (string);
}

int words (char *sentence)
{  size_t i;
   int spaces = 0;
   /* sentence is not constant in this context, so calls to len
    * should not be considered to be __attribute__ ((const)) calls */
   for (i = 0; i < len (sentence); i++)
   { if (sentence[i] == '.') sentence[i + 1] = 0;
     if (sentence[i] == ' ') spaces++;
   }
   return len (sentence) > 0 ? spaces + 1 : 0;
} 

int cwords (const char *sentence)
{  size_t i;
   int spaces = 0;
   /* sentence is constant in this context, so len (sentence) is in
    * fact constant */
   for (i = 0; i < len (sentence); i++)
     if (sentence [i] == ' ') spaces++;
   return len (sentence) > 0 ? spaces + 1 : 0;
}

int main ()
{  char s[] = "This is a sentence. This one is not counted.";

   calls = 0;
   printf ("\"%s\" has %i words\n", &s, cwords (s));
   printf ("%i calls to strlen\n", calls);

   calls = 0;
   /* This counts 8 words with -O, while it should count 4. */
   printf ("\"%s\" has %i words\n", &s, words (s) );
   printf ("%i calls to strlen\n", calls);

   return 0;
}



^ permalink raw reply	[flat|nested] 64+ messages in thread
* Re: forcing tail/sibling call optimization
@ 2000-11-26  8:21 Robert Dewar
  2000-11-26 13:51 ` Fergus Henderson
  0 siblings, 1 reply; 64+ messages in thread
From: Robert Dewar @ 2000-11-26  8:21 UTC (permalink / raw)
  To: bernds, fjh; +Cc: dewar, gcc

>       Implementations shall issue a warning if there are any tail call
>       statements for which the implementation is unable to follow
>       the implementation advice.

Are there precedents in either ANSI C or GNU C for requiring warnings.
I find the requirement dubious, it would require a formal definition
of what a warningf is. This sounds like it should be implementation
advice, not a normative requirement.

^ permalink raw reply	[flat|nested] 64+ messages in thread
* Re: forcing tail/sibling call optimization
@ 2000-11-26  8:14 Robert Dewar
  2000-11-26 13:43 ` Fergus Henderson
  2000-11-27  7:58 ` Jeffrey A Law
  0 siblings, 2 replies; 64+ messages in thread
From: Robert Dewar @ 2000-11-26  8:14 UTC (permalink / raw)
  To: dewar, fjh; +Cc: gcc

The formal definition seems quite reasonable here, but I must say
I dislike the syntax, and it is unnecessarily provocative, since
this really is not semantically a goto at all (e.g. the formal
denmotational semantics would have nothing to do with the semantics
of goto). Why not something like "tail return" or perhaps better 
simply a compiler directive.

The real point here is that the semantics is identical to return. What
the declaration (in whatever form it exists) is doing is to say that
the semanjtics of execution will be undefined if there are any subsequent
references to local variables of the caller. That's *all* that needs to
be said semantically.

In Ada, one would provide this capability by simply having a pragma
e.g. pragma Tail_Return; which has no effect on the semantics of the
program if it is correct.

^ permalink raw reply	[flat|nested] 64+ messages in thread
* Re: forcing tail/sibling call optimization
@ 2000-11-26  5:00 Robert Dewar
  2000-11-26  7:44 ` Fergus Henderson
  0 siblings, 1 reply; 64+ messages in thread
From: Robert Dewar @ 2000-11-26  5:00 UTC (permalink / raw)
  To: fjh, gcc

<<So, any comments?  If I were to provide a clean patch that implements
this feature, together with documentation giving a clear specification,
would you be happy to have this change included in future versions of
GNU C?
>>

How about two steps here. First the clear specification, then the decision
as to whether this extension makes sense (I have trouble seeing what this
clear specification would look like). I think it is very important that
extensions to GNU be very clearly defined.

^ permalink raw reply	[flat|nested] 64+ messages in thread
* forcing tail/sibling call optimization
@ 2000-11-26  3:56 Fergus Henderson
  2000-11-26  5:22 ` Mark Probst
  0 siblings, 1 reply; 64+ messages in thread
From: Fergus Henderson @ 2000-11-26  3:56 UTC (permalink / raw)
  To: gcc

Hi,

I would like to propose an extension to GNU C.  I'm willing to
implement it, but first I'd like to test the waters here to see
the reaction.

The basic idea is to provide a way for the programmer to tell
the C compiler that a particular call should be treated as
a sibling call or tail call, even if the compiler can't prove
that the storage for the locals is no longer live.

For example, for code such as

	extern void bar(int *, int *);
	extern void baz(int);

	void foo(int x) {
		int y;
		bar(&x, &y);
		baz(y);
	}

the compiler won't be able to perform sibling call optimization, since
it can't be sure that bar() doesn't save the addresses of x and y in
some storage that is accessible to baz().  I would like some way to
tell the compiler to go ahead and perform the sibling call
optimization anyway.

This feature is important for compilers of high-level functional and
logic programming languages that target C.  For such languages,
recursion is the primary form of iteration, and it is important that
sibling calls be optimized.  Often the high-level language compiler
has more information about when it is safe to do tail calls than gcc
has, but currently there is no way for the high-level language
compiler to communicate that to gcc.

The language C-- (see <www.cminusminus.org>), which is designed to be
ideal as a target language, provides this feature.  I would like
GNU C to provide it too.

So, any comments?  If I were to provide a clean patch that implements
this feature, together with documentation giving a clear specification,
would you be happy to have this change included in future versions of
GNU C?

I'm not sure what the best syntax for the extension would be.
One possibility is to insert a new keyword `__tailcall' before
such calls:

	void foo(int x) {
		int y;
		bar(&x, &y);
		__tailcall baz(y);
	}

Another alternative is to reuse the `goto' keyword

	void foo(int x) {
		int y;
		bar(&x, &y);
		goto baz(y);
	}

-- 
Fergus Henderson <fjh@cs.mu.oz.au>  |  "I have always known that the pursuit
                                    |  of excellence is a lethal habit"
WWW: < http://www.cs.mu.oz.au/~fjh >  |     -- the last words of T. S. Garp.

^ permalink raw reply	[flat|nested] 64+ messages in thread

end of thread, other threads:[~2002-09-16 16:19 UTC | newest]

Thread overview: 64+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2000-11-26 15:46 forcing tail/sibling call optimization Robert Dewar
2000-11-26 16:21 ` Joseph S. Myers
2000-11-26 18:08 ` Fergus Henderson
2000-11-26 21:50 ` Jeffrey A Law
  -- strict thread matches above, loose matches on Subject: below --
2000-11-29  4:58 Robert Dewar
2000-11-27 15:33 Mike Stump
2000-11-27 10:04 Robert Dewar
2000-11-27  9:39 Geert Bosch
2000-11-27 12:06 ` Jeffrey A Law
2000-11-27  9:08 Robert Dewar
2000-11-27  9:14 ` Bernd Schmidt
2000-11-27 10:09   ` Michael Matz
2000-11-27  8:44 Robert Dewar
2000-11-27  9:44 ` Jeffrey A Law
2000-11-27 10:22   ` Mark Probst
2000-11-27 14:42     ` Harvey J. Stein
2000-11-27 16:07       ` Mark Probst
2000-11-27 14:30   ` Harvey J. Stein
2000-11-26 18:09 Robert Dewar
2000-11-26 15:27 Robert Dewar
2000-11-26 17:56 ` Fergus Henderson
2000-11-26 10:59 Timothy J. Wood
2000-11-26  9:12 Geert Bosch
2000-11-26  8:21 Robert Dewar
2000-11-26 13:51 ` Fergus Henderson
2000-11-26  8:14 Robert Dewar
2000-11-26 13:43 ` Fergus Henderson
2000-11-27  7:58 ` Jeffrey A Law
2000-11-27  8:05   ` David Edelsohn
2000-11-27  8:07   ` Andi Kleen
2000-11-27  8:25     ` Jeffrey A Law
2000-11-27  8:39       ` Andi Kleen
2000-11-27  9:48         ` Jeffrey A Law
2000-11-27 11:21           ` Lars Brinkhoff
2000-11-27 10:54         ` Mark Mitchell
2000-11-27  8:38     ` Bernd Schmidt
2000-11-27 11:26       ` Eric W. Biederman
2000-11-27 10:48     ` Mark Mitchell
2000-11-27 12:46       ` Harvey J. Stein
2000-11-27 13:02         ` Travis Moulton
2000-11-27 10:47   ` Mark Mitchell
2000-11-28 19:21     ` Fergus Henderson
2000-11-29  2:09       ` Mark Mitchell
2000-11-30 23:59         ` Fergus Henderson
2000-12-01 15:51           ` Joe Buck
2001-01-03 12:24             ` Fergus Henderson
2001-01-03 13:09               ` Richard Henderson
2001-01-03 14:59                 ` Fergus Henderson
2001-01-03 15:32                   ` Richard Henderson
2001-01-03 15:53                     ` Fergus Henderson
2001-01-03 16:11                       ` Richard Henderson
2001-01-03 16:36                         ` Fergus Henderson
2002-09-14 23:35                   ` Fergus Henderson
2002-09-16  9:26                     ` Richard Henderson
2000-11-27 23:39   ` Fergus Henderson
2000-11-26  5:00 Robert Dewar
2000-11-26  7:44 ` Fergus Henderson
2000-11-26  8:18   ` Bernd Schmidt
2000-11-26  9:55   ` Andi Kleen
2000-11-26 11:34   ` Per Bothner
2000-11-26 11:55     ` Mark Probst
2000-11-26 17:40     ` Fergus Henderson
2000-11-26  3:56 Fergus Henderson
2000-11-26  5:22 ` Mark Probst

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).