Functions that are CSEable but not pure
Jason Merrill
jason@redhat.com
Thu Oct 4 15:22:00 GMT 2012
On 10/04/2012 09:07 AM, Richard Guenther wrote:
> Ugh. Especially with the above (you can DCE those calls) makes this
> severly mis-specified ... and any implementation error-prone (look what
> mess our losely defined 'malloc' attribute opened ...).
>
> I thought of a testcase like
>
> int *p = get_me ();
> .. = *p;
> int *q = get_me ();
> .. = *q;
>
> and get_me allocating/initalizing and returning a singleton.
Right.
> But you tell me it's more complicated and get_me () needs to
> be a barrier for any load/store (as it may modify arbitrary memory,
> but only on the "first" call).
Yes, because the initialization is user-written code.
> I think that "may modify arbitrary memory" isn't going to fly and
> my answer would be, better don't try to optimize anything here,
> at least not in generic terms. How would you handle this in
> the alias oracle? How would you then make CSE recognize
> two functions return the same value and are CSEable?
For aliasing purposes, the call is like a call to a normal function.
For CSE purposes, we want to recognize identical calls and combine them.
I don't know the GCC bits well enough to be any more specific.
> Can you come up with a short but complete testcase illustrating the issue
> better (preferably C, so I don't need to read-in magic points where construction
> happens)?
int init_count;
int data;
void init()
{
static int initialized;
if (!initialized)
{
data = ++init_count;
initialized = 1;
}
}
inline int *get_me() __attribute ((pure));
inline int *get_me()
{
init ();
return &data;
}
int sink;
int main()
{
sink = init_count;
int *p = get_me();
if (init_count != 1)
__builtin_abort();
int *q = get_me();
if (init_count != 1)
__builtin_abort();
return *p + *q;
}
On this testcase, gcc -O2 doesn't reload init_count after the call to
get_me because it thinks that the call can't have modified init_count.
I want the compiler to know that it is safe to discard the redundant
assignment, but not make assumptions about memory.
On 10/04/2012 08:59 AM, Jakub Jelinek wrote:> On Thu, Oct 04, 2012 at
08:56:03AM -0400, Jason Merrill wrote:
> Sure, but I thought you want to inline the wrapper function as soon as
> possible. Or do you want to keep it as some kind of builtin that gets
> expanded during expansion to the test and call?
Ah, I see your point; if get_me is inlined we end up with two calls to
init, so it would be good to mark init with the same hypothetical attribute.
Jason
More information about the Gcc
mailing list