diff mbox series

[PATCH-1v4] fwprop: Replace rtx_cost with insn_cost in try_fwprop_subst_pattern [PR113325]

Message ID bf333060-92d2-48e7-ab6b-0e56d9e868ec@linux.ibm.com
State New
Headers show
Series [PATCH-1v4] fwprop: Replace rtx_cost with insn_cost in try_fwprop_subst_pattern [PR113325] | expand

Commit Message

HAO CHEN GUI June 17, 2024, 8:58 a.m. UTC
Hi,
  This patch replaces rtx_cost with insn_cost in forward propagation.
In the PR, one constant vector should be propagated and replace a
pseudo in a store insn if we know it's a duplicated constant vector.
It reduces the insn cost but not rtx cost. In this case, the cost is
determined by destination operand (memory or pseudo). Unfortunately,
rtx cost can't help.

  The test case is added in the second rs6000 specific patch.

  Compared to previous version, the main changes are:
1. Invalidate recog_data when the cached INSN is swapped out.
2. Pass strict_p according to prop.likely_profitable_p () to
change_is_worthwhile.

Previous version
https://gcc.gnu.org/pipermail/gcc-patches/2024-June/654276.html


  The patch causes a regression cases on i386 as the pattern cost
regulation has a bug. Please refer the patch and discussion here.
https://gcc.gnu.org/pipermail/gcc-patches/2024-May/651363.html

  Bootstrapped and tested on powerpc64-linux BE and LE with no
regressions. Is it OK for the trunk?

ChangeLog
fwprop: invoke change_is_worthwhile to judge if a replacement is worthwhile

gcc/
	* fwprop.cc (try_fwprop_subst_pattern): Invoke change_is_worthwhile
	to judge if a replacement is worthwhile.
	* recog.cc (swap_change): Invalidate recog_data when the cached INSN
	is swapped out.
	* rtl-ssa/changes.cc (rtl_ssa::changes_are_worthwhile): Check if the
	insn cost of new rtl is unknown and fail the replacement.

patch.diff

Comments

HAO CHEN GUI June 18, 2024, 9:26 a.m. UTC | #1
Hi Richard,

在 2024/6/17 17:04, Richard Sandiford 写道:
> I don't think we should keep the single_set condition after this change.
> insn_cost can handle all instructions.

Just tested with removing single_set condition. It causes some regressions.
If the new_rtl is a debug insn, it still can do the replacement as it can
be recog and it's not a single_set rtl. After removing single_set condition,
the "ok" (recog) will be reset to false in the "if" block as the cost of
debug insn is unknown. So the replacement won't be done.

  bool ok = recog (attempt, use_change);
  if (ok && !prop.changed_mem_p () && !use_insn->is_asm ())
    {
      bool strict_p = !prop.likely_profitable_p ();
      if (!change_is_worthwhile (use_change, strict_p))
        {
          if (dump_file)
            fprintf (dump_file, "change not profitable");
          ok = false;
        }
    }

  if (!ok)
    {
      /* The pattern didn't match, but if all uses of SRC folded to
         constants, we can add a REG_EQUAL note for the result, if there
         isn't one already.  */
      if (!prop.folded_to_constants_p ())

  Looking forwarding to your advice.

Thanks
Gui Haochen
Richard Sandiford June 18, 2024, 8:12 p.m. UTC | #2
HAO CHEN GUI <guihaoc@linux.ibm.com> writes:
> Hi Richard,
>
> 在 2024/6/17 17:04, Richard Sandiford 写道:
>> I don't think we should keep the single_set condition after this change.
>> insn_cost can handle all instructions.
>
> Just tested with removing single_set condition. It causes some regressions.
> If the new_rtl is a debug insn, it still can do the replacement as it can
> be recog and it's not a single_set rtl. After removing single_set condition,
> the "ok" (recog) will be reset to false in the "if" block as the cost of
> debug insn is unknown. So the replacement won't be done.
>
>   bool ok = recog (attempt, use_change);
>   if (ok && !prop.changed_mem_p () && !use_insn->is_asm ())
>     {
>       bool strict_p = !prop.likely_profitable_p ();
>       if (!change_is_worthwhile (use_change, strict_p))
>         {
>           if (dump_file)
>             fprintf (dump_file, "change not profitable");
>           ok = false;
>         }
>     }
>
>   if (!ok)
>     {
>       /* The pattern didn't match, but if all uses of SRC folded to
>          constants, we can add a REG_EQUAL note for the result, if there
>          isn't one already.  */
>       if (!prop.folded_to_constants_p ())

We shouldn't be trying to cost changes to debug insns, so I think
the extra condition should be !use_insn->is_debug_insn ().

Thanks,
Richard
diff mbox series

Patch

diff --git a/gcc/fwprop.cc b/gcc/fwprop.cc
index de543923b92..4a9f68b66b1 100644
--- a/gcc/fwprop.cc
+++ b/gcc/fwprop.cc
@@ -471,29 +471,18 @@  try_fwprop_subst_pattern (obstack_watermark &attempt, insn_change &use_change,
       redo_changes (0);
     }

-  /* ??? In theory, it should be better to use insn costs rather than
-     set_src_costs here.  That would involve replacing this code with
-     change_is_worthwhile.  */
   bool ok = recog (attempt, use_change);
-  if (ok && !prop.changed_mem_p () && !use_insn->is_asm ())
-    if (rtx use_set = single_set (use_rtl))
-      {
-	bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (use_rtl));
-	temporarily_undo_changes (0);
-	auto old_cost = set_src_cost (SET_SRC (use_set),
-				      GET_MODE (SET_DEST (use_set)), speed);
-	redo_changes (0);
-	auto new_cost = set_src_cost (SET_SRC (use_set),
-				      GET_MODE (SET_DEST (use_set)), speed);
-	if (new_cost > old_cost
-	    || (new_cost == old_cost && !prop.likely_profitable_p ()))
-	  {
-	    if (dump_file)
-	      fprintf (dump_file, "change not profitable"
-		       " (cost %d -> cost %d)\n", old_cost, new_cost);
-	    ok = false;
-	  }
-      }
+  if (ok && !prop.changed_mem_p () && !use_insn->is_asm ()
+      && single_set (use_rtl))
+    {
+      bool strict_p = !prop.likely_profitable_p ();
+      if (!change_is_worthwhile (use_change, strict_p))
+	{
+	  if (dump_file)
+	    fprintf (dump_file, "change not profitable");
+	  ok = false;
+	}
+    }

   if (!ok)
     {
diff --git a/gcc/recog.cc b/gcc/recog.cc
index a6799e3f5e6..56370e40e01 100644
--- a/gcc/recog.cc
+++ b/gcc/recog.cc
@@ -614,7 +614,11 @@  swap_change (int num)
   else
     std::swap (*changes[num].loc, changes[num].old);
   if (changes[num].object && !MEM_P (changes[num].object))
-    std::swap (INSN_CODE (changes[num].object), changes[num].old_code);
+    {
+      std::swap (INSN_CODE (changes[num].object), changes[num].old_code);
+      if (recog_data.insn == changes[num].object)
+	recog_data.insn = nullptr;
+    }
 }

 /* Temporarily undo all the changes numbered NUM and up, with a view
diff --git a/gcc/rtl-ssa/changes.cc b/gcc/rtl-ssa/changes.cc
index 11639e81bb7..c5ac4956a19 100644
--- a/gcc/rtl-ssa/changes.cc
+++ b/gcc/rtl-ssa/changes.cc
@@ -186,6 +186,14 @@  rtl_ssa::changes_are_worthwhile (array_slice<insn_change *const> changes,
       if (!change->is_deletion ())
 	{
 	  change->new_cost = insn_cost (change->rtl (), for_speed);
+	  /* If the cost is unknown, replacement is not worthwhile.  */
+	  if (!change->new_cost)
+	    {
+	      if (dump_file && (dump_flags & TDF_DETAILS))
+		fprintf (dump_file,
+			 "Reject replacement due to unknown insn cost.\n");
+	      return false;
+	    }
 	  new_cost += change->new_cost;
 	  if (for_speed)
 	    weighted_new_cost += (cfg_bb->count.to_sreal_scale (entry_count)