aboutsummaryrefslogtreecommitdiff
path: root/gcc/expr.c
diff options
context:
space:
mode:
authorRoger Sayle <roger@nextmovesoftware.com>2021-08-04 14:19:14 +0100
committerRoger Sayle <roger@nextmovesoftware.com>2021-08-04 14:22:51 +0100
commit96146e61cd7aee62c21c2845916ec42152918ab7 (patch)
tree99914e14e7b67d97aa6e4789f3159c9e4ad02058 /gcc/expr.c
parent0d04fe49239d91787850036599164788f1c87785 (diff)
downloadgcc-96146e61cd7aee62c21c2845916ec42152918ab7.zip
gcc-96146e61cd7aee62c21c2845916ec42152918ab7.tar.gz
gcc-96146e61cd7aee62c21c2845916ec42152918ab7.tar.bz2
Fold (X<<C1)^(X<<C2) to a multiplication when possible.
The easiest way to motivate these additions to match.pd is with the following example: unsigned int foo(unsigned char i) { return i | (i<<8) | (i<<16) | (i<<24); } which mainline with -O2 on x86_64 currently generates: foo: movzbl %dil, %edi movl %edi, %eax movl %edi, %edx sall $8, %eax sall $16, %edx orl %edx, %eax orl %edi, %eax sall $24, %edi orl %edi, %eax ret but with this patch now becomes: foo: movzbl %dil, %eax imull $16843009, %eax, %eax ret Interestingly, this transformation is already applied when using addition, allowing synth_mult to select an optimal sequence, but not when using the equivalent bit-wise ior or xor operators. The solution is to use tree_nonzero_bits to check that the potentially non-zero bits of each operand don't overlap, which ensures that BIT_IOR_EXPR and BIT_XOR_EXPR produce the same results as PLUS_EXPR, which effectively generalizes the old fold_plusminus_mult_expr. Technically, the transformation is to canonicalize (X*C1)|(X*C2) and (X*C1)^(X*C2) to X*(C1+C2) where X and X<<C are considered special cases. 2021-08-04 Roger Sayle <roger@nextmovesoftware.com> Marc Glisse <marc.glisse@inria.fr> gcc/ChangeLog * match.pd (bit_ior, bit_xor): Canonicalize (X*C1)|(X*C2) and (X*C1)^(X*C2) as X*(C1+C2), and related variants, using tree_nonzero_bits to ensure that operands are bit-wise disjoint. gcc/testsuite/ChangeLog * gcc.dg/fold-ior-4.c: New test.
Diffstat (limited to 'gcc/expr.c')
0 files changed, 0 insertions, 0 deletions