On Tue, Mar 10, 2020 at 06:10:27PM -0700, Andrew Morton wrote: > On Tue, 10 Mar 2020 11:56:09 -0700 Matthew Wilcox <willy@xxxxxxxxxxxxx> wrote: > > > From: "Matthew Wilcox (Oracle)" <willy@xxxxxxxxxxxxx> > > > > PageType is a little hard for GCC to reason about, By checking > > ((~A) & flag) instead of (flag & (A | MASK) == MASK), GCC can do > > better optimisations, saving 652 bytes in page_alloc.o (which is > > a heavy user of PageBuddy). > > > > ... > > > > --- a/include/linux/page-flags.h > > +++ b/include/linux/page-flags.h > > @@ -725,14 +725,14 @@ PAGEFLAG_FALSE(DoubleMap) > > #define PG_table 0x00000400 > > #define PG_guard 0x00000800 > > > > -#define PageType(page, flag) \ > > - ((page->page_type & (PAGE_TYPE_BASE | flag)) == PAGE_TYPE_BASE) > > - > > static inline int page_has_type(struct page *page) > > { > > return (int)page->page_type < PAGE_MAPCOUNT_RESERVE; > > } > > > > +#define PageType(page, flag) \ > > + (page_has_type(page) && (~page->page_type & flag)) > > + > > `flag' should be parenthesized here. As should `page' if one is even > more paranoid. I suppose so. The thing is, the flag name isn't specified by the user; users say 'if (PageBuddy(page))' and the flag gets expanded through PAGE_TYPE_OPS. We also don't need to worry about the user doing 'if (PageBuddy(page++))' as it'll expand into a call to static __always_inline int PageBuddy(struct page *page) { return PageType(page, PG_buddy) } > I tried this: > > --- a/include/linux/page-flags.h~mm-make-pagetype-more-efficient-fix > +++ a/include/linux/page-flags.h > @@ -731,7 +731,7 @@ static inline int page_has_type(struct p > } > > #define PageType(page, flag) \ > - (page_has_type(page) && (~page->page_type & flag)) > + (page_has_type(page) && !(page->page_type & ~(flag))) Mr Boole would like to let you know you misapplied his rules of algebra. ~flag is going to expand into 0xfffffff7f and then gcc will figure out the expression as a whole is always false, and so no page is ever a buddy page, and .. > and page_alloc.o shrunk by 6782 bytes, half of it in > get_page_from_freelist(). Something crazy is going on. gcc-7.2.0.