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

Reply via email to