On Tue, Sep 12, 2023 at 6:22 AM Andrew Pinski via Gcc-patches <gcc-patches@gcc.gnu.org> wrote: > > This adds the missing optimizations here. > Note we don't need to match where CMP1 and CMP2 are complements of each > other as that is already handled elsewhere. > > I added a new executable testcase to make sure we optimize it correctly > as I had originally messed up one of the entries for the resulting > comparison to make sure they were 100% correct. > > OK? Bootstrapped and tested on x86_64-linux-gnu with no regressions.
OK. > PR tree-optimization/107881 > > gcc/ChangeLog: > > * match.pd (`(a CMP1 b) ^ (a CMP2 b)`): New pattern. > (`(a CMP1 b) == (a CMP2 b)`): New pattern. > > gcc/testsuite/ChangeLog: > > * gcc.c-torture/execute/pr107881-1.c: New test. > * gcc.dg/tree-ssa/cmpeq-4.c: New test. > * gcc.dg/tree-ssa/cmpxor-1.c: New test. > --- > gcc/match.pd | 20 +++ > .../gcc.c-torture/execute/pr107881-1.c | 115 ++++++++++++++++++ > gcc/testsuite/gcc.dg/tree-ssa/cmpeq-4.c | 51 ++++++++ > gcc/testsuite/gcc.dg/tree-ssa/cmpxor-1.c | 51 ++++++++ > 4 files changed, 237 insertions(+) > create mode 100644 gcc/testsuite/gcc.c-torture/execute/pr107881-1.c > create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/cmpeq-4.c > create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/cmpxor-1.c > > diff --git a/gcc/match.pd b/gcc/match.pd > index e96e385c6fa..39c7ea1088f 100644 > --- a/gcc/match.pd > +++ b/gcc/match.pd > @@ -3154,6 +3154,26 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) > { constant_boolean_node (true, type); }) > )))))) > > +/* Optimize (a CMP b) ^ (a CMP b) */ > +/* Optimize (a CMP b) != (a CMP b) */ > +(for op (bit_xor ne) > + (for cmp1 (lt lt lt le le le) > + cmp2 (gt eq ne ge eq ne) > + rcmp (ne le gt ne lt ge) > + (simplify > + (op:c (cmp1:c @0 @1) (cmp2:c @0 @1)) > + (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)) || POINTER_TYPE_P (TREE_TYPE (@0))) > + (rcmp @0 @1))))) > + > +/* Optimize (a CMP b) == (a CMP b) */ > +(for cmp1 (lt lt lt le le le) > + cmp2 (gt eq ne ge eq ne) > + rcmp (eq gt le eq ge lt) > + (simplify > + (eq:c (cmp1:c @0 @1) (cmp2:c @0 @1)) > + (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)) || POINTER_TYPE_P (TREE_TYPE (@0))) > + (rcmp @0 @1)))) > + > /* We can't reassociate at all for saturating types. */ > (if (!TYPE_SATURATING (type)) > > diff --git a/gcc/testsuite/gcc.c-torture/execute/pr107881-1.c > b/gcc/testsuite/gcc.c-torture/execute/pr107881-1.c > new file mode 100644 > index 00000000000..063ec4c2797 > --- /dev/null > +++ b/gcc/testsuite/gcc.c-torture/execute/pr107881-1.c > @@ -0,0 +1,115 @@ > +#define func(vol, op1, op2, op3) \ > +_Bool op1##_##op2##_##op3##_##vol (int a, int b) \ > +{ \ > + vol _Bool x = op_##op1(a, b); \ > + vol _Bool y = op_##op2(a, b); \ > + return op_##op3(x, y); \ > +} > + > +#define op_lt(a, b) ((a) < (b)) > +#define op_le(a, b) ((a) <= (b)) > +#define op_eq(a, b) ((a) == (b)) > +#define op_ne(a, b) ((a) != (b)) > +#define op_gt(a, b) ((a) > (b)) > +#define op_ge(a, b) ((a) >= (b)) > +#define op_xor(a, b) ((a) ^ (b)) > + > + > +#define funcs(a) \ > + a(lt,lt,ne) \ > + a(lt,lt,eq) \ > + a(lt,lt,xor) \ > + a(lt,le,ne) \ > + a(lt,le,eq) \ > + a(lt,le,xor) \ > + a(lt,gt,ne) \ > + a(lt,gt,eq) \ > + a(lt,gt,xor) \ > + a(lt,ge,ne) \ > + a(lt,ge,eq) \ > + a(lt,ge,xor) \ > + a(lt,eq,ne) \ > + a(lt,eq,eq) \ > + a(lt,eq,xor) \ > + a(lt,ne,ne) \ > + a(lt,ne,eq) \ > + a(lt,ne,xor) \ > + \ > + a(le,lt,ne) \ > + a(le,lt,eq) \ > + a(le,lt,xor) \ > + a(le,le,ne) \ > + a(le,le,eq) \ > + a(le,le,xor) \ > + a(le,gt,ne) \ > + a(le,gt,eq) \ > + a(le,gt,xor) \ > + a(le,ge,ne) \ > + a(le,ge,eq) \ > + a(le,ge,xor) \ > + a(le,eq,ne) \ > + a(le,eq,eq) \ > + a(le,eq,xor) \ > + a(le,ne,ne) \ > + a(le,ne,eq) \ > + a(le,ne,xor) \ > + \ > + a(gt,lt,ne) \ > + a(gt,lt,eq) \ > + a(gt,lt,xor) \ > + a(gt,le,ne) \ > + a(gt,le,eq) \ > + a(gt,le,xor) \ > + a(gt,gt,ne) \ > + a(gt,gt,eq) \ > + a(gt,gt,xor) \ > + a(gt,ge,ne) \ > + a(gt,ge,eq) \ > + a(gt,ge,xor) \ > + a(gt,eq,ne) \ > + a(gt,eq,eq) \ > + a(gt,eq,xor) \ > + a(gt,ne,ne) \ > + a(gt,ne,eq) \ > + a(gt,ne,xor) \ > + \ > + a(ge,lt,ne) \ > + a(ge,lt,eq) \ > + a(ge,lt,xor) \ > + a(ge,le,ne) \ > + a(ge,le,eq) \ > + a(ge,le,xor) \ > + a(ge,gt,ne) \ > + a(ge,gt,eq) \ > + a(ge,gt,xor) \ > + a(ge,ge,ne) \ > + a(ge,ge,eq) \ > + a(ge,ge,xor) \ > + a(ge,eq,ne) \ > + a(ge,eq,eq) \ > + a(ge,eq,xor) \ > + a(ge,ne,ne) \ > + a(ge,ne,eq) \ > + a(ge,ne,xor) > + > +#define funcs1(a,b,c) \ > +func(,a,b,c) \ > +func(volatile,a,b,c) > + > +funcs(funcs1) > + > +#define test(op1,op2,op3) \ > +do { \ > + if (op1##_##op2##_##op3##_(x,y) \ > + != op1##_##op2##_##op3##_volatile(x,y)) \ > + __builtin_abort(); \ > +} while(0); > + > +int main() > +{ > + for(int x = -10; x < 10; x++) > + for(int y = -10; y < 10; y++) > + { > + funcs(test) > + } > +} > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/cmpeq-4.c > b/gcc/testsuite/gcc.dg/tree-ssa/cmpeq-4.c > new file mode 100644 > index 00000000000..868d80fdcca > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/tree-ssa/cmpeq-4.c > @@ -0,0 +1,51 @@ > +/* { dg-do compile } */ > +/* { dg-options "-O2 -fdump-tree-optimized -fdump-tree-original" } */ > +/* PR tree-optimization/107881 */ > + > +_Bool ltgt_eq(int a, int b) > +{ > + _Bool c = a < b; > + _Bool d = a > b; > + return c == d; // a == b > +} > +/* { dg-final { scan-tree-dump "a_\[0-9\]+.D. == b_\[0-9\]+.D.|b_\[0-9\]+.D. > == a_\[0-9\]+.D." "optimized" } } */ > + > +_Bool lteq_eq(int x, int y) > +{ > + _Bool c = x < y; > + _Bool d = x == y; > + return c == d; // x > y > +} > +/* { dg-final { scan-tree-dump "x_\[0-9\]+.D. > y_\[0-9\]+.D.|y_\[0-9\]+.D. > < x_\[0-9\]+.D." "optimized" } } */ > + > +_Bool ltne_eq(int z, int w) > +{ > + _Bool c = z < w; > + _Bool d = z != w; > + return c == d; // z <= w > +} > +/* { dg-final { scan-tree-dump "z_\[0-9\]+.D. <= w_\[0-9\]+.D.|w_\[0-9\]+.D. > >= y_\[0-9\]+.D." "optimized" } } */ > + > +_Bool lege_eq(int i, int j) > +{ > + _Bool c = i <= j; > + _Bool d = i >= j; > + return c == d; // i == j > +} > +/* { dg-final { scan-tree-dump "i_\[0-9\]+.D. == j_\[0-9\]+.D.|j_\[0-9\]+.D. > == i_\[0-9\]+.D." "optimized" } } */ > + > +_Bool leeq_eq(int k, int l) > +{ > + _Bool c = k <= l; > + _Bool d = k == l; > + return c == d; // k >= l > +} > +/* { dg-final { scan-tree-dump "k_\[0-9\]+.D. >= l_\[0-9\]+.D.|l_\[0-9\]+.D. > <= k_\[0-9\]+.D." "optimized" } } */ > + > +_Bool lene_eq(int m, int n) > +{ > + _Bool c = m <= n; > + _Bool d = m != n; > + return c == d; // m < n > +} > +/* { dg-final { scan-tree-dump "m_\[0-9\]+.D. < n_\[0-9\]+.D.|n_\[0-9\]+.D. > > m_\[0-9\]+.D." "optimized" } } */ > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/cmpxor-1.c > b/gcc/testsuite/gcc.dg/tree-ssa/cmpxor-1.c > new file mode 100644 > index 00000000000..8de2d9d2244 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/tree-ssa/cmpxor-1.c > @@ -0,0 +1,51 @@ > +/* { dg-do compile } */ > +/* { dg-options "-O2 -fdump-tree-optimized" } */ > +/* PR tree-optimization/107881 */ > + > +_Bool ltgtxor(int a, int b) > +{ > + _Bool c = a < b; > + _Bool d = a > b; > + return c ^ d; // a != b > +} > +/* { dg-final { scan-tree-dump "a_\[0-9\]+.D. != b_\[0-9\]+.D.|b_\[0-9\]+.D. > != a_\[0-9\]+.D." "optimized" } } */ > + > +_Bool lteqxor(int x, int y) > +{ > + _Bool c = x < y; > + _Bool d = x == y; > + return c ^ d; // x <= y (basically | here) > +} > +/* { dg-final { scan-tree-dump "x_\[0-9\]+.D. <= y_\[0-9\]+.D.|y_\[0-9\]+.D. > >= x_\[0-9\]+.D." "optimized" } } */ > + > +_Bool ltnexor(int z, int w) > +{ > + _Bool c = z < w; > + _Bool d = z != w; > + return c ^ d; // z > w > +} > +/* { dg-final { scan-tree-dump "z_\[0-9\]+.D. > w_\[0-9\]+.D.|w_\[0-9\]+.D. > < y_\[0-9\]+.D." "optimized" } } */ > + > +_Bool legexor(int i, int j) > +{ > + _Bool c = i <= j; > + _Bool d = i >= j; > + return c ^ d; // i != j > +} > +/* { dg-final { scan-tree-dump "i_\[0-9\]+.D. != j_\[0-9\]+.D.|j_\[0-9\]+.D. > != i_\[0-9\]+.D." "optimized" } } */ > + > +_Bool leeqxor(int k, int l) > +{ > + _Bool c = k <= l; > + _Bool d = k == l; > + return c ^ d; // k < l > +} > +/* { dg-final { scan-tree-dump "k_\[0-9\]+.D. < l_\[0-9\]+.D.|l_\[0-9\]+.D. > > k_\[0-9\]+.D." "optimized" } } */ > + > +_Bool lenexor(int m, int n) > +{ > + _Bool c = m <= n; > + _Bool d = m != n; > + return c ^ d; // m >= n > +} > +/* { dg-final { scan-tree-dump "m_\[0-9\]+.D. >= n_\[0-9\]+.D.|n_\[0-9\]+.D. > <= m_\[0-9\]+.D." "optimized" } } */ > -- > 2.31.1 >