aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPan Li <pan2.li@intel.com>2024-07-18 20:16:34 +0800
committerPan Li <pan2.li@intel.com>2024-07-19 08:39:21 +0800
commit02cc8494745c4235890ad58e93b5acce5a89a775 (patch)
tree3a11a58357e95d730c0030095871474dc5695b10
parente20ea6bcf8456b655656e50174f58a364fdb7a4e (diff)
downloadgcc-02cc8494745c4235890ad58e93b5acce5a89a775.zip
gcc-02cc8494745c4235890ad58e93b5acce5a89a775.tar.gz
gcc-02cc8494745c4235890ad58e93b5acce5a89a775.tar.bz2
Match: Only allow single use of MIN_EXPR for SAT_TRUNC form 2 [PR115863]
The SAT_TRUNC form 2 has below pattern matching. From: _18 = MIN_EXPR <left_8, 4294967295>; iftmp.0_11 = (unsigned int) _18; To: _18 = MIN_EXPR <left_8, 4294967295>; iftmp.0_11 = .SAT_TRUNC (left_8); But if there is another use of _18 like below, the transform to the .SAT_TRUNC may have no earnings. For example: From: _18 = MIN_EXPR <left_8, 4294967295>; // op_0 def iftmp.0_11 = (unsigned int) _18; // op_0 stream.avail_out = iftmp.0_11; left_37 = left_8 - _18; // op_0 use To: _18 = MIN_EXPR <left_8, 4294967295>; // op_0 def iftmp.0_11 = .SAT_TRUNC (left_8); stream.avail_out = iftmp.0_11; left_37 = left_8 - _18; // op_0 use Pattern recog to .SAT_TRUNC cannot eliminate MIN_EXPR as above. Then the backend (for example x86/riscv) will have additional 2-3 more insns after pattern recog besides the MIN_EXPR. Thus, keep the normal truncation as is should be the better choose. The below testsuites are passed for this patch: 1. The rv64gcv fully regression tests. 2. The x86 bootstrap tests. 3. The x86 fully regression tests. PR target/115863 gcc/ChangeLog: * match.pd: Add single_use check for .SAT_TRUNC form 2. gcc/testsuite/ChangeLog: * gcc.target/i386/pr115863-1.c: New test. Signed-off-by: Pan Li <pan2.li@intel.com>
-rw-r--r--gcc/match.pd15
-rw-r--r--gcc/testsuite/gcc.target/i386/pr115863-1.c37
2 files changed, 50 insertions, 2 deletions
diff --git a/gcc/match.pd b/gcc/match.pd
index 6818856..cf359b0 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -3252,10 +3252,21 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
/* Unsigned saturation truncate, case 2, sizeof (WT) > sizeof (NT).
SAT_U_TRUNC = (NT)(MIN_EXPR (X, 255)). */
+/* If Op_0 def is MIN_EXPR and not single_use. Aka below pattern:
+
+ _18 = MIN_EXPR <left_8, 4294967295>; // op_0 def
+ iftmp.0_11 = (unsigned int) _18; // op_0
+ stream.avail_out = iftmp.0_11;
+ left_37 = left_8 - _18; // op_0 use
+
+ Transfer to .SAT_TRUNC will have MIN_EXPR still live. Then the backend
+ (for example x86/riscv) will have 2-3 more insns generation for .SAT_TRUNC
+ besides the MIN_EXPR. Thus, keep the normal truncation as is should be
+ the better choose. */
(match (unsigned_integer_sat_trunc @0)
- (convert (min @0 INTEGER_CST@1))
+ (convert (min@2 @0 INTEGER_CST@1))
(if (INTEGRAL_TYPE_P (type) && TYPE_UNSIGNED (type)
- && TYPE_UNSIGNED (TREE_TYPE (@0)))
+ && TYPE_UNSIGNED (TREE_TYPE (@0)) && single_use (@2))
(with
{
unsigned itype_precision = TYPE_PRECISION (TREE_TYPE (@0));
diff --git a/gcc/testsuite/gcc.target/i386/pr115863-1.c b/gcc/testsuite/gcc.target/i386/pr115863-1.c
new file mode 100644
index 0000000..a672f62
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr115863-1.c
@@ -0,0 +1,37 @@
+/* PR target/115863 */
+/* { dg-do compile } */
+/* { dg-options "-O3 -fdump-rtl-expand-details" } */
+
+#include <stdint-gcc.h>
+
+typedef struct z_stream_s {
+ uint32_t avail_out;
+} z_stream;
+
+typedef z_stream *z_streamp;
+
+extern int deflate (z_streamp strmp);
+
+int compress2 (uint64_t *destLen)
+{
+ z_stream stream;
+ int err;
+ const uint32_t max = (uint32_t)(-1);
+ uint64_t left;
+
+ left = *destLen;
+
+ stream.avail_out = 0;
+
+ do {
+ if (stream.avail_out == 0) {
+ stream.avail_out = left > (uint64_t)max ? max : (uint32_t)left;
+ left -= stream.avail_out;
+ }
+ err = deflate(&stream);
+ } while (err == 0);
+
+ return err;
+}
+
+/* { dg-final { scan-rtl-dump-not ".SAT_TRUNC " "expand" } } */