From: Roger Sayle Date: Tue, 16 Jul 2024 06:58:28 +0000 (+0100) Subject: PR tree-optimization/114661: Generalize MULT_EXPR recognition in match.pd. X-Git-Tag: basepoints/gcc-16~7500 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=df9451936c6c9e4faea371e3f188e1fc6b6d39e3;p=thirdparty%2Fgcc.git PR tree-optimization/114661: Generalize MULT_EXPR recognition in match.pd. This patch resolves PR tree-optimization/114661, by generalizing the set of expressions that we canonicalize to multiplication. This extends the optimization(s) contributed (by me) back in July 2021. https://gcc.gnu.org/pipermail/gcc-patches/2021-July/575999.html The existing transformation folds (X*C1)^(X< 3) __builtin_unreachable(); return c << 18 | c << 15 | c << 12 | c << 9 | c << 6 | c << 3 | c; } GCC on x86_64 with -O2 previously generated: mul: movzbl %dil, %edi leal (%rdi,%rdi,8), %edx leal 0(,%rdx,8), %eax movl %edx, %ecx sall $15, %edx orl %edi, %eax sall $9, %ecx orl %ecx, %eax orl %edx, %eax ret with this patch we now generate: mul: movzbl %dil, %eax imull $299593, %eax, %eax ret 2024-07-16 Roger Sayle Richard Biener gcc/ChangeLog PR tree-optimization/114661 * match.pd ((X*C1)|(X*C2) to X*(C1+C2)): Allow optional useless type conversions around multiplications, such as those inserted by this transformation. gcc/testsuite/ChangeLog PR tree-optimization/114661 * gcc.dg/pr114661.c: New test case. --- diff --git a/gcc/match.pd b/gcc/match.pd index 3759c64d461..24a0bbead3e 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -4171,30 +4171,39 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) Likewise, handle (X< 0 - && (tree_nonzero_bits (@0) & tree_nonzero_bits (@3)) == 0) - (with { wide_int wone = wi::one (TYPE_PRECISION (type)); + && (tree_nonzero_bits (@5) & tree_nonzero_bits (@3)) == 0) + (with { tree t = type; + if (!TYPE_OVERFLOW_WRAPS (t)) + t = unsigned_type_for (t); + wide_int wone = wi::one (TYPE_PRECISION (type)); wide_int c = wi::add (wi::to_wide (@2), wi::lshift (wone, wi::to_wide (@4))); } - (mult @1 { wide_int_to_tree (type, c); })))) + (convert (mult:t (convert:t @1) { wide_int_to_tree (t, c); }))))) (simplify - (op:c (mult:s@0 @1 INTEGER_CST@2) + (op:c (nop_convert?:s@3 (mult:s@0 (nop_convert? @1) INTEGER_CST@2)) @1) - (if (INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_WRAPS (type) - && (tree_nonzero_bits (@0) & tree_nonzero_bits (@1)) == 0) - (mult @1 - { wide_int_to_tree (type, - wi::add (wi::to_wide (@2), 1)); }))) + (if (INTEGRAL_TYPE_P (type) + && (tree_nonzero_bits (@3) & tree_nonzero_bits (@1)) == 0) + (with { tree t = type; + if (!TYPE_OVERFLOW_WRAPS (t)) + t = unsigned_type_for (t); + wide_int c = wi::add (wi::to_wide (@2), 1); } + (convert (mult:t (convert:t @1) { wide_int_to_tree (t, c); }))))) (simplify (op (lshift:s@0 @1 INTEGER_CST@2) (lshift:s@3 @1 INTEGER_CST@4)) diff --git a/gcc/testsuite/gcc.dg/pr114661.c b/gcc/testsuite/gcc.dg/pr114661.c new file mode 100644 index 00000000000..e6b5c69dba8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr114661.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-evrp" } */ + +unsigned mul(unsigned char c) { + if (c > 3) __builtin_unreachable(); + return c << 18 | c << 15 | + c << 12 | c << 9 | + c << 6 | c << 3 | c; +} +/* { dg-final { scan-tree-dump-times " \\* 299593" 1 "evrp" } } */