This patch adds a new case for unsigned scalar saturating subtraction using a branch with a greater-than-or-equal condition. For example,
X >= (X - Y) ? (X - Y) : 0 is transformed into SAT_SUB (X, Y) when X and Y are unsigned scalars, which therefore correctly matches more cases of IFN SAT_SUB. New tests are added to verify this behaviour on targets which use the standard names for IFN SAT_SUB, and the tests are skipped if the current target does not support IFN_SAT_SUB for each of these modes (via dg-require-effective-target). This passes the aarch64 regression tests with no additional failures. gcc/ChangeLog: * match.pd: Add new match for SAT_SUB. gcc/testsuite/ChangeLog: * gcc.dg/tree-ssa/sat-u-sub-match-1-u16.c: New test. * gcc.dg/tree-ssa/sat-u-sub-match-1-u32.c: New test. * gcc.dg/tree-ssa/sat-u-sub-match-1-u64.c: New test. * gcc.dg/tree-ssa/sat-u-sub-match-1-u8.c: New test. --- gcc/match.pd | 8 ++++++++ .../gcc.dg/tree-ssa/sat-u-sub-match-1-u16.c | 15 +++++++++++++++ .../gcc.dg/tree-ssa/sat-u-sub-match-1-u32.c | 15 +++++++++++++++ .../gcc.dg/tree-ssa/sat-u-sub-match-1-u64.c | 15 +++++++++++++++ .../gcc.dg/tree-ssa/sat-u-sub-match-1-u8.c | 15 +++++++++++++++ 5 files changed, 68 insertions(+) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/sat-u-sub-match-1-u16.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/sat-u-sub-match-1-u32.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/sat-u-sub-match-1-u64.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/sat-u-sub-match-1-u8.c diff --git a/gcc/match.pd b/gcc/match.pd index ee53c25cef9..4fc5efa6247 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -3360,6 +3360,14 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) } (if (wi::eq_p (sum, wi::uhwi (0, precision))))))) +/* Unsigned saturation sub, case 11 (branch with ge): + SAT_U_SUB = X >= (X - Y) ? (X - Y) : 0. */ +(match (unsigned_integer_sat_sub @0 @1) + (cond^ (ge @0 (minus @0 @1)) + (convert? (minus (convert1? @0) (convert1? @1))) integer_zerop) + (if (INTEGRAL_TYPE_P (type) && TYPE_UNSIGNED (type) + && TYPE_UNSIGNED (TREE_TYPE (@0)) && types_match (@0, @1)))) + /* Signed saturation sub, case 1: T minus = (T)((UT)X - (UT)Y); SAT_S_SUB = (X ^ Y) & (X ^ minus) < 0 ? (-(T)(X < 0) ^ MAX) : minus; diff --git a/gcc/testsuite/gcc.dg/tree-ssa/sat-u-sub-match-1-u16.c b/gcc/testsuite/gcc.dg/tree-ssa/sat-u-sub-match-1-u16.c new file mode 100644 index 00000000000..641fac50858 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/sat-u-sub-match-1-u16.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target ussub_himode } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +#include <stdint.h> + +#define T uint16_t + +T sat_u_sub_1 (T a, T b) +{ + T sum = a - b; + return sum > a ? 0 : sum; +} + +/* { dg-final { scan-tree-dump " .SAT_SUB " "optimized" } } */ \ No newline at end of file diff --git a/gcc/testsuite/gcc.dg/tree-ssa/sat-u-sub-match-1-u32.c b/gcc/testsuite/gcc.dg/tree-ssa/sat-u-sub-match-1-u32.c new file mode 100644 index 00000000000..27f3bae7d52 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/sat-u-sub-match-1-u32.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target ussub_simode } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +#include <stdint.h> + +#define T uint32_t + +T sat_u_sub_1 (T a, T b) +{ + T sum = a - b; + return sum > a ? 0 : sum; +} + +/* { dg-final { scan-tree-dump " .SAT_SUB " "optimized" } } */ \ No newline at end of file diff --git a/gcc/testsuite/gcc.dg/tree-ssa/sat-u-sub-match-1-u64.c b/gcc/testsuite/gcc.dg/tree-ssa/sat-u-sub-match-1-u64.c new file mode 100644 index 00000000000..92883ce60c7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/sat-u-sub-match-1-u64.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target ussub_dimode } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +#include <stdint.h> + +#define T uint64_t + +T sat_u_sub_1 (T a, T b) +{ + T sum = a - b; + return sum > a ? 0 : sum; +} + +/* { dg-final { scan-tree-dump " .SAT_SUB " "optimized" } } */ \ No newline at end of file diff --git a/gcc/testsuite/gcc.dg/tree-ssa/sat-u-sub-match-1-u8.c b/gcc/testsuite/gcc.dg/tree-ssa/sat-u-sub-match-1-u8.c new file mode 100644 index 00000000000..06ff91dbed0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/sat-u-sub-match-1-u8.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target ussub_qimode } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +#include <stdint.h> + +#define T uint8_t + +T sat_u_sub_1 (T a, T b) +{ + T sum = a - b; + return sum > a ? 0 : sum; +} + +/* { dg-final { scan-tree-dump " .SAT_SUB " "optimized" } } */ \ No newline at end of file -- 2.34.1