diff mbox series

Match: Simplify branch form 3 of unsigned SAT_ADD into branchless

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

Commit Message

Li, Pan2 Oct. 24, 2024, 2:07 p.m. UTC
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.

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

Comments

Richard Biener Oct. 25, 2024, 12:48 p.m. UTC | #1
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 mbox series

Patch

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" } } */