diff mbox series

[v3,4/4] ree: Using ABI interfaces to improve ree pass for rs6000 target.

Message ID d80335eb-9436-fe77-dca4-fbb02d3d688d@linux.ibm.com
State New
Headers show
Series [v3,1/4] ree: Default ree pass for O2 and above for rs6000 target. | expand

Commit Message

Ajit Agarwal April 19, 2023, 6:03 p.m. UTC
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  <aagarwa1@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

Comments

Jeff Law April 19, 2023, 9:59 p.m. UTC | #1
On 4/19/23 12:03, Ajit Agarwal wrote:
> 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  <aagarwa1@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
So my general comment on this code is we need to expose properties of 
the ABI so they can be queried.  ie, just because you found that a REGNO 
happens to be a function argument doesn't mean you know anything about 
its extension status.   We need a way to describe the extension property 
of the ABI.  Ideally there'll be something pre-existing that we can 
query, but I'm not sure that's the case.

The overarching point is what you're doing is highly dependent on the 
precise semantics of the ABI.  But nowhere do you ask the question "does 
the ABI mandate a particular sign/zero extension state for this 
argument?"  So it's just wrong as-written as far as I can tell.

Jeff
Ajit Agarwal April 22, 2023, 1:47 p.m. UTC | #2
Hello Jeff:

On 20/04/23 3:29 am, Jeff Law wrote:
> 
> 
> On 4/19/23 12:03, Ajit Agarwal wrote:
>> 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  <aagarwa1@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
> So my general comment on this code is we need to expose properties of the ABI so they can be queried.  ie, just because you found that a REGNO happens to be a function argument doesn't mean you know anything about its extension status.   We need a way to describe the extension property of the ABI.  Ideally there'll be something pre-existing that we can query, but I'm not sure that's the case.
> 
> The overarching point is what you're doing is highly dependent on the precise semantics of the ABI.  But nowhere do you ask the question "does the ABI mandate a particular sign/zero extension state for this argument?"  So it's just wrong as-written as far as I can tell.
>

I have submitted new version of the patch which incorporates the above. Please review and let me know your feedback.

Thanks & Regards
Ajit
 
> Jeff
>
diff mbox series

Patch

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