From: Eugene Rozenfeld Date: Thu, 10 Dec 2020 00:44:25 +0000 (-0800) Subject: Optimize combination of comparisons to dec+compare X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=49e8c14ef6f1f968602a04c8499a672182590e87;p=gcc.git Optimize combination of comparisons to dec+compare This patch adds patterns for optimizing x < y || y == XXX_MIN to x <= y-1 x >= y && y != XXX_MIN to x > y-1 if y is an integer with TYPE_OVERFLOW_WRAPS. This fixes pr96674. Tested on x86_64-pc-linux-gnu. For this function bool f(unsigned a, unsigned b) { return (b == 0) | (a < b); } the code without the patch is test esi,esi sete al cmp esi,edi seta dl or eax,edx ret the code with the patch is sub esi,0x1 cmp esi,edi setae al ret PR tree-optimization/96674 gcc/ * match.pd: New patterns: x < y || y == XXX_MIN --> x <= y - 1 x >= y && y != XXX_MIN --> x > y - 1 gcc/testsuite * gcc.dg/pr96674.c: New tests. --- diff --git a/gcc/match.pd b/gcc/match.pd index 7158e983d21..05e7ba9a333 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -2159,6 +2159,20 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (if (eqne == NE_EXPR) { constant_boolean_node (true, type); })))) +/* y == XXX_MIN || x < y --> x <= y - 1 */ +(simplify + (bit_ior:c (eq:s @1 min_value) (lt:s @0 @1)) + (if (INTEGRAL_TYPE_P (TREE_TYPE (@1)) + && TYPE_OVERFLOW_WRAPS (TREE_TYPE (@1))) + (le @0 (minus @1 { build_int_cst (TREE_TYPE (@1), 1); })))) + +/* y != XXX_MIN && x >= y --> x > y - 1 */ +(simplify + (bit_and:c (ne:s @1 min_value) (ge:s @0 @1)) + (if (INTEGRAL_TYPE_P (TREE_TYPE (@1)) + && TYPE_OVERFLOW_WRAPS (TREE_TYPE (@1))) + (gt @0 (minus @1 { build_int_cst (TREE_TYPE (@1), 1); })))) + /* Convert (X == CST1) && (X OP2 CST2) to a known value based on CST1 OP2 CST2. Similarly for (X != CST1). */ diff --git a/gcc/testsuite/gcc.dg/pr96674.c b/gcc/testsuite/gcc.dg/pr96674.c new file mode 100644 index 00000000000..194ce2e6352 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr96674.c @@ -0,0 +1,40 @@ +/* { dg-do run } */ +/* { dg-options "-O -fdump-tree-optimized -fwrapv" } */ + +#include +#include + +bool __attribute__ ((noipa)) test1 (unsigned a, unsigned b) +{ + return (b == 0) | (a < b); +} + +bool __attribute__ ((noipa)) test2 (int a, int b) +{ + return (b == INT_MIN) | (a < b); +} + +bool __attribute__ ((noipa)) test3 (unsigned a, unsigned b) +{ + return (b != 0) & (a >= b); +} + +bool __attribute__ ((noipa)) test4 (int a, int b) +{ + return (b != INT_MIN) & (a >= b); +} + +int main() +{ + if (!test1 (1, 0) || !test1 (1, 2) || test1 (2, 1) || + !test2 (1, INT_MIN) || !test2 (1, 2) || test2 (2, 1) || + test3 (1, 0) || test3 (1, 2) || !test3 (2, 1) || + test4 (1, INT_MIN) || test4 (1, 2) || !test4 (2, 1)) { + __builtin_abort(); + } + + return 0; +} + +/* { dg-final { scan-tree-dump-times "\\+ 4294967295;" 2 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "\\+ -1;" 2 "optimized" } } */