[46/61] nanoMIPS: unnecessary AND following an EXT

Message ID 20250131171232.1018281-48-aleksandar.rakic@htecgroup.com
State New
Headers
Series Improve Mips target |

Commit Message

Aleksandar Rakic Jan. 31, 2025, 5:13 p.m. UTC
  From: "dragan.mladjenovic" <dragan.mladjenovic@rt-rk.com>

The fwprop1 introduces a new use of Y by replacing the
(subreg:QI (reg:SI X)) with (reg:QI Y) preventing the optimization of
zero_extend later during the combine. This patch prevents this
replacement in two new cases.

     A: (set (subreg:SI (reg:QI Y))
             (zero_extract:SI Z (const_int 8) (const_int ?)))
     B: (set (reg:SI X) (zero_extend:SI (reg:QI Y)))
     C: (... (subreg:QI (reg:SI X)) ...)
     D: (... (reg:SI X) ...)

     A: (set (reg:SI Y)
             (zero_extract:SI Z (const_int 8) (const_int ?)))
     B: (set (reg:SI X) (zero_extend:SI (reg:QI Y)))
     C: (... (subreg:QI (reg:SI X)) ...)
     D: (... (reg:SI X) ...)

gcc/

    * fwprop.cc (free_load_extend): Renamed to ...
      (free_extend): Handle zero/sign_extract sources.
      (forward_propagate_subreg): Use free_extend.

gcc/testsuite/

    * gcc.target/mips/union-zext.c: New.

Cherry-picked a76808b917661f102d4b5f6256f76a1a1e580676
from https://github.com/MIPS/gcc

Signed-off-by: Dragan Mladjenovic <dragan.mladjenovic@rt-rk.com>
Signed-off-by: Faraz Shahbazker <fshahbazker@wavecomp.com>
Signed-off-by: Aleksandar Rakic <aleksandar.rakic@htecgroup.com>
---
 gcc/fwprop.cc                              | 38 ++++++++++++++++++----
 gcc/testsuite/gcc.target/mips/union-zext.c | 29 +++++++++++++++++
 2 files changed, 60 insertions(+), 7 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/mips/union-zext.c
  

Patch

diff --git a/gcc/fwprop.cc b/gcc/fwprop.cc
index 8cba6b7ce9f..717415a4fb6 100644
--- a/gcc/fwprop.cc
+++ b/gcc/fwprop.cc
@@ -614,15 +614,14 @@  try_fwprop_subst (use_info *use, set_info *def,
 
 /* For the given single_set INSN, containing SRC known to be a
    ZERO_EXTEND or SIGN_EXTEND of a register, return true if INSN
-   is redundant due to the register being set by a LOAD_EXTEND_OP
-   load from memory.  */
+   is redundant due to the register being set by ZERO_EXTRACT or
+   SIGN_EXTRACT of appropriate size or by LOAD_EXTEND_OP load
+   from memory.  */
 
 static bool
-free_load_extend (rtx src, insn_info *insn)
+free_extend (rtx src, insn_info *insn)
 {
   rtx reg = XEXP (src, 0);
-  if (load_extend_op (GET_MODE (reg)) != GET_CODE (src))
-    return false;
 
   def_info *def = nullptr;
   for (use_info *use : insn->uses ())
@@ -644,10 +643,35 @@  free_load_extend (rtx src, insn_info *insn)
     {
       rtx patt = PATTERN (def_rtl);
 
-      if (GET_CODE (patt) == SET
+      if (GET_CODE (patt) != SET)
+  return false;
+
+#ifdef LOAD_EXTEND_OP
+      if (LOAD_EXTEND_OP (GET_MODE (reg)) == GET_CODE (src)
 	  && GET_CODE (SET_SRC (patt)) == MEM
 	  && rtx_equal_p (SET_DEST (patt), reg))
 	return true;
+#endif
+
+      int extract_code = GET_CODE (src) == ZERO_EXTEND
+    ? ZERO_EXTRACT : SIGN_EXTRACT;
+
+      if (GET_CODE (SET_SRC (patt)) == extract_code
+    && GET_MODE (SET_SRC (patt)) == GET_MODE (src)
+	  && INTVAL (XEXP (SET_SRC (patt), 1))
+	     <= GET_MODE_BITSIZE (GET_MODE (reg)).to_constant ())
+  {
+    if (GET_CODE (SET_DEST (patt)) == SUBREG
+      && GET_MODE (SET_DEST (patt)) == GET_MODE (src)
+      && rtx_equal_p (XEXP (SET_DEST (patt), 0), reg))
+      return true;
+
+    if (REG_P (SET_DEST (patt))
+      && GET_MODE (SET_DEST (patt)) == GET_MODE (src)
+      && REGNO (SET_DEST (patt)) == REGNO (reg))
+      return true;
+  }
+
     }
   return false;
 }
@@ -709,7 +733,7 @@  forward_propagate_subreg (use_info *use, set_info *def,
 	  && REG_P (XEXP (src, 0))
 	  && REGNO (XEXP (src, 0)) >= FIRST_PSEUDO_REGISTER
 	  && GET_MODE (XEXP (src, 0)) == use_mode
-	  && !free_load_extend (src, def->insn ())
+	  && !free_extend (src, def->insn ())
 	  && (targetm.mode_rep_extended (int_use_mode, src_mode)
 	      != (int) GET_CODE (src)))
 	return try_fwprop_subst (use, def, loc, use_reg, XEXP (src, 0));
diff --git a/gcc/testsuite/gcc.target/mips/union-zext.c b/gcc/testsuite/gcc.target/mips/union-zext.c
new file mode 100644
index 00000000000..6728d415f5a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/union-zext.c
@@ -0,0 +1,29 @@ 
+/* { dg-do compile } */
+/* { dg-options "(HAS_INS) -mgp32" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+/* { dg-final { scan-assembler-not "\tandi\t"} } */
+
+typedef struct bits
+{
+  unsigned B0:8, B1:8, B2:8, B3:8;
+} bits_t;
+
+typedef union
+{
+  unsigned v;
+  bits_t b;
+} bitfields_t;
+
+void *
+strcpy (void *__restrict__ dst, const void *__restrict__ _a)
+{
+  unsigned x = *(unsigned *) _a;
+  bitfields_t bx;
+  bx.v = x;
+
+  unsigned char v2 = (unsigned char) bx.b.B2;
+  ((unsigned char *) (dst))[2] = (v2);
+  if (v2 == 0)
+    return 0;
+  return dst;
+}