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