[PATCH] fwprop: Fix single_use_p calculation
Ilya Leoshkevich
iii@linux.ibm.com
Tue Mar 2 22:37:26 GMT 2021
Bootstrapped and regtested on x86_64-redhat-linux, ppc64le-redhat-linux
and s390x-redhat-linux. Ok for master?
Commit efb6bc55a93a ("fwprop: Allow (subreg (mem)) simplifications")
introduced a check that was supposed to look at the propagated def's
number of uses. It uses insn_info::num_uses (), which in reality
returns the number of uses def's insn has. The whole change therefore
works only by accident.
Fix by looking at def_info's uses instead of insn_info's uses. This
requires passing around def_info instead of insn_info.
gcc/ChangeLog:
2021-03-02 Ilya Leoshkevich <iii@linux.ibm.com>
* fwprop.c (def_has_single_use_p): New function.
(fwprop_propagation::fwprop_propagation): Look at
def_info's uses.
(try_fwprop_subst_note): Use def_info instead of insn_info.
(try_fwprop_subst_pattern): Likewise.
(try_fwprop_subst_notes): Likewise.
(try_fwprop_subst): Likewise.
(forward_propagate_subreg): Likewise.
(forward_propagate_and_simplify): Likewise.
(forward_propagate_into): Likewise.
* iterator-utils.h (single_element_p): New function.
---
gcc/fwprop.c | 89 ++++++++++++++++++++++++++------------------
gcc/iterator-utils.h | 10 +++++
2 files changed, 62 insertions(+), 37 deletions(-)
diff --git a/gcc/fwprop.c b/gcc/fwprop.c
index 4b8a554e823..478dcdd96cc 100644
--- a/gcc/fwprop.c
+++ b/gcc/fwprop.c
@@ -175,7 +175,7 @@ namespace
static const uint16_t CONSTANT = FIRST_SPARE_RESULT << 1;
static const uint16_t PROFITABLE = FIRST_SPARE_RESULT << 2;
- fwprop_propagation (insn_info *, insn_info *, rtx, rtx);
+ fwprop_propagation (insn_info *, def_info *, rtx, rtx);
bool changed_mem_p () const { return result_flags & CHANGED_MEM; }
bool folded_to_constants_p () const;
@@ -191,13 +191,27 @@ namespace
};
}
-/* Prepare to replace FROM with TO in INSN. */
+/* Return true if DEF has a single non-debug non-phi use. */
+
+static bool
+def_has_single_use_p (def_info *def)
+{
+ if (!is_a<set_info *> (def))
+ return false;
+
+ set_info *set = as_a<set_info *> (def);
+
+ return single_element_p (set->nondebug_insn_uses ())
+ && !set->has_phi_uses ();
+}
+
+/* Prepare to replace FROM with TO in USE_INSN. */
fwprop_propagation::fwprop_propagation (insn_info *use_insn,
- insn_info *def_insn, rtx from, rtx to)
+ def_info *def, rtx from, rtx to)
: insn_propagation (use_insn->rtl (), from, to),
- single_use_p (def_insn->num_uses () == 1),
- single_ebb_p (use_insn->ebb () == def_insn->ebb ())
+ single_use_p (def_has_single_use_p (def)),
+ single_ebb_p (use_insn->ebb () == def->insn ()->ebb ())
{
should_check_mems = true;
should_note_simplifications = true;
@@ -368,9 +382,9 @@ contains_paradoxical_subreg_p (rtx x)
return false;
}
-/* Try to substitute (set DEST SRC) from DEF_INSN into note NOTE of USE_INSN.
- Return the number of substitutions on success, otherwise return -1 and
- leave USE_INSN unchanged.
+/* Try to substitute (set DEST SRC), which defines DEF, into note NOTE of
+ USE_INSN. Return the number of substitutions on success, otherwise return
+ -1 and leave USE_INSN unchanged.
If REQUIRE_CONSTANT is true, require all substituted occurences of SRC
to fold to a constant, so that the note does not use any more registers
@@ -379,13 +393,14 @@ contains_paradoxical_subreg_p (rtx x)
instruction pattern. */
static int
-try_fwprop_subst_note (insn_info *use_insn, insn_info *def_insn,
+try_fwprop_subst_note (insn_info *use_insn, def_info *def,
rtx note, rtx dest, rtx src, bool require_constant)
{
rtx_insn *use_rtl = use_insn->rtl ();
+ insn_info *def_insn = def->insn ();
insn_change_watermark watermark;
- fwprop_propagation prop (use_insn, def_insn, dest, src);
+ fwprop_propagation prop (use_insn, def, dest, src);
if (!prop.apply_to_rvalue (&XEXP (note, 0)))
{
if (dump_file && (dump_flags & TDF_DETAILS))
@@ -436,19 +451,20 @@ try_fwprop_subst_note (insn_info *use_insn, insn_info *def_insn,
return prop.num_replacements;
}
-/* Try to substitute (set DEST SRC) from DEF_INSN into location LOC of
+/* Try to substitute (set DEST SRC), which defines DEF, into location LOC of
USE_INSN's pattern. Return true on success, otherwise leave USE_INSN
unchanged. */
static bool
try_fwprop_subst_pattern (obstack_watermark &attempt, insn_change &use_change,
- insn_info *def_insn, rtx *loc, rtx dest, rtx src)
+ def_info *def, rtx *loc, rtx dest, rtx src)
{
insn_info *use_insn = use_change.insn ();
rtx_insn *use_rtl = use_insn->rtl ();
+ insn_info *def_insn = def->insn ();
insn_change_watermark watermark;
- fwprop_propagation prop (use_insn, def_insn, dest, src);
+ fwprop_propagation prop (use_insn, def, dest, src);
if (!prop.apply_to_pattern (loc))
{
if (dump_file && (dump_flags & TDF_DETAILS))
@@ -538,7 +554,7 @@ try_fwprop_subst_pattern (obstack_watermark &attempt, insn_change &use_change,
{
if ((REG_NOTE_KIND (note) == REG_EQUAL
|| REG_NOTE_KIND (note) == REG_EQUIV)
- && try_fwprop_subst_note (use_insn, def_insn, note,
+ && try_fwprop_subst_note (use_insn, def, note,
dest, src, false) < 0)
{
*note_ptr = XEXP (note, 1);
@@ -554,19 +570,19 @@ try_fwprop_subst_pattern (obstack_watermark &attempt, insn_change &use_change,
return true;
}
-/* Try to substitute (set DEST SRC) from DEF_INSN into USE_INSN's notes,
+/* Try to substitute (set DEST SRC), which defines DEF, into USE_INSN's notes,
given that it was not possible to do this for USE_INSN's main pattern.
Return true on success, otherwise leave USE_INSN unchanged. */
static bool
-try_fwprop_subst_notes (insn_info *use_insn, insn_info *def_insn,
+try_fwprop_subst_notes (insn_info *use_insn, def_info *def,
rtx dest, rtx src)
{
rtx_insn *use_rtl = use_insn->rtl ();
for (rtx note = REG_NOTES (use_rtl); note; note = XEXP (note, 1))
if ((REG_NOTE_KIND (note) == REG_EQUAL
|| REG_NOTE_KIND (note) == REG_EQUIV)
- && try_fwprop_subst_note (use_insn, def_insn, note,
+ && try_fwprop_subst_note (use_insn, def, note,
dest, src, true) > 0)
{
confirm_change_group ();
@@ -576,7 +592,7 @@ try_fwprop_subst_notes (insn_info *use_insn, insn_info *def_insn,
return false;
}
-/* Check whether we could validly substitute (set DEST SRC) from DEF_INSN
+/* Check whether we could validly substitute (set DEST SRC), which defines DEF,
into USE. If so, first try performing the substitution in location LOC
of USE->insn ()'s pattern. If that fails, try instead to substitute
into the notes.
@@ -584,10 +600,11 @@ try_fwprop_subst_notes (insn_info *use_insn, insn_info *def_insn,
Return true on success, otherwise leave USE_INSN unchanged. */
static bool
-try_fwprop_subst (use_info *use, insn_info *def_insn,
+try_fwprop_subst (use_info *use, def_info *def,
rtx *loc, rtx dest, rtx src)
{
insn_info *use_insn = use->insn ();
+ insn_info *def_insn = def->insn ();
auto attempt = crtl->ssa->new_change_attempt ();
use_array src_uses = remove_note_accesses (attempt, def_insn->uses ());
@@ -622,9 +639,8 @@ try_fwprop_subst (use_info *use, insn_info *def_insn,
if (!restrict_movement (use_change))
return false;
- return (try_fwprop_subst_pattern (attempt, use_change, def_insn,
- loc, dest, src)
- || try_fwprop_subst_notes (use_insn, def_insn, dest, src));
+ return (try_fwprop_subst_pattern (attempt, use_change, def, loc, dest, src)
+ || try_fwprop_subst_notes (use_insn, def, dest, src));
}
/* For the given single_set INSN, containing SRC known to be a
@@ -671,7 +687,7 @@ free_load_extend (rtx src, insn_info *insn)
in REF. The other parameters are the same. */
static bool
-forward_propagate_subreg (use_info *use, insn_info *def_insn,
+forward_propagate_subreg (use_info *use, def_info *def,
rtx dest, rtx src, df_ref ref)
{
scalar_int_mode int_use_mode, src_mode;
@@ -697,8 +713,7 @@ forward_propagate_subreg (use_info *use, insn_info *def_insn,
&& REGNO (SUBREG_REG (src)) >= FIRST_PSEUDO_REGISTER
&& GET_MODE (SUBREG_REG (src)) == use_mode
&& subreg_lowpart_p (src))
- return try_fwprop_subst (use, def_insn, loc,
- use_reg, SUBREG_REG (src));
+ return try_fwprop_subst (use, def, loc, use_reg, SUBREG_REG (src));
}
/* If this is a SUBREG of a ZERO_EXTEND or SIGN_EXTEND, and the SUBREG
@@ -725,22 +740,21 @@ forward_propagate_subreg (use_info *use, insn_info *def_insn,
&& 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_load_extend (src, def->insn ())
&& (targetm.mode_rep_extended (int_use_mode, src_mode)
!= (int) GET_CODE (src)))
- return try_fwprop_subst (use, def_insn, loc, use_reg, XEXP (src, 0));
+ return try_fwprop_subst (use, def, loc, use_reg, XEXP (src, 0));
}
return false;
}
-/* Try to substitute (set DEST SRC) from DEF_INSN into USE and simplify
+/* Try to substitute (set DEST SRC), which defines DEF, into USE and simplify
the result, handling cases where DEST is used in a subreg and where
applying that subreg to SRC results in a useful simplification. */
static bool
-forward_propagate_subreg (use_info *use, insn_info *def_insn,
- rtx dest, rtx src)
+forward_propagate_subreg (use_info *use, def_info *def, rtx dest, rtx src)
{
if (!use->includes_subregs () || !REG_P (dest))
return false;
@@ -755,26 +769,27 @@ forward_propagate_subreg (use_info *use, insn_info *def_insn,
FOR_EACH_INSN_USE (ref, use_rtl)
if (DF_REF_REGNO (ref) == use->regno ()
- && forward_propagate_subreg (use, def_insn, dest, src, ref))
+ && forward_propagate_subreg (use, def, dest, src, ref))
return true;
FOR_EACH_INSN_EQ_USE (ref, use_rtl)
if (DF_REF_REGNO (ref) == use->regno ()
- && forward_propagate_subreg (use, def_insn, dest, src, ref))
+ && forward_propagate_subreg (use, def, dest, src, ref))
return true;
return false;
}
-/* Try to substitute (set DEST SRC) from DEF_INSN into USE and
+/* Try to substitute (set DEST SRC), which defines DEF, into USE and
simplify the result. */
static bool
-forward_propagate_and_simplify (use_info *use, insn_info *def_insn,
+forward_propagate_and_simplify (use_info *use, def_info *def,
rtx dest, rtx src)
{
insn_info *use_insn = use->insn ();
rtx_insn *use_rtl = use_insn->rtl ();
+ insn_info *def_insn = def->insn ();
/* ??? This check seems unnecessary. We should be able to propagate
into any kind of instruction, regardless of whether it's a single set.
@@ -820,7 +835,7 @@ forward_propagate_and_simplify (use_info *use, insn_info *def_insn,
/* ??? Unconditionally propagating into PATTERN would work better
for instructions that have match_dups. */
rtx *loc = need_single_set ? &use_set : &PATTERN (use_rtl);
- return try_fwprop_subst (use, def_insn, loc, dest, src);
+ return try_fwprop_subst (use, def, loc, dest, src);
}
/* Given a use USE of an insn, if it has a single reaching
@@ -880,8 +895,8 @@ forward_propagate_into (use_info *use, bool reg_prop_only = false)
&& find_reg_note (use_rtl, REG_NON_LOCAL_GOTO, NULL_RTX))
return false;
- if (forward_propagate_and_simplify (use, def_insn, dest, src)
- || forward_propagate_subreg (use, def_insn, dest, src))
+ if (forward_propagate_and_simplify (use, def, dest, src)
+ || forward_propagate_subreg (use, def, dest, src))
return true;
return false;
diff --git a/gcc/iterator-utils.h b/gcc/iterator-utils.h
index a02dfcc3c8f..01a7d5c947e 100644
--- a/gcc/iterator-utils.h
+++ b/gcc/iterator-utils.h
@@ -200,4 +200,14 @@ list_iterator<T, Next>::operator++ (int)
return ret;
}
+// Return true if CONTAINER has precisely one element.
+template <typename T>
+bool
+single_element_p (const T &container)
+{
+ auto it = container.begin ();
+ auto end = container.end ();
+ return it != end && ++it == end;
+}
+
#endif
--
2.29.2
More information about the Gcc-patches
mailing list