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>
This commit is contained in:
Pan Li 2024-07-18 20:16:34 +08:00
parent e20ea6bcf8
commit 02cc849474
2 changed files with 50 additions and 2 deletions

View File

@ -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));

View File

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