https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83653
Aldy Hernandez <aldyh at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
Status|UNCONFIRMED |WAITING
Last reconfirmed| |2018-01-11
CC| |aldyh at gcc dot gnu.org
Ever confirmed|0 |1
--- Comment #4 from Aldy Hernandez <aldyh at gcc dot gnu.org> ---
I can reproduce this on mainline, however the testcase is suspect.
I see that page_ref_sub() is defined as:
int __ia64_asr_i = ((nr))
...
if (__ia64_asr_i == xxx)
else if (__ia64_asr_i == yyy)
else if (__ia64_asr_i == yyy)
etc
else _tmp = __bad_increment_for_ia64_fetch_and_add();
The thing I see is that NR doesn't seem like an inlineable constant when passed
from the caller:
nr = 1UL << compound_order(page)
...
page_ref_sub(page, nr)
because:
unsigned int compound_order(struct page *page)
{
if (!PageHead(page))
return 0;
return page[1].compound_order;
}
And sure enough...after early inlining, both compound_order and page_ref_sub
are inlined into shmem_add_to_page_cache and we can see:
_117 = MEM[(struct page *)page_49(D) + 56B].D.16951.D.16950.compound_order;
There's no way the compiler can know that _117 is a known constant if it's
reading the value from memory.
OTOH, the other *_bad* thinggies do get inlined correctly because they depend
on sizeof(stuff), whose size can be determined at compile time.
Matthew, could you double check here? Maybe I missed something, but perhaps a
reduced testcase would help analyze better (at least for me :)).