public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* Re: [PATCH v3] EXPR: Emit an truncate if 31+ bits polluted for SImode
@ 2023-12-24  0:49 Roger Sayle
  2023-12-24  5:38 ` Jeff Law
  2023-12-24  8:29 ` YunQiang Su
  0 siblings, 2 replies; 16+ messages in thread
From: Roger Sayle @ 2023-12-24  0:49 UTC (permalink / raw)
  To: gcc-patches, 'YunQiang Su'; +Cc: 'Jeff Law'


Hi YunQiang (and Jeff),

> MIPS claims TRULY_NOOP_TRUNCATION_MODES_P (DImode, SImode)) == true
> based on that the hard register is always sign-extended, but here
> the hard register is polluted by zero_extract.

I suspect that the bug here is that the MIPS backend shouldn't be returning
true for TRULY_NOOP_TRUNCATION_MODES_P (DImode, SImode).   It's true
that the backend stores SImode values in DImode registers by sign extending
them, but this doesn't mean that any DImode pseudo register can be truncated
to an SImode pseudo just by SUBREG/register naming.  As you point out, if
the
high bits of a DImode value are random, truncation isn't a no-op, and
requires
an explicit sign-extension instruction.

There's a PR in Bugzilla around this representational issue on MIPS, but I
can't find it straight away.

Out of curiosity, how badly affected is the testsuite if mips.cc's
mips_truly_noop_truncation (poly_uint64 outprec, poly_uint64 inprec)
is changed to just return !TARGET_64BIT ?

I agree with Jeff there's an invariant that isn't correctly being modelled
by
the MIPS machine description.  A machine description probably shouldn't
define an addsi3  pattern if what it actually supports is
(sign_extend:DI (truncate:SI (plus:DI (reg:DI x) (reg:DI y))))
Trying to model this as SImode addition plus a SUBREG_PROMOTED flag
is less than ideal.

Just my thoughts.  I'm curious what other folks think.

Cheers,
Roger
--



^ permalink raw reply	[flat|nested] 16+ messages in thread
* [PATCH v3] EXPR: Emit an truncate if 31+ bits polluted for SImode
@ 2023-12-23  8:58 YunQiang Su
  2023-12-23 16:51 ` Jeff Law
  2024-01-03 23:39 ` Richard Sandiford
  0 siblings, 2 replies; 16+ messages in thread
From: YunQiang Su @ 2023-12-23  8:58 UTC (permalink / raw)
  To: gcc-patches
  Cc: richard.sandiford, pinskia, jeffreyalaw, rguenther, YunQiang Su

On TRULY_NOOP_TRUNCATION_MODES_P (DImode, SImode)) == true platforms,
if 31 or above bits is polluted by an bitops, we will need an
truncate. Let's emit one, and mark let's use the same hardreg
as in and out, the RTL may like:

(insn 21 20 24 2 (set (subreg/s/u:SI (reg/v:DI 200 [ val ]) 0)
        (truncate:SI (reg/v:DI 200 [ val ]))) "../xx.c":7:29 -1
     (nil))

We use /s/u flags to mark it as really needed, as in
combine_simplify_rtx, this insn may be considered as truncated,
so let's skip this combination.

gcc/ChangeLog:
        PR: 104914.
        * combine.cc (try_combine): Skip combine with truncate if
	dest is subreg and has /u/s flags on platforms
	TRULY_NOOP_TRUNCATION_MODES_P (DImode, SImode)) == true.
	* expr.cc (expand_assignment): Emit a truncate insn, if
	31+ bits is polluted for SImode.

gcc/testsuite/ChangeLog:
	PR: 104914.
	* gcc.target/mips/pr104914.c: New testcase.
---
 gcc/combine.cc                           | 23 +++++++++++++++++++++-
 gcc/expr.cc                              | 17 ++++++++++++++++
 gcc/testsuite/gcc.target/mips/pr104914.c | 25 ++++++++++++++++++++++++
 3 files changed, 64 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.target/mips/pr104914.c

diff --git a/gcc/combine.cc b/gcc/combine.cc
index 1cda4dd57f2..04b9c414053 100644
--- a/gcc/combine.cc
+++ b/gcc/combine.cc
@@ -3294,6 +3294,28 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
       n_occurrences = 0;		/* `subst' counts here */
       subst_low_luid = DF_INSN_LUID (i2);
 
+      /* Don't try to combine a TRUNCATE INSN, if it's DEST is SUBREG and has
+	 FLAG /s/u.  We use these 2 flags to mark this INSN as really needed:
+	 normally, it means that the bits of 31+ of this variable is polluted
+	 by a bitops.  The reason of existing of case (subreg:SI (reg:DI)) is
+	 that, the same hardreg may act as src and dest.  */
+      if (TRULY_NOOP_TRUNCATION_MODES_P (DImode, SImode)
+	  && INSN_P (i2))
+	{
+	  rtx i2dest_o = SET_DEST (PATTERN (i2));
+	  rtx i2src_o = SET_SRC (PATTERN (i2));
+	  if (GET_CODE (i2dest_o) == SUBREG
+	      && GET_MODE (i2dest_o) == SImode
+	      && GET_MODE (SUBREG_REG (i2dest_o)) == DImode
+	      && SUBREG_PROMOTED_VAR_P (i2dest_o)
+	      && SUBREG_PROMOTED_GET (i2dest_o) == SRP_SIGNED
+	      && GET_CODE (i2src_o) == TRUNCATE
+	      && GET_MODE (i2src_o) == SImode
+	      && rtx_equal_p (SUBREG_REG (i2dest_o), XEXP (i2src_o, 0))
+	      )
+	    return 0;
+	}
+
       /* If I1 feeds into I2 and I1DEST is in I1SRC, we need to make a unique
 	 copy of I2SRC each time we substitute it, in order to avoid creating
 	 self-referential RTL when we will be substituting I1SRC for I1DEST
@@ -5326,7 +5348,6 @@ find_split_point (rtx *loc, rtx_insn *insn, bool set_src)
 
    UNIQUE_COPY is true if each substitution must be unique.  We do this
    by copying if `n_occurrences' is nonzero.  */
-
 static rtx
 subst (rtx x, rtx from, rtx to, bool in_dest, bool in_cond, bool unique_copy)
 {
diff --git a/gcc/expr.cc b/gcc/expr.cc
index 9fef2bf6585..f7236040a34 100644
--- a/gcc/expr.cc
+++ b/gcc/expr.cc
@@ -6284,6 +6284,23 @@ expand_assignment (tree to, tree from, bool nontemporal)
 					nontemporal, reversep);
 		  convert_move (SUBREG_REG (to_rtx), to_rtx1,
 				SUBREG_PROMOTED_SIGN (to_rtx));
+
+		  rtx last = get_last_insn ();
+		  if (TRULY_NOOP_TRUNCATION_MODES_P (DImode, SImode)
+		      && known_ge (bitregion_end, 31)
+		      && SUBREG_PROMOTED_VAR_P (to_rtx)
+		      && SUBREG_PROMOTED_SIGN (to_rtx) == SRP_SIGNED
+		      && GET_MODE (to_rtx) == SImode
+		      && GET_MODE (SUBREG_REG (to_rtx)) == DImode
+		      && GET_CODE (SET_SRC (PATTERN (last))) == SIGN_EXTEND
+		      )
+		    {
+		      insn_code icode = convert_optab_handler
+						(trunc_optab, SImode, DImode);
+		      if (icode != CODE_FOR_nothing)
+			emit_unop_insn (icode, to_rtx,
+					SUBREG_REG (to_rtx), TRUNCATE);
+		    }
 		}
 	    }
 	  else
diff --git a/gcc/testsuite/gcc.target/mips/pr104914.c b/gcc/testsuite/gcc.target/mips/pr104914.c
new file mode 100644
index 00000000000..5dd10e84c17
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/pr104914.c
@@ -0,0 +1,25 @@
+/* { dg-do run } */
+/* { dg-options "-mabi=64" } */
+
+extern void abort (void);
+extern void exit (int);
+
+NOMIPS16 int test (const unsigned char *buf)
+{
+  int val;
+  ((unsigned char*)&val)[0] = *buf++;
+  ((unsigned char*)&val)[1] = *buf++;
+  ((unsigned char*)&val)[2] = *buf++;
+  ((unsigned char*)&val)[3] = *buf++;
+  if(val > 0)
+    return 1;
+  else
+    return 0;
+}
+
+int main ()
+{
+  if (test("\xff\xff\xff\xff") != 0)
+    abort();
+  exit(0);
+}
-- 
2.39.2


^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2024-01-09 18:49 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-12-24  0:49 [PATCH v3] EXPR: Emit an truncate if 31+ bits polluted for SImode Roger Sayle
2023-12-24  5:38 ` Jeff Law
2023-12-24  8:51   ` Roger Sayle
2023-12-24  9:15     ` YunQiang Su
2023-12-24  9:28       ` Andrew Pinski
2023-12-24 12:24       ` Roger Sayle
2023-12-28 18:26         ` Jeff Law
2023-12-24  8:29 ` YunQiang Su
  -- strict thread matches above, loose matches on Subject: below --
2023-12-23  8:58 YunQiang Su
2023-12-23 16:51 ` Jeff Law
2023-12-23 22:46   ` YunQiang Su
2023-12-24  5:27     ` Jeff Law
2023-12-24  8:11       ` YunQiang Su
2023-12-28 18:11         ` Jeff Law
2024-01-03 23:39 ` Richard Sandiford
2024-01-09 18:49   ` Jeff Law

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).