PR middle-end/98865: Expand X*Y as X&-Y when Y is [0,1].
authorRoger Sayle <roger@nextmovesoftware.com>
Thu, 19 May 2022 16:54:38 +0000 (17:54 +0100)
committerRoger Sayle <roger@nextmovesoftware.com>
Thu, 19 May 2022 16:54:38 +0000 (17:54 +0100)
commitd863ba23fb16122bb0547b0c678173be0d98f43c
treef8e5d507bac668e8cb40e94aae74975aef76a675
parentcd427e17c00f2a5a6b97f370c9a25a6e6a9af143
PR middle-end/98865: Expand X*Y as X&-Y when Y is [0,1].

The patch is a revised solution for PR middle-end/98865 incorporating
the feedback/suggestions from Richard Biener's review here:
https://gcc.gnu.org/pipermail/gcc-patches/2022-May/593928.html
Most significantly, this patch now performs the transformation/optimization
during RTL expansion, where the target's rtx_costs can be used to determine
whether the original multiplication (that may potentially be implemented by
a shift or lea) is cheaper than a negation and a bit-wise and.

Previously the expression (x>>63)*y would be compiled with -O2 as
        shrq    $63, %rdi
        movq    %rdi, %rax
        imulq   %rsi, %rax

but with this patch now produces:
        sarq    $63, %rdi
        movq    %rdi, %rax
        andq    %rsi, %rax

Likewise the expression (x>>63)*135 [that appears in a hot-spot of the
Botan AES-128 benchmark] was previously:

        shrq    $63, %rdi
        leaq    (%rdi,%rdi,8), %rdx
        movq    %rdx, %rax
        salq    $4, %rax
        subq    %rdx, %rax

now becomes:
        movq    %rdi, %rax
        sarq    $63, %rax
        andl    $135, %eax

2022-05-19  Roger Sayle  <roger@nextmovesoftware.com>

gcc/ChangeLog
PR middle-end/98865
* expr.cc (expand_expr_real_2) [MULT_EXPR]:  Expand X*Y as X&Y
when both X and Y are [0, 1], X*Y as X&-Y when Y is [0,1] and
likewise X*Y as -X&Y when X is [0,1] using tree_nonzero_bits.

gcc/testsuite/ChangeLog
PR middle-end/98865
* gcc.target/i386/pr98865.c: New test case.
gcc/expr.cc
gcc/testsuite/gcc.target/i386/pr98865.c [new file with mode: 0644]