This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Functions that are CSEable but not pure
- From: Jason Merrill <jason at redhat dot com>
- To: GCC <gcc at gcc dot gnu dot org>
- Date: Wed, 03 Oct 2012 15:00:15 -0400
- Subject: Functions that are CSEable but not pure
In C++ there is a common idiom called "initialize on first use". In its
simplest form it looks like
int& lazy_i()
{
static int i = init;
return i;
}
If the initialization is expensive or order-sensitive, this is a useful
alternative to initialization on load
(http://www.parashift.com/c++-faq/static-init-order-on-first-use.html).
An interesting property of such functions is that they only have
side-effects the first time they are called, so subsequent calls can be
optimized away to just use the return value of the first call.
Currently there is no way to express this in GCC so that the optimizers
know that multiple calls are redundant. Marking the function as pure
causes calls to be CSEd as desired, but also asserts that the first call
has no side-effects, which is not the case.
My implementation of dynamic initialization of TLS variables as mandated
by the C++11 and OpenMP standards uses this idiom implicitly, so I'd
really like to be able to optimize away multiple calls.
Right now we have the following ECF flags (among others):
const = no read, no write, no side-effects, cseable
pure = no write, no side-effects, cseable
novops = no read, no write
looping_const_or_pure = wait, actually there are side-effects
Seems like the difference between novops and looping_const_or_pure is
whether calls are subject to CSE. Is that right?
Rather than checking these flag bundles, it seems to me that we ought to
break them up into
no reads
no writes
no side-effects
cseable side-effects
So const would be noread|nowrite|noside
pure would be nowrite|noside
const|looping would be noread|nowrite|cseside
pure|looping would be nowrite|cseside
novops would be noread|nowrite
and the behavior I want would be just cseside.
Does this make sense? Anyone more familiar with this area of the code
want to implement it for me? :}
Jason