Hello All:

This is patch-4 to improve ree pass for rs6000 target.
Use ABI interfaces support.

Bootstrapped and regtested on powerpc64-linux-gnu.

Thanks & Regards
Ajit

        ree: Improve ree pass for rs6000 target.

        For rs6000 target we see redundant zero and sign
        extension and done to improve ree pass to eliminate
        such redundant zero and sign extension. Support of
        ABI interfaces.

        2023-04-19  Ajit Kumar Agarwal  <aagar...@linux.ibm.com>

gcc/ChangeLog:

        * ree.cc (combline_reaching_defs): Add zero_extend and sign_extend.
        Add FUNCTION_ARG_REGNO_P abi interfaces calls and
        FUNCTION_VALUE_REGNO_P support.
        (add_removable_extension): Add FUNCTION_ARG_REGNO_P abi
        interface calls.

gcc/testsuite/ChangeLog:

        * g++.target/powerpc/zext-elim-3.C
---
 gcc/ree.cc                                    | 127 +++++++++++++-----
 .../g++.target/powerpc/zext-elim-3.C          |  16 +++
 2 files changed, 113 insertions(+), 30 deletions(-)
 create mode 100644 gcc/testsuite/g++.target/powerpc/zext-elim-3.C

diff --git a/gcc/ree.cc b/gcc/ree.cc
index 413aec7c8eb..33c803f16ce 100644
--- a/gcc/ree.cc
+++ b/gcc/ree.cc
@@ -473,7 +473,8 @@ get_defs (rtx_insn *insn, rtx reg, vec<rtx_insn *> *dest)
        break;
     }
 
-  gcc_assert (use != NULL);
+  if (use == NULL)
+    return NULL;
 
   ref_chain = DF_REF_CHAIN (use);
 
@@ -514,7 +515,8 @@ get_uses (rtx_insn *insn, rtx reg)
     if (REGNO (DF_REF_REG (def)) == REGNO (reg))
       break;
 
-  gcc_assert (def != NULL);
+  if (def == NULL)
+    return NULL;
 
   ref_chain = DF_REF_CHAIN (def);
 
@@ -771,6 +773,58 @@ combine_reaching_defs (ext_cand *cand, const_rtx set_pat, 
ext_state *state)
   state->defs_list.truncate (0);
   state->copies_list.truncate (0);
 
+  if (cand->code == ZERO_EXTEND)
+    {
+      rtx orig_src = XEXP (SET_SRC (cand->expr),0);
+      rtx set = single_set (cand->insn);
+
+      if (!set)
+       return false;
+
+      machine_mode ext_dst_mode = GET_MODE (SET_DEST (set));
+
+      if (!get_defs (cand->insn, orig_src, NULL))
+       {
+          bool copy_needed
+            = (REGNO (SET_DEST (cand->expr)) != REGNO (XEXP (SET_SRC 
(cand->expr), 0)));
+
+         if (!copy_needed && ext_dst_mode != GET_MODE (orig_src)
+             && FUNCTION_ARG_REGNO_P (REGNO (orig_src))
+             && !FUNCTION_VALUE_REGNO_P (REGNO (orig_src)))
+            {
+               if (side_effects_p (PATTERN (cand->insn)))
+                 return false;
+
+               struct df_link *uses
+                 = get_uses (cand->insn, SET_DEST (PATTERN (cand->insn)));
+
+               if (!uses) return false;
+
+               for (df_link *use = uses; use; use = use->next)
+                 {
+                   if (!use->ref)
+                     return false;
+
+                   if (BLOCK_FOR_INSN (cand->insn)
+                       != BLOCK_FOR_INSN (DF_REF_INSN (use->ref)))
+                     return false;
+
+                   rtx_insn *insn = DF_REF_INSN (use->ref);
+
+                   if (GET_CODE (PATTERN (insn)) == SET)
+                     {
+                       rtx_code code = GET_CODE (SET_SRC (PATTERN (insn)));
+                       if (GET_RTX_CLASS (code) == RTX_BIN_ARITH
+                           || GET_RTX_CLASS (code) == RTX_COMM_ARITH
+                           || GET_RTX_CLASS (code) == RTX_UNARY)
+                         return false;
+                      }
+                   }
+                return true;
+            }
+        }
+    }
+
   outcome = make_defs_and_copies_lists (cand->insn, set_pat, state);
 
   if (!outcome)
@@ -1112,26 +1166,35 @@ add_removable_extension (const_rtx expr, rtx_insn *insn,
       rtx reg = XEXP (src, 0);
       struct df_link *defs, *def;
       ext_cand *cand;
+      defs = get_defs (insn, reg, NULL);
 
       /* Zero-extension of an undefined value is partly defined (it's
         completely undefined for sign-extension, though).  So if there exists
         a path from the entry to this zero-extension that leaves this register
         uninitialized, removing the extension could change the behavior of
         correct programs.  So first, check it is not the case.  */
-      if (code == ZERO_EXTEND && !bitmap_bit_p (init_regs, REGNO (reg)))
+      if (!defs && code == ZERO_EXTEND && FUNCTION_ARG_REGNO_P (REGNO (reg)))
        {
-         if (dump_file)
-           {
-             fprintf (dump_file, "Cannot eliminate extension:\n");
-             print_rtl_single (dump_file, insn);
-             fprintf (dump_file, " because it can operate on uninitialized"
-                                 " data\n");
-           }
+         ext_cand e = {expr, code, mode, insn};
+         insn_list->safe_push (e);
          return;
        }
 
+
+       if ((code == ZERO_EXTEND
+           && !bitmap_bit_p (init_regs, REGNO (reg))))
+         {
+           if (dump_file)
+             {
+               fprintf (dump_file, "Cannot eliminate extension:\n");
+               print_rtl_single (dump_file, insn);
+               fprintf (dump_file, " because it can operate on uninitialized"
+                                   " data\n");
+             }
+           return;
+         }
+
       /* Second, make sure we can get all the reaching definitions.  */
-      defs = get_defs (insn, reg, NULL);
       if (!defs)
        {
          if (dump_file)
@@ -1321,7 +1384,8 @@ find_and_remove_re (void)
              && (REGNO (SET_DEST (set)) != REGNO (XEXP (SET_SRC (set), 0))))
            {
               reinsn_copy_list.safe_push (curr_cand->insn);
-              reinsn_copy_list.safe_push (state.defs_list[0]);
+             if (state.defs_list.length() != 0)
+               reinsn_copy_list.safe_push (state.defs_list[0]);
            }
          reinsn_del_list.safe_push (curr_cand->insn);
          state.modified[INSN_UID (curr_cand->insn)].deleted = 1;
@@ -1342,24 +1406,27 @@ find_and_remove_re (void)
      Remember that the memory reference will be changed to refer to the
      destination of the extention.  So we're actually emitting a copy
      from the new destination to the old destination.  */
-  for (unsigned int i = 0; i < reinsn_copy_list.length (); i += 2)
-    {
-      rtx_insn *curr_insn = reinsn_copy_list[i];
-      rtx_insn *def_insn = reinsn_copy_list[i + 1];
-
-      /* Use the mode of the destination of the defining insn
-        for the mode of the copy.  This is necessary if the
-        defining insn was used to eliminate a second extension
-        that was wider than the first.  */
-      rtx sub_rtx = *get_sub_rtx (def_insn);
-      rtx set = single_set (curr_insn);
-      rtx new_dst = gen_rtx_REG (GET_MODE (SET_DEST (sub_rtx)),
-                                REGNO (XEXP (SET_SRC (set), 0)));
-      rtx new_src = gen_rtx_REG (GET_MODE (SET_DEST (sub_rtx)),
-                                REGNO (SET_DEST (set)));
-      rtx new_set = gen_rtx_SET (new_dst, new_src);
-      emit_insn_after (new_set, def_insn);
-    }
+   for (unsigned int i = 0; i < reinsn_copy_list.length (); i += 2)
+     {
+       rtx_insn *curr_insn = reinsn_copy_list[i];
+
+       if ((i+1) < reinsn_copy_list.length())
+        {
+          rtx_insn *def_insn = reinsn_copy_list[i + 1];
+          /* Use the mode of the destination of the defining insn
+             for the mode of the copy.  This is necessary if the
+             defining insn was used to eliminate a second extension
+             that was wider than the first.  */
+          rtx sub_rtx = *get_sub_rtx (def_insn);
+          rtx set = single_set (curr_insn);
+          rtx new_dst = gen_rtx_REG (GET_MODE (SET_DEST (sub_rtx)),
+                                     REGNO (XEXP (SET_SRC (set), 0)));
+          rtx new_src = gen_rtx_REG (GET_MODE (SET_DEST (sub_rtx)),
+                                     REGNO (SET_DEST (set)));
+          rtx new_set = gen_rtx_SET (new_dst, new_src);
+          emit_insn_after (new_set, def_insn);
+       }
+      }
 
   /* Delete all useless extensions here in one sweep.  */
   FOR_EACH_VEC_ELT (reinsn_del_list, i, curr_insn)
diff --git a/gcc/testsuite/g++.target/powerpc/zext-elim-3.C 
b/gcc/testsuite/g++.target/powerpc/zext-elim-3.C
new file mode 100644
index 00000000000..1d443af066a
--- /dev/null
+++ b/gcc/testsuite/g++.target/powerpc/zext-elim-3.C
@@ -0,0 +1,16 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target powerpc_p9vector_ok } */
+/* { dg-options "-mcpu=power9 -O2 -free" } */
+
+void *memset(void *b, int c, unsigned long len)
+{
+  unsigned long i;
+
+  for (i = 0; i < len; i++)
+    ((unsigned char *)b)[i] = c;
+
+   return b;
+}
+
+/* { dg-final { scan-assembler-not "rlwinm" } } */
-- 
2.31.1

Reply via email to