Message ID | 20241024140709.4153038-1-pan2.li@intel.com |
---|---|
State | New |
Headers | show |
Series | Match: Simplify branch form 3 of unsigned SAT_ADD into branchless | expand |
On Thu, Oct 24, 2024 at 4:08 PM <pan2.li@intel.com> wrote: > > From: Pan Li <pan2.li@intel.com> > > There are sorts of forms for the unsigned SAT_ADD. Some of them are > complicated while others are cheap. This patch would like to simplify > the complicated form into the cheap ones. For example as below: > > From the form 3 (branch): > SAT_U_ADD = (X + Y) >= x ? (X + Y) : -1. > > To (branchless): > SAT_U_ADD = (X + Y) | - ((X + Y) < X). > > #define T uint8_t > > T sat_add_u_1 (T x, T y) > { > return (T)(x + y) >= x ? (x + y) : -1; > } > > Before this patch: > 1 │ uint8_t sat_add_u_1 (uint8_t x, uint8_t y) > 2 │ { > 3 │ uint8_t D.2809; > 4 │ > 5 │ _1 = x + y; > 6 │ if (x <= _1) goto <D.2810>; else goto <D.2811>; > 7 │ <D.2810>: > 8 │ D.2809 = x + y; > 9 │ goto <D.2812>; > 10 │ <D.2811>: > 11 │ D.2809 = 255; > 12 │ <D.2812>: > 13 │ return D.2809; > 14 │ } > > After this patch: > 1 │ uint8_t sat_add_u_1 (uint8_t x, uint8_t y) > 2 │ { > 3 │ uint8_t D.2809; > 4 │ > 5 │ _1 = x + y; > 6 │ _2 = x + y; > 7 │ _3 = x > _2; > 8 │ _4 = (unsigned char) _3; > 9 │ _5 = -_4; > 10 │ D.2809 = _1 | _5; > 11 │ return D.2809; > 12 │ } > > The simplify doesn't need to check if target support the SAT_ADD, it > is somehow the optimization in gimple level. > > The below test suites are passed for this patch. > * The rv64gcv fully regression test. > * The x86 bootstrap test. > * The x86 fully regression test. OK. Richard. > gcc/ChangeLog: > > * match.pd: Remove unsigned branch form 3 for SAT_ADD, and > add simplify to branchless instead. > > gcc/testsuite/ChangeLog: > > * gcc.dg/tree-ssa/sat_u_add-simplify-1-u16.c: New test. > * gcc.dg/tree-ssa/sat_u_add-simplify-1-u32.c: New test. > * gcc.dg/tree-ssa/sat_u_add-simplify-1-u64.c: New test. > * gcc.dg/tree-ssa/sat_u_add-simplify-1-u8.c: New test. > > Signed-off-by: Pan Li <pan2.li@intel.com> > --- > gcc/match.pd | 11 +++++++---- > .../gcc.dg/tree-ssa/sat_u_add-simplify-1-u16.c | 15 +++++++++++++++ > .../gcc.dg/tree-ssa/sat_u_add-simplify-1-u32.c | 15 +++++++++++++++ > .../gcc.dg/tree-ssa/sat_u_add-simplify-1-u64.c | 15 +++++++++++++++ > .../gcc.dg/tree-ssa/sat_u_add-simplify-1-u8.c | 15 +++++++++++++++ > 5 files changed, 67 insertions(+), 4 deletions(-) > create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/sat_u_add-simplify-1-u16.c > create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/sat_u_add-simplify-1-u32.c > create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/sat_u_add-simplify-1-u64.c > create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/sat_u_add-simplify-1-u8.c > > diff --git a/gcc/match.pd b/gcc/match.pd > index 0455dfa6993..0ecd44bd51a 100644 > --- a/gcc/match.pd > +++ b/gcc/match.pd > @@ -3141,10 +3141,13 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) > (match (unsigned_integer_sat_add @0 @1) > (bit_ior:c (usadd_left_part_2 @0 @1) (usadd_right_part_2 @0 @1))) > > -/* Unsigned saturation add, case 3 (branch with ge): > - SAT_U_ADD = (X + Y) >= x ? (X + Y) : -1. */ > -(match (unsigned_integer_sat_add @0 @1) > - (cond^ (ge (usadd_left_part_1@2 @0 @1) @0) @2 integer_minus_onep)) > +/* Simplify SAT_U_ADD to the cheap form > + From: SAT_U_ADD = (X + Y) >= x ? (X + Y) : -1. > + To: SAT_U_ADD = (X + Y) | - ((X + Y) < X). */ > +(simplify (cond (ge (plus:c@2 @0 @1) @0) @2 integer_minus_onep) > + (if (INTEGRAL_TYPE_P (type) && TYPE_UNSIGNED (type) > + && types_match (type, @0, @1)) > + (bit_ior @2 (negate (convert (lt @2 @0)))))) > > /* Unsigned saturation add, case 4 (branch with lt): > SAT_U_ADD = (X + Y) < x ? -1 : (X + Y). */ > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/sat_u_add-simplify-1-u16.c b/gcc/testsuite/gcc.dg/tree-ssa/sat_u_add-simplify-1-u16.c > new file mode 100644 > index 00000000000..7617fbaca45 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/tree-ssa/sat_u_add-simplify-1-u16.c > @@ -0,0 +1,15 @@ > +/* { dg-do compile } */ > +/* { dg-options "-O2 -fdump-tree-gimple-details" } */ > + > +#include <stdint.h> > + > +#define T uint16_t > + > +T sat_add_u_1 (T x, T y) > +{ > + return (T)(x + y) >= x ? (x + y) : -1; > +} > + > +/* { dg-final { scan-tree-dump-not " if " "gimple" } } */ > +/* { dg-final { scan-tree-dump-not " else " "gimple" } } */ > +/* { dg-final { scan-tree-dump-not " goto " "gimple" } } */ > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/sat_u_add-simplify-1-u32.c b/gcc/testsuite/gcc.dg/tree-ssa/sat_u_add-simplify-1-u32.c > new file mode 100644 > index 00000000000..efea85bfbb7 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/tree-ssa/sat_u_add-simplify-1-u32.c > @@ -0,0 +1,15 @@ > +/* { dg-do compile } */ > +/* { dg-options "-O2 -fdump-tree-gimple-details" } */ > + > +#include <stdint.h> > + > +#define T uint32_t > + > +T sat_add_u_1 (T x, T y) > +{ > + return (T)(x + y) >= x ? (x + y) : -1; > +} > + > +/* { dg-final { scan-tree-dump-not " if " "gimple" } } */ > +/* { dg-final { scan-tree-dump-not " else " "gimple" } } */ > +/* { dg-final { scan-tree-dump-not " goto " "gimple" } } */ > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/sat_u_add-simplify-1-u64.c b/gcc/testsuite/gcc.dg/tree-ssa/sat_u_add-simplify-1-u64.c > new file mode 100644 > index 00000000000..b7b55d72ede > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/tree-ssa/sat_u_add-simplify-1-u64.c > @@ -0,0 +1,15 @@ > +/* { dg-do compile } */ > +/* { dg-options "-O2 -fdump-tree-gimple-details" } */ > + > +#include <stdint.h> > + > +#define T uint64_t > + > +T sat_add_u_1 (T x, T y) > +{ > + return (T)(x + y) >= x ? (x + y) : -1; > +} > + > +/* { dg-final { scan-tree-dump-not " if " "gimple" } } */ > +/* { dg-final { scan-tree-dump-not " else " "gimple" } } */ > +/* { dg-final { scan-tree-dump-not " goto " "gimple" } } */ > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/sat_u_add-simplify-1-u8.c b/gcc/testsuite/gcc.dg/tree-ssa/sat_u_add-simplify-1-u8.c > new file mode 100644 > index 00000000000..77e9af3dd29 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/tree-ssa/sat_u_add-simplify-1-u8.c > @@ -0,0 +1,15 @@ > +/* { dg-do compile } */ > +/* { dg-options "-O2 -fdump-tree-gimple-details" } */ > + > +#include <stdint.h> > + > +#define T uint8_t > + > +T sat_add_u_1 (T x, T y) > +{ > + return (T)(x + y) >= x ? (x + y) : -1; > +} > + > +/* { dg-final { scan-tree-dump-not " if " "gimple" } } */ > +/* { dg-final { scan-tree-dump-not " else " "gimple" } } */ > +/* { dg-final { scan-tree-dump-not " goto " "gimple" } } */ > -- > 2.43.0 >
diff --git a/gcc/match.pd b/gcc/match.pd index 0455dfa6993..0ecd44bd51a 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -3141,10 +3141,13 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (match (unsigned_integer_sat_add @0 @1) (bit_ior:c (usadd_left_part_2 @0 @1) (usadd_right_part_2 @0 @1))) -/* Unsigned saturation add, case 3 (branch with ge): - SAT_U_ADD = (X + Y) >= x ? (X + Y) : -1. */ -(match (unsigned_integer_sat_add @0 @1) - (cond^ (ge (usadd_left_part_1@2 @0 @1) @0) @2 integer_minus_onep)) +/* Simplify SAT_U_ADD to the cheap form + From: SAT_U_ADD = (X + Y) >= x ? (X + Y) : -1. + To: SAT_U_ADD = (X + Y) | - ((X + Y) < X). */ +(simplify (cond (ge (plus:c@2 @0 @1) @0) @2 integer_minus_onep) + (if (INTEGRAL_TYPE_P (type) && TYPE_UNSIGNED (type) + && types_match (type, @0, @1)) + (bit_ior @2 (negate (convert (lt @2 @0)))))) /* Unsigned saturation add, case 4 (branch with lt): SAT_U_ADD = (X + Y) < x ? -1 : (X + Y). */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/sat_u_add-simplify-1-u16.c b/gcc/testsuite/gcc.dg/tree-ssa/sat_u_add-simplify-1-u16.c new file mode 100644 index 00000000000..7617fbaca45 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/sat_u_add-simplify-1-u16.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-gimple-details" } */ + +#include <stdint.h> + +#define T uint16_t + +T sat_add_u_1 (T x, T y) +{ + return (T)(x + y) >= x ? (x + y) : -1; +} + +/* { dg-final { scan-tree-dump-not " if " "gimple" } } */ +/* { dg-final { scan-tree-dump-not " else " "gimple" } } */ +/* { dg-final { scan-tree-dump-not " goto " "gimple" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/sat_u_add-simplify-1-u32.c b/gcc/testsuite/gcc.dg/tree-ssa/sat_u_add-simplify-1-u32.c new file mode 100644 index 00000000000..efea85bfbb7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/sat_u_add-simplify-1-u32.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-gimple-details" } */ + +#include <stdint.h> + +#define T uint32_t + +T sat_add_u_1 (T x, T y) +{ + return (T)(x + y) >= x ? (x + y) : -1; +} + +/* { dg-final { scan-tree-dump-not " if " "gimple" } } */ +/* { dg-final { scan-tree-dump-not " else " "gimple" } } */ +/* { dg-final { scan-tree-dump-not " goto " "gimple" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/sat_u_add-simplify-1-u64.c b/gcc/testsuite/gcc.dg/tree-ssa/sat_u_add-simplify-1-u64.c new file mode 100644 index 00000000000..b7b55d72ede --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/sat_u_add-simplify-1-u64.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-gimple-details" } */ + +#include <stdint.h> + +#define T uint64_t + +T sat_add_u_1 (T x, T y) +{ + return (T)(x + y) >= x ? (x + y) : -1; +} + +/* { dg-final { scan-tree-dump-not " if " "gimple" } } */ +/* { dg-final { scan-tree-dump-not " else " "gimple" } } */ +/* { dg-final { scan-tree-dump-not " goto " "gimple" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/sat_u_add-simplify-1-u8.c b/gcc/testsuite/gcc.dg/tree-ssa/sat_u_add-simplify-1-u8.c new file mode 100644 index 00000000000..77e9af3dd29 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/sat_u_add-simplify-1-u8.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-gimple-details" } */ + +#include <stdint.h> + +#define T uint8_t + +T sat_add_u_1 (T x, T y) +{ + return (T)(x + y) >= x ? (x + y) : -1; +} + +/* { dg-final { scan-tree-dump-not " if " "gimple" } } */ +/* { dg-final { scan-tree-dump-not " else " "gimple" } } */ +/* { dg-final { scan-tree-dump-not " goto " "gimple" } } */