From 49e8c14ef6f1f968602a04c8499a672182590e87 Mon Sep 17 00:00:00 2001 From: Eugene Rozenfeld Date: Wed, 9 Dec 2020 16:44:25 -0800 Subject: [PATCH] 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. --- gcc/match.pd | 14 ++++++++++++ gcc/testsuite/gcc.dg/pr96674.c | 40 ++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 gcc/testsuite/gcc.dg/pr96674.c 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" } } */ -- 2.30.2