Bug 96237 - Failure to recognize and pattern composed of and+or after shift
Summary: Failure to recognize and pattern composed of and+or after shift
Status: ASSIGNED
Alias: None
Product: gcc
Classification: Unclassified
Component: tree-optimization (show other bugs)
Version: 11.0
: P3 enhancement
Target Milestone: ---
Assignee: Andrew Pinski
URL:
Keywords: missed-optimization
Depends on:
Blocks: 19987
  Show dependency treegraph
 
Reported: 2020-07-17 21:16 UTC by Gabriel Ravier
Modified: 2021-08-15 22:58 UTC (History)
0 users

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2020-07-19 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Gabriel Ravier 2020-07-17 21:16:35 UTC
unsigned char f(unsigned char x)
{
    auto a = (x >> 3) & 1;
    if (x & 16)
        a |= 2;
    if (x & 32)
        a |= 4;
    return a;
}

This can be optimized to `return (x >> 3) & 7;`. This transformation is done by LLVM, but not by GCC.
Comment 1 Andrew Pinski 2020-07-19 22:53:42 UTC
if (x & 16)
        a |= 2;

Maybe should be transformed into:
a |= ((x >> 4) & 0x1) << 1;
Which in turn should be transformed into:
a |= ((x & 0x10) >> 3);


    if (x & 32)
        a |= 4;
gets transformed into:
a |= ((x & 0x20) >> 3);

And:
a |= ((x & 0x40) >> 3);
a |= ((x & 0x20) >> 3);
Into:
a |= ((x & 0x60) >> 3);
Or:
a |= ((x >> 3) & 0x6);

Combine that with:
a = (x >> 3) & 1;
gets us:
a |= ((x >> 3) & 0x7);

Hopefully I did that correctly.
Comment 2 Andrew Pinski 2021-07-17 02:38:52 UTC
I am going to implement the match patterns needed.

Something like:
(for bitop (bit_and bit_ior)
 (simplify
  (cond @0 (bitop @1 integer_power2@2) @1)
  (bitop @1 (lshift @0 ({ log2(@2); }) ))))

Note log2 here is just psedu-code :).