aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPan Li <pan2.li@intel.com>2024-10-24 21:57:04 +0800
committerPan Li <pan2.li@intel.com>2024-10-25 21:52:43 +0800
commitdf4af89bc3eabbeaccb16539aa1082cb9863e187 (patch)
tree09ec974a2f102735fc3cb6f5c13b84b1f6c8fa3e
parente2a8772c9328960c625f5b95091d4312efa0e284 (diff)
downloadgcc-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.pd11
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/sat_u_add-simplify-1-u16.c15
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/sat_u_add-simplify-1-u32.c15
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/sat_u_add-simplify-1-u64.c15
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/sat_u_add-simplify-1-u8.c15
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" } } */