From c16504f6eabad7e173e4fbcfacf52820fffcb9ec Mon Sep 17 00:00:00 2001 From: Li Jia He Date: Mon, 16 Sep 2019 14:22:16 +0000 Subject: [PATCH] Fix PR88784, middle end is missing some optimizations about unsigned 2019-09-16 Li Jia He Qi Feng PR middle-end/88784 * match.pd (x > y && x != XXX_MIN): Optimize into 'x > y'. (x > y && x == XXX_MIN): Optimize into 'false'. (x <= y && x == XXX_MIN): Optimize into 'x == XXX_MIN'. (x < y && x != XXX_MAX): Optimize into 'x < y'. (x < y && x == XXX_MAX): Optimize into 'false'. (x >= y && x == XXX_MAX): Optimize into 'x == XXX_MAX'. (x > y || x != XXX_MIN): Optimize into 'x != XXX_MIN'. (x <= y || x != XXX_MIN): Optimize into 'true'. (x <= y || x == XXX_MIN): Optimize into 'x <= y'. (x < y || x != XXX_MAX): Optimize into 'x != XXX_MAX'. (x >= y || x != XXX_MAX): Optimize into 'true'. (x >= y || x == XXX_MAX): Optimize into 'x >= y'. 2019-09-16 Li Jia He Qi Feng PR middle-end/88784 * gcc.dg/pr88784-1.c: New testcase. * gcc.dg/pr88784-2.c: New testcase. * gcc.dg/pr88784-3.c: New testcase. * gcc.dg/pr88784-4.c: New testcase. * gcc.dg/pr88784-5.c: New testcase. * gcc.dg/pr88784-6.c: New testcase. * gcc.dg/pr88784-7.c: New testcase. * gcc.dg/pr88784-8.c: New testcase. * gcc.dg/pr88784-9.c: New testcase. * gcc.dg/pr88784-10.c: New testcase. * gcc.dg/pr88784-11.c: New testcase. * gcc.dg/pr88784-12.c: New testcase. Co-Authored-By: Qi Feng From-SVN: r275749 --- gcc/ChangeLog | 17 +++++++ gcc/match.pd | 82 +++++++++++++++++++++++++++++-- gcc/testsuite/ChangeLog | 17 +++++++ gcc/testsuite/gcc.dg/pr88784-1.c | 30 +++++++++++ gcc/testsuite/gcc.dg/pr88784-10.c | 32 ++++++++++++ gcc/testsuite/gcc.dg/pr88784-11.c | 30 +++++++++++ gcc/testsuite/gcc.dg/pr88784-12.c | 30 +++++++++++ gcc/testsuite/gcc.dg/pr88784-2.c | 30 +++++++++++ gcc/testsuite/gcc.dg/pr88784-3.c | 32 ++++++++++++ gcc/testsuite/gcc.dg/pr88784-4.c | 32 ++++++++++++ gcc/testsuite/gcc.dg/pr88784-5.c | 31 ++++++++++++ gcc/testsuite/gcc.dg/pr88784-6.c | 31 ++++++++++++ gcc/testsuite/gcc.dg/pr88784-7.c | 31 ++++++++++++ gcc/testsuite/gcc.dg/pr88784-8.c | 31 ++++++++++++ gcc/testsuite/gcc.dg/pr88784-9.c | 32 ++++++++++++ 15 files changed, 484 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/pr88784-1.c create mode 100644 gcc/testsuite/gcc.dg/pr88784-10.c create mode 100644 gcc/testsuite/gcc.dg/pr88784-11.c create mode 100644 gcc/testsuite/gcc.dg/pr88784-12.c create mode 100644 gcc/testsuite/gcc.dg/pr88784-2.c create mode 100644 gcc/testsuite/gcc.dg/pr88784-3.c create mode 100644 gcc/testsuite/gcc.dg/pr88784-4.c create mode 100644 gcc/testsuite/gcc.dg/pr88784-5.c create mode 100644 gcc/testsuite/gcc.dg/pr88784-6.c create mode 100644 gcc/testsuite/gcc.dg/pr88784-7.c create mode 100644 gcc/testsuite/gcc.dg/pr88784-8.c create mode 100644 gcc/testsuite/gcc.dg/pr88784-9.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 864da5a3034..3bb383769e5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,20 @@ +2019-09-16 Li Jia He + Qi Feng + + PR middle-end/88784 + * match.pd (x > y && x != XXX_MIN): Optimize into 'x > y'. + (x > y && x == XXX_MIN): Optimize into 'false'. + (x <= y && x == XXX_MIN): Optimize into 'x == XXX_MIN'. + (x < y && x != XXX_MAX): Optimize into 'x < y'. + (x < y && x == XXX_MAX): Optimize into 'false'. + (x >= y && x == XXX_MAX): Optimize into 'x == XXX_MAX'. + (x > y || x != XXX_MIN): Optimize into 'x != XXX_MIN'. + (x <= y || x != XXX_MIN): Optimize into 'true'. + (x <= y || x == XXX_MIN): Optimize into 'x <= y'. + (x < y || x != XXX_MAX): Optimize into 'x != XXX_MAX'. + (x >= y || x != XXX_MAX): Optimize into 'true'. + (x >= y || x == XXX_MAX): Optimize into 'x >= y'. + 2019-09-16 Li Jia He Martin Liska diff --git a/gcc/match.pd b/gcc/match.pd index 5690cf3d349..2ca88000cad 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -1883,6 +1883,80 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) { wide_int_to_tree (type, (wi::to_wide (@1) & (bitpos / BITS_PER_UNIT))); })))) +(match min_value + INTEGER_CST + (if (INTEGRAL_TYPE_P (type) + && wi::eq_p (wi::to_wide (t), wi::min_value (type))))) + +(match max_value + INTEGER_CST + (if (INTEGRAL_TYPE_P (type) + && wi::eq_p (wi::to_wide (t), wi::max_value (type))))) + +/* x > y && x != XXX_MIN --> x > y + x > y && x == XXX_MIN --> false . */ +(for eqne (eq ne) + (simplify + (bit_and:c (gt:c@2 @0 @1) (eqne @0 min_value)) + (switch + (if (eqne == EQ_EXPR) + { constant_boolean_node (false, type); }) + (if (eqne == NE_EXPR) + @2) + ))) + +/* x < y && x != XXX_MAX --> x < y + x < y && x == XXX_MAX --> false. */ +(for eqne (eq ne) + (simplify + (bit_and:c (lt:c@2 @0 @1) (eqne @0 max_value)) + (switch + (if (eqne == EQ_EXPR) + { constant_boolean_node (false, type); }) + (if (eqne == NE_EXPR) + @2) + ))) + +/* x <= y && x == XXX_MIN --> x == XXX_MIN. */ +(simplify + (bit_and:c (le:c @0 @1) (eq@2 @0 min_value)) + @2) + +/* x >= y && x == XXX_MAX --> x == XXX_MAX. */ +(simplify + (bit_and:c (ge:c @0 @1) (eq@2 @0 max_value)) + @2) + +/* x > y || x != XXX_MIN --> x != XXX_MIN. */ +(simplify + (bit_ior:c (gt:c @0 @1) (ne@2 @0 min_value)) + @2) + +/* x <= y || x != XXX_MIN --> true. */ +(simplify + (bit_ior:c (le:c @0 @1) (ne @0 min_value)) + { constant_boolean_node (true, type); }) + +/* x <= y || x == XXX_MIN --> x <= y. */ +(simplify + (bit_ior:c (le:c@2 @0 @1) (eq @0 min_value)) + @2) + +/* x < y || x != XXX_MAX --> x != XXX_MAX. */ +(simplify + (bit_ior:c (lt:c @0 @1) (ne@2 @0 max_value)) + @2) + +/* x >= y || x != XXX_MAX --> true + x >= y || x == XXX_MAX --> x >= y. */ +(for eqne (eq ne) + (simplify + (bit_ior:c (ge:c@2 @0 @1) (eqne @0 max_value)) + (switch + (if (eqne == EQ_EXPR) + @2) + (if (eqne == NE_EXPR) + { constant_boolean_node (true, type); })))) /* We can't reassociate at all for saturating types. */ (if (!TYPE_SATURATING (type)) @@ -5425,10 +5499,10 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) on c, so could drop potentially-trapping arithmetic, but that's a valid simplification if the result of the operation isn't needed. - Avoid speculatively generating a stand-alone vector comparison - on targets that might not support them. Any target implementing - conditional internal functions must support the same comparisons - inside and outside a VEC_COND_EXPR. */ + Avoid speculatively generating a stand-alone vector comparison + on targets that might not support them. Any target implementing + conditional internal functions must support the same comparisons + inside and outside a VEC_COND_EXPR. */ #if GIMPLE (for uncond_op (UNCOND_BINARY) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index b893ed0d462..7b9d0d05089 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,20 @@ +2019-09-16 Li Jia He + Qi Feng + + PR middle-end/88784 + * gcc.dg/pr88784-1.c: New testcase. + * gcc.dg/pr88784-2.c: New testcase. + * gcc.dg/pr88784-3.c: New testcase. + * gcc.dg/pr88784-4.c: New testcase. + * gcc.dg/pr88784-5.c: New testcase. + * gcc.dg/pr88784-6.c: New testcase. + * gcc.dg/pr88784-7.c: New testcase. + * gcc.dg/pr88784-8.c: New testcase. + * gcc.dg/pr88784-9.c: New testcase. + * gcc.dg/pr88784-10.c: New testcase. + * gcc.dg/pr88784-11.c: New testcase. + * gcc.dg/pr88784-12.c: New testcase. + 2019-09-16 Richard Biener PR tree-optimization/91756 diff --git a/gcc/testsuite/gcc.dg/pr88784-1.c b/gcc/testsuite/gcc.dg/pr88784-1.c new file mode 100644 index 00000000000..b8daae0b330 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr88784-1.c @@ -0,0 +1,30 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-ifcombine" } */ + +#include + +_Bool and1(unsigned x, unsigned y) +{ + /* x > y && x != 0 --> x > y */ + return x > y && x != 0; +} + +_Bool and2(unsigned x, unsigned y) +{ + /* x < y && x != UINT_MAX --> x < y */ + return x < y && x != UINT_MAX; +} + +_Bool and3(signed x, signed y) +{ + /* x > y && x != INT_MIN --> x > y */ + return x > y && x != INT_MIN; +} + +_Bool and4(signed x, signed y) +{ + /* x < y && x != INT_MAX --> x < y */ + return x < y && x != INT_MAX; +} + +/* { dg-final { scan-tree-dump-not " != " "ifcombine" } } */ diff --git a/gcc/testsuite/gcc.dg/pr88784-10.c b/gcc/testsuite/gcc.dg/pr88784-10.c new file mode 100644 index 00000000000..958d7656556 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr88784-10.c @@ -0,0 +1,32 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +#include + +_Bool or1(unsigned x, unsigned y) +{ + /* x <= y || x != 0 --> true */ + return x <= y || x != 0; +} + +_Bool or2(unsigned x, unsigned y) +{ + /* x >= y || x != UINT_MAX --> true */ + return x >= y || x != UINT_MAX; +} + +_Bool or3(signed x, signed y) +{ + /* x <= y || x != INT_MIN --> true */ + return x <= y || x != INT_MIN; +} + +_Bool or4(signed x, signed y) +{ + /* x >= y || x != INT_MAX --> true */ + return x >= y || x != INT_MAX; +} + +/* { dg-final { scan-tree-dump-not " != " "optimized" } } */ +/* { dg-final { scan-tree-dump-not " <= " "optimized" } } */ +/* { dg-final { scan-tree-dump-not " >= " "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/pr88784-11.c b/gcc/testsuite/gcc.dg/pr88784-11.c new file mode 100644 index 00000000000..c4b05082443 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr88784-11.c @@ -0,0 +1,30 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-ifcombine" } */ + +#include + +_Bool or1(unsigned x, unsigned y) +{ + /* x <= y || x == 0 --> x <= y */ + return x <= y || x == 0; +} + +_Bool or2(unsigned x, unsigned y) +{ + /* x >= y || x == UINT_MAX --> x >= y */ + return x >= y || x == UINT_MAX; +} + +_Bool or3(signed x, signed y) +{ + /* x <= y || x == INT_MIN --> x <= y */ + return x <= y || x == INT_MIN; +} + +_Bool or4(signed x, signed y) +{ + /* x >= y || x == INT_MAX --> x >= y */ + return x >= y || x == INT_MAX; +} + +/* { dg-final { scan-tree-dump-not " == " "ifcombine" } } */ diff --git a/gcc/testsuite/gcc.dg/pr88784-12.c b/gcc/testsuite/gcc.dg/pr88784-12.c new file mode 100644 index 00000000000..5b60b3883f0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr88784-12.c @@ -0,0 +1,30 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-dce3" } */ + +#include + +_Bool or1(unsigned x, unsigned y) +{ + /* x <= y || x == 0 --> x <= y */ + return x <= y || x == 0; +} + +_Bool or2(unsigned x, unsigned y) +{ + /* x >= y || x == UINT_MAX --> x >= y */ + return x >= y || x == UINT_MAX; +} + +_Bool or3(signed x, signed y) +{ + /* x <= y || x == INT_MIN --> x <= y */ + return x <= y || x == INT_MIN; +} + +_Bool or4(signed x, signed y) +{ + /* x >= y || x == INT_MAX --> x >= y */ + return x >= y || x == INT_MAX; +} + +/* { dg-final { scan-tree-dump-not " == " "dce3" } } */ diff --git a/gcc/testsuite/gcc.dg/pr88784-2.c b/gcc/testsuite/gcc.dg/pr88784-2.c new file mode 100644 index 00000000000..ed360018b0f --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr88784-2.c @@ -0,0 +1,30 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +#include + +_Bool and1(unsigned x, unsigned y) +{ + /* x > y && x != 0 --> x > y */ + return x > y && x != 0; +} + +_Bool and2(unsigned x, unsigned y) +{ + /* x < y && x != UINT_MAX --> x < y */ + return x < y && x != UINT_MAX; +} + +_Bool and3(signed x, signed y) +{ + /* x > y && x != INT_MIN --> x > y */ + return x > y && x != INT_MIN; +} + +_Bool and4(signed x, signed y) +{ + /* x < y && x != INT_MAX --> x < y */ + return x < y && x != INT_MAX; +} + +/* { dg-final { scan-tree-dump-not " != " "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/pr88784-3.c b/gcc/testsuite/gcc.dg/pr88784-3.c new file mode 100644 index 00000000000..8c48e1b8943 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr88784-3.c @@ -0,0 +1,32 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-ifcombine" } */ + +#include + +_Bool and1(unsigned x, unsigned y) +{ + /* x > y && x == 0 --> false */ + return x > y && x == 0; +} + +_Bool and2(unsigned x, unsigned y) +{ + /* x < y && x == UINT_MAX --> false */ + return x < y && x == UINT_MAX; +} + +_Bool and3(signed x, signed y) +{ + /* x > y && x == INT_MIN --> false */ + return x > y && x == INT_MIN; +} + +_Bool and4(signed x, signed y) +{ + /* x < y && x == INT_MAX --> false */ + return x < y && x == INT_MAX; +} + +/* { dg-final { scan-tree-dump-not " == " "ifcombine" } } */ +/* { dg-final { scan-tree-dump-not " > " "ifcombine" } } */ +/* { dg-final { scan-tree-dump-not " < " "ifcombine" } } */ diff --git a/gcc/testsuite/gcc.dg/pr88784-4.c b/gcc/testsuite/gcc.dg/pr88784-4.c new file mode 100644 index 00000000000..a9aa74cb9c3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr88784-4.c @@ -0,0 +1,32 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +#include + +_Bool and1(unsigned x, unsigned y) +{ + /* x > y && x == 0 --> false */ + return x > y && x == 0; +} + +_Bool and2(unsigned x, unsigned y) +{ + /* x < y && x == UINT_MAX --> false */ + return x < y && x == UINT_MAX; +} + +_Bool and3(signed x, signed y) +{ + /* x > y && x == INT_MIN --> false */ + return x > y && x == INT_MIN; +} + +_Bool and4(signed x, signed y) +{ + /* x < y && x == INT_MAX --> false */ + return x < y && x == INT_MAX; +} + +/* { dg-final { scan-tree-dump-not " == " "optimized" } } */ +/* { dg-final { scan-tree-dump-not " > " "optimized" } } */ +/* { dg-final { scan-tree-dump-not " < " "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/pr88784-5.c b/gcc/testsuite/gcc.dg/pr88784-5.c new file mode 100644 index 00000000000..b147abbcfaf --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr88784-5.c @@ -0,0 +1,31 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-ifcombine" } */ + +#include + +_Bool and1(unsigned x, unsigned y) +{ + /* x <= y && x == 0 --> x == 0 */ + return x <= y && x == 0; +} + +_Bool and2(unsigned x, unsigned y) +{ + /* x >= y && x == UINT_MAX --> x == UINT_MAX */ + return x >= y && x == UINT_MAX; +} + +_Bool and3(signed x, signed y) +{ + /* x <= y && x == INT_MIN --> x == INT_MIN */ + return x <= y && x == INT_MIN; +} + +_Bool and4(signed x, signed y) +{ + /* x >= y && x == INT_MAX --> x == INT_MAX */ + return x >= y && x == INT_MAX; +} + +/* { dg-final { scan-tree-dump-not " <= " "ifcombine" } } */ +/* { dg-final { scan-tree-dump-not " >= " "ifcombine" } } */ diff --git a/gcc/testsuite/gcc.dg/pr88784-6.c b/gcc/testsuite/gcc.dg/pr88784-6.c new file mode 100644 index 00000000000..6d5bd7b0c74 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr88784-6.c @@ -0,0 +1,31 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +#include + +_Bool and1(unsigned x, unsigned y) +{ + /* x <= y && x == 0 --> x == 0 */ + return x <= y && x == 0; +} + +_Bool and2(unsigned x, unsigned y) +{ + /* x >= y && x == UINT_MAX --> x == UINT_MAX */ + return x >= y && x == UINT_MAX; +} + +_Bool and3(signed x, signed y) +{ + /* x <= y && x == INT_MIN --> x == INT_MIN */ + return x <= y && x == INT_MIN; +} + +_Bool and4(signed x, signed y) +{ + /* x >= y && x == INT_MAX --> x == INT_MAX */ + return x >= y && x == INT_MAX; +} + +/* { dg-final { scan-tree-dump-not " <= " "optimized" } } */ +/* { dg-final { scan-tree-dump-not " >= " "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/pr88784-7.c b/gcc/testsuite/gcc.dg/pr88784-7.c new file mode 100644 index 00000000000..6577ff9e14d --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr88784-7.c @@ -0,0 +1,31 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-ifcombine" } */ + +#include + +_Bool or1(unsigned x, unsigned y) +{ + /* x > y || x != 0 --> x != 0 */ + return x > y || x != 0; +} + +_Bool or2(unsigned x, unsigned y) +{ + /* x < y || x != UINT_MAX --> x != UINT_MAX */ + return x < y || x != UINT_MAX; +} + +_Bool or3(signed x, signed y) +{ + /* x > y || x != INT_MIN --> x != INT_MIN */ + return x > y || x != INT_MIN; +} + +_Bool or4(signed x, signed y) +{ + /* x < y || x != INT_MAX --> x != INT_MAX */ + return x < y || x != INT_MAX; +} + +/* { dg-final { scan-tree-dump-not " > " "ifcombine" } } */ +/* { dg-final { scan-tree-dump-not " < " "ifcombine" } } */ diff --git a/gcc/testsuite/gcc.dg/pr88784-8.c b/gcc/testsuite/gcc.dg/pr88784-8.c new file mode 100644 index 00000000000..6bb56a91561 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr88784-8.c @@ -0,0 +1,31 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +#include + +_Bool or1(unsigned x, unsigned y) +{ + /* x > y || x != 0 --> x != 0 */ + return x > y || x != 0; +} + +_Bool or2(unsigned x, unsigned y) +{ + /* x < y || x != UINT_MAX --> x != UINT_MAX */ + return x < y || x != UINT_MAX; +} + +_Bool or3(signed x, signed y) +{ + /* x > y || x != INT_MIN --> x != INT_MIN */ + return x > y || x != INT_MIN; +} + +_Bool or4(signed x, signed y) +{ + /* x < y || x != INT_MAX --> x != INT_MAX */ + return x < y || x != INT_MAX; +} + +/* { dg-final { scan-tree-dump-not " > " "optimized" } } */ +/* { dg-final { scan-tree-dump-not " < " "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/pr88784-9.c b/gcc/testsuite/gcc.dg/pr88784-9.c new file mode 100644 index 00000000000..27e3281c555 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr88784-9.c @@ -0,0 +1,32 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-ifcombine" } */ + +#include + +_Bool or1(unsigned x, unsigned y) +{ + /* x <= y || x != 0 --> true */ + return x <= y || x != 0; +} + +_Bool or2(unsigned x, unsigned y) +{ + /* x >= y || x != UINT_MAX --> true */ + return x >= y || x != UINT_MAX; +} + +_Bool or3(signed x, signed y) +{ + /* x <= y || x != INT_MIN --> true */ + return x <= y || x != INT_MIN; +} + +_Bool or4(signed x, signed y) +{ + /* x >= y || x != INT_MAX --> true */ + return x >= y || x != INT_MAX; +} + +/* { dg-final { scan-tree-dump-not " != " "ifcombine" } } */ +/* { dg-final { scan-tree-dump-not " <= " "ifcombine" } } */ +/* { dg-final { scan-tree-dump-not " >= " "ifcombine" } } */ -- 2.30.2