public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* RE: pure and const functions
@ 2002-04-26 10:17 Chris Lattner
  2002-04-26 10:21 ` Kris Warkentin
                   ` (2 more replies)
  0 siblings, 3 replies; 33+ messages in thread
From: Chris Lattner @ 2002-04-26 10:17 UTC (permalink / raw)
  To: gcc


> int fib(int n) {
>   if (n==0 || n==1) return n;
>   return fib(n-1) + fib(n-2);
> }

> According to the definitions given above, this function is const,
> but not total, because it does not return for negative n.

While this is true in a practical sense, given infinite resources, this is
certainly not the case.  Assuming you had a whole lot of stack space and
bunch of time, the negative values for 'n' would wrap around to positive
values.  Eventually it would get to 1 and terminate.

As this is the case, for this example...

int double_or_nothing (int n) {
  fib(n);
  return 2*n;
}

... it should be optimizable to:

int double_or_nothing (int n) {
  return 2*n;
}

...because on an ideal, theoretical, machine, they results are exactly the
same.

IOW: we don't try to predict stack overflow in other cases, so why should
     we have to worry about that possibility here?

There may be other cases where functions are "partial", can you give
another example?

-Chris

http://www.nondot.org/~sabre/os/
http://www.nondot.org/~sabre/Projects/

^ permalink raw reply	[flat|nested] 33+ messages in thread
* Re: pure and const functions
@ 2002-04-29 17:25 John Wehle
  0 siblings, 0 replies; 33+ messages in thread
From: John Wehle @ 2002-04-29 17:25 UTC (permalink / raw)
  To: mdetting; +Cc: gcc

> Does the latest GCC really already try to prove functions as pure?

Current mainline.

> int square (int n) {
>   int i,j,result;
> 
>   result = 0;
>   for (i=0; i<n; i++)
>     for (j=0; j<n; j++)
>       result++;
>   return result;
> }

Loops are not currently handled.  There is a pending
patch to handle loops with known iteration counts:

  http://gcc.gnu.org/ml/gcc-patches/2002-03/msg01612.html

-- John
-------------------------------------------------------------------------
|   Feith Systems  |   Voice: 1-215-646-8000  |  Email: john@feith.com  |
|    John Wehle    |     Fax: 1-215-540-5495  |                         |
-------------------------------------------------------------------------

^ permalink raw reply	[flat|nested] 33+ messages in thread
* Re: pure and const functions
@ 2002-04-29  9:29 Robert Dewar
  2002-04-29  9:34 ` Chris Lattner
  0 siblings, 1 reply; 33+ messages in thread
From: Robert Dewar @ 2002-04-29  9:29 UTC (permalink / raw)
  To: dewar, sabre; +Cc: gcc

> I don't really agree with this.  If the compiler can determine that it's
> pure, the programmer shouldn't have to provide the annotation.  Instead
> (at least for the C/C++ frontends), I propose that we trust the programmer
> to not do something dumb (scary I know...).  These languages are built
> around the notion that the programmer knows what they are doing, I don't
> see how it would be any different here...

In order for the programmer to "know what they are doing", you have to do
one of two things:

1. Define what pure means semantically

or

2. Define what the functional effect of declarting something pure is

I actually think you *do* agree with me. What I said was that it was in
practice impractical for the compiler to check that you are doing the
right thing when you declare a function pure (though obvious problems
might be detectable and cause appropriate warnings).

As an example of a fuction that is unlikely to obey any set of semantic
rules but in practice can be treated as pure, consider a sqrt function
which is instrumented to count the number of times it is called. This
is obviously not pure in the semantic sense, but operationally it may
make perfect sense to treat it as pure.

^ permalink raw reply	[flat|nested] 33+ messages in thread
* Re: pure and const functions
@ 2002-04-29  8:30 Robert Dewar
  2002-04-29  8:57 ` Chris Lattner
  0 siblings, 1 reply; 33+ messages in thread
From: Robert Dewar @ 2002-04-29  8:30 UTC (permalink / raw)
  To: gcc, sabre; +Cc: dewar, mdetting

> 
> This seems nice and simple, but #2 confuses things.  As I understand it,
> GCC automatically trys to prove functions pure.  Obviously it will not be
> able to figure out the structure of a memoizing function in general, so it
> would punt on these functions, thus not automatically marking it pure.
> 
> The programmer, however, can manually add the pure attribute, so the
> actual _notion_ of being pure is still intact, even if the actual
> implementation isn't "smart enough" (and there isn't really any reasonable
> way to make it so).

Given that a programmer can mark things as pure, you need to decide

1. If the compiler can check that this designation is correct. The answer
is pretty clearly no.

2. What exactly is the criterion for "correct" designation of Pure (in
Ada by the way this is the Pure_Function pragma).

Yes, the compiler can try to prove some functions pure, but it will always
end up being too conservative, which is fine.

^ permalink raw reply	[flat|nested] 33+ messages in thread
* Re: pure and const functions
@ 2002-04-29  8:30 Chris Lattner
  2002-04-29  9:23 ` Daniel Berlin
  0 siblings, 1 reply; 33+ messages in thread
From: Chris Lattner @ 2002-04-29  8:30 UTC (permalink / raw)
  To: gcc; +Cc: mdetting, dewar


>>   a) having no effects except the return value
>>   b) return value depends only on the parameters
>>   c) return value depends on global variables
>>
>> Condition a) is too strong for removal of duplicate calls, since it
>> eliminates considering memo functions as pure.

> Yes, but I think that's okay. There are cases where duplicate calls
> to a non-pure memoizing function could be removed too, but how should
> the compiler determine which side-effects can be ignored?
> All we say is that if condition a) is fulfilled, we are on the safe
> side.

There are two different issues going on here confusing things:

1. The defined semantics
2. What we actually do

For #1, Robert is correct...
>   a) having no effects except the return value

Is too strong of a statement... the problem is that it's really hard to
make an accurate summary of what things really are.  Perhaps "Always
returns the same value for a particular set of input parameters" coupled
with "makes no changes to global state that would break the program if
they didn't happen" is close enough.  Effectively we just need to get
across the idea that a pure function _can_ be eliminated, and doing so
should not affect the semantics of the program.

This seems nice and simple, but #2 confuses things.  As I understand it,
GCC automatically trys to prove functions pure.  Obviously it will not be
able to figure out the structure of a memoizing function in general, so it
would punt on these functions, thus not automatically marking it pure.

The programmer, however, can manually add the pure attribute, so the
actual _notion_ of being pure is still intact, even if the actual
implementation isn't "smart enough" (and there isn't really any reasonable
way to make it so).

-Chris

http://www.nondot.org/~sabre/os/
http://www.nondot.org/~sabre/Projects/

^ permalink raw reply	[flat|nested] 33+ messages in thread
* Re: pure and const functions
@ 2002-04-29  5:18 Robert Dewar
  2002-04-29  5:44 ` Mark Dettinger
  0 siblings, 1 reply; 33+ messages in thread
From: Robert Dewar @ 2002-04-29  5:18 UTC (permalink / raw)
  To: gcc, mdetting

> > `pure'
> >      Many functions have no effects except the return value and their
> >      return value depends only on the parameters and/or global
> >      variables. 


This is a bit of a confused definition

  a) having no effects except the return value
  b) return value depends only on the parameters
  c) return value depends on global variables

Condition a) is too strong for removal of duplicate calls, since it 
eliminates considering memo functions as pure.

Conditions b) and c) are quite different from an optimization point of view.

In GNAT we define a pure function as one for which it is permissible to
optimize away multiple calls with provably identical parameter calls.

^ permalink raw reply	[flat|nested] 33+ messages in thread
* Re: pure and const functions
@ 2002-04-29  3:59 Mark Dettinger
  0 siblings, 0 replies; 33+ messages in thread
From: Mark Dettinger @ 2002-04-29  3:59 UTC (permalink / raw)
  To: gcc

Sorry for causing unneccessary confusion - the definition of "pure" 
in my original posting was wrong. The definition in the gcc manual

> `pure'
>      Many functions have no effects except the return value and their
>      return value depends only on the parameters and/or global
>      variables. 

is good. The whole point, as Chris Lattner pointed out, is to make
optimizations like foo()+foo() ---> 2*foo() possible. (Currently,
GCC is not very good here.)

Such a common subexpression elimination does not require foo() 
to terminate for all inputs and in all contexts. For this reason, 
I think that termination issues should be kept out of the definition 
of "pure". 
If we require a "pure" function to always terminate - as some people 
have advocated - we 

(1) get a stricter kind of "pure" that is better for dead code
    elimination, but worse for CSE elimination.

(2) make it much harder for the compiler to automatically recognize
    a "pure" function

It's still a good idea to add detection code that determines 
whether a function is total, i.e. always terminates.
We just should not MIX this with the definition of pure. 
Treating the issues separately yields better results.

foo is pure           --> foo()+foo() can be optimized to 2*foo()
foo is pure and total --> foo();      can be optimized to ;


-Mark Dettinger


__________________________________________________
Do You Yahoo!?
Yahoo! Health - your guide to health and wellness
http://health.yahoo.com

^ permalink raw reply	[flat|nested] 33+ messages in thread
* pure and const functions
@ 2002-04-26  5:16 Mark Dettinger
  2002-04-26 11:20 ` Joseph S. Myers
  2002-04-26 12:59 ` Jakub Jelinek
  0 siblings, 2 replies; 33+ messages in thread
From: Mark Dettinger @ 2002-04-26  5:16 UTC (permalink / raw)
  To: gcc

A month ago, there was a discussion whether a pure or const function
should be required to terminate for all inputs and in all contexts.
=> http://gcc.gnu.org/ml/gcc-patches/2002-03/msg01477.html

Since for some code optimizations the termination requirement is important, 
but for other optimizations it is irrelevant, I propose that we should
keep termination issues out of the definition of const and pure. Instead, 
I would rather add the concept of total and partial functions. 
So, I suggest to go with the following attribute definitions:

A function is "pure", if it only examines its arguments, i.e. does not
read global memory and does not take input from any device. In other 
words, if its behavior does not depend on the context.

A function is "const", if - in addition to being pure - it does not have a 
side effect besides returning a value, i.e. it does not modify global memory 
and does not write to a file, to the screen, or to any other device.

A function is "total", if it returns in all cases, i.e. for all inputs
and (for non-pure functions) in all contexts. 

A function is "partial", if it may or may not return. 

A function has the "noreturn" attribute, if it never returns.


If the new concepts "total" and "partial" sound unneccessary to you,
please consider this example:

int fib(int n) {
  if (n==0 || n==1) return n;
  return fib(n-1) + fib(n-2);
}

According to the definitions given above, this function is const, 
but not total, because it does not return for negative n.
This has different implications for different optimizations:

Dead Code Elimination:
----------------------

int double_or_nothing (int n) {
  fib(n);
  return 2*n;
}
  
Since fib is not total, the compiler cannot delete the call fib(n) here, 
although the return value is not used:
If we delete the call, then double_or_nothing always returns, 
while the unoptimized function does not return for negative n. 

Common Subexpression Elimination:
---------------------------------

int fib_cube (int n) {
  return fib(n) * fib(n) * fib(n);
}

Here it does not matter whether fib is total or not. If the first call
returns, the second and third call will return too, since fib is a const
function. So, the compiler can (and should!) optimize this to

int fib_cube (int n) {
  int cse = fib(n);
  return cse * cse * cse;
}

So DCE requires const + total, CSE only requires const here. This is
the reason why I wouldn't add the termination requirement to const,
but rather add a total attribute.

Attributes versus Automatic Detection
-------------------------------------

In my opinion, the compiler should definitely try to determine the
function attributes by code analysis. In many cases, it is possible
to determine automatically whether a function is pure, const or total.
In the fib function, for example, it's easy for the compiler to see 
that the function is const. We definitely need good automatic analyses.
Attributes provided by the programmer should be just for the cases 
that the compiler cannot solve alone.

Finally, here's how I think a good compiler should behave when conflicts 
between user-given attributes and automatically detected attributes occur:

1. If an attribute is present and is clearly wrong, an error should be thrown.
2. If an attribute is present and might be wrong, a warning should be given.
3. If an attribute is missing, but maybe should be there, a suggestion to add 
   the missing attribute should be made.
4. If an attribute is missing, but clearly should be there, the compiler
   should just add the attribute and continue and not bother the programmer.

1 and 4 should be always active. 2 and 3 should be optional.
 
What do you think?

-Mark Dettinger


__________________________________________________
Do You Yahoo!?
Yahoo! Games - play chess, backgammon, pool and more
http://games.yahoo.com/

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

end of thread, other threads:[~2002-08-30 23:02 UTC | newest]

Thread overview: 33+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-04-26 10:17 pure and const functions Chris Lattner
2002-04-26 10:21 ` Kris Warkentin
2002-04-26 10:30   ` Chris Lattner
2002-04-26 10:34     ` Magnus Fromreide
2002-04-26 10:35       ` Chris Lattner
2002-04-26 10:59         ` Magnus Fromreide
2002-04-26 11:03           ` Chris Lattner
2002-04-26 11:27             ` Magnus Fromreide
2002-04-26 12:49           ` Russ Allbery
2002-04-26 10:36     ` Kris Warkentin
2002-04-26 10:46       ` Chris Lattner
2002-04-26 10:26 ` Tim Hollebeek
2002-04-26 10:30   ` Chris Lattner
2002-04-26 10:56     ` Tony Finch
2002-04-26 10:56     ` Zack Weinberg
2002-04-26 11:01       ` Chris Lattner
2002-08-30 23:02         ` Zack Weinberg
2002-04-26 12:11 ` Mark Mitchell
  -- strict thread matches above, loose matches on Subject: below --
2002-04-29 17:25 John Wehle
2002-04-29  9:29 Robert Dewar
2002-04-29  9:34 ` Chris Lattner
2002-04-29  8:30 Robert Dewar
2002-04-29  8:57 ` Chris Lattner
2002-04-29  8:30 Chris Lattner
2002-04-29  9:23 ` Daniel Berlin
2002-04-29  9:52   ` Chris Lattner
2002-04-29  9:58   ` Mark Dettinger
2002-04-29  5:18 Robert Dewar
2002-04-29  5:44 ` Mark Dettinger
2002-04-29  3:59 Mark Dettinger
2002-04-26  5:16 Mark Dettinger
2002-04-26 11:20 ` Joseph S. Myers
2002-04-26 12:59 ` Jakub Jelinek

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