diff options
author | Pan Li <pan2.li@intel.com> | 2024-10-24 21:57:04 +0800 |
---|---|---|
committer | Pan Li <pan2.li@intel.com> | 2024-10-25 21:52:43 +0800 |
commit | df4af89bc3eabbeaccb16539aa1082cb9863e187 (patch) | |
tree | 09ec974a2f102735fc3cb6f5c13b84b1f6c8fa3e | |
parent | e2a8772c9328960c625f5b95091d4312efa0e284 (diff) | |
download | gcc-df4af89bc3eabbeaccb16539aa1082cb9863e187.zip gcc-df4af89bc3eabbeaccb16539aa1082cb9863e187.tar.gz gcc-df4af89bc3eabbeaccb16539aa1082cb9863e187.tar.bz2 |
Match: Simplify branch form 3 of unsigned SAT_ADD into branchless
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>
-rw-r--r-- | gcc/match.pd | 11 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/sat_u_add-simplify-1-u16.c | 15 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/sat_u_add-simplify-1-u32.c | 15 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/sat_u_add-simplify-1-u64.c | 15 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/sat_u_add-simplify-1-u8.c | 15 |
5 files changed, 67 insertions, 4 deletions
diff --git a/gcc/match.pd b/gcc/match.pd index e622ccb..f16b733 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -3146,10 +3146,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 0000000..7617fba --- /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 0000000..efea85b --- /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 0000000..b7b55d7 --- /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 0000000..77e9af3 --- /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" } } */ |