reorg.c (fill_slots_from_thread): Improve for TARGET_FLAGS_REGNUM targets
Richard Sandiford
richard.sandiford@arm.com
Thu Aug 20 19:04:21 GMT 2020
Hans-Peter Nilsson via Gcc-patches <gcc-patches@gcc.gnu.org> writes:
>> > @@ -2411,6 +2411,21 @@ fill_slots_from_thread (rtx_jump_insn *insn, rtx condition,
>> > CLEAR_RESOURCE (&needed);
>> > CLEAR_RESOURCE (&set);
>> >
>> > + /* Handle the flags register specially, to be able to accept a
>> > + candidate that clobbers it. See also fill_simple_delay_slots. */
>> > + bool filter_flags
>> > + = (slots_to_fill == 1
>> > + && targetm.flags_regnum != INVALID_REGNUM
>> > + && find_regno_note (insn, REG_DEAD, targetm.flags_regnum));
>> > + struct resources fset;
>> > + struct resources flags_res;
>> > + if (filter_flags)
>> > + {
>> > + CLEAR_RESOURCE (&fset);
>> > + CLEAR_RESOURCE (&flags_res);
>> > + SET_HARD_REG_BIT (flags_res.regs, targetm.flags_regnum);
>> > + }
>> > +
>> > /* If we do not own this thread, we must stop as soon as we find
>> > something that we can't put in a delay slot, since all we can do
>> > is branch into THREAD at a later point. Therefore, labels stop
>> > @@ -2439,8 +2454,18 @@ fill_slots_from_thread (rtx_jump_insn *insn, rtx condition,
>> > /* If TRIAL conflicts with the insns ahead of it, we lose. Also,
>> > don't separate or copy insns that set and use CC0. */
>> > if (! insn_references_resource_p (trial, &set, true)
>> > - && ! insn_sets_resource_p (trial, &set, true)
>> > + && ! insn_sets_resource_p (trial, filter_flags ? &fset : &set, true)
>> > && ! insn_sets_resource_p (trial, &needed, true)
>> > + /* If we're handling sets to the flags register specially, we
>> > + only allow an insn into a delay-slot, if it either:
>> > + - doesn't set the flags register,
>> > + - the "set" of the flags register isn't used (clobbered),
>> > + - insns between the delay-slot insn and the trial-insn
>> > + as accounted in "set", have not affected the flags register. */
>> > + && (! filter_flags
>> > + || ! insn_sets_resource_p (trial, &flags_res, true)
>> > + || find_regno_note (trial, REG_UNUSED, targetm.flags_regnum)
>> > + || ! TEST_HARD_REG_BIT (set.regs, targetm.flags_regnum))
>> > && (!HAVE_cc0 || (! (reg_mentioned_p (cc0_rtx, pat)
>> > && (! own_thread || ! sets_cc0_p (pat)))))
>> > && ! can_throw_internal (trial))
>> > @@ -2618,6 +2643,16 @@ fill_slots_from_thread (rtx_jump_insn *insn, rtx condition,
>> > lose = 1;
>> > mark_set_resources (trial, &set, 0, MARK_SRC_DEST_CALL);
>> > mark_referenced_resources (trial, &needed, true);
>> > + if (filter_flags)
>> > + {
>> > + mark_set_resources (trial, &fset, 0, MARK_SRC_DEST_CALL);
>> > +
>> > + /* Groups of flags-register setters with users should not
>> > + affect opportunities to move flags-register-setting insns
>> > + (clobbers) into the delay-slot. */
>> > + CLEAR_HARD_REG_BIT (needed.regs, targetm.flags_regnum);
>>
>> If we do this, what stops us from trying to move a flags-register user
>> ahead of the associated setter, when the user doesn't itself set the
>> flags register?
>
> First, all sets are still in set (set.regs) including any that
> set the flags register between the insn with the delay-slot and
> the trial.
>
> (That's why it's separate from fset (fset.regs). I used the
> same naming scheme as in the named commit, but perhaps a better
> name would be set_with_flags_filtered or something.)
>
>> Feels like there should be some test involving
>> insn_references_resource_p (trial, &flags_res, true) in the
>> (! filter_flags || ...) condition above.
>
> There is: the "! insn_references_resource_p (trial, &set, true)"
> (pre-existing in the context above the patch), so we don't move
> anything that references anything set (only additional flags
> register setters where the result is unused).
Ah, right, I think I was getting them the wrong way around.
Looks OK to me, but give Eric 24 hrs to object/comment.
Like you say, he's better qualified to review this, I was just
stepping in because it looked like the patch had fallen through
the cracks.
Thanks,
Richard
More information about the Gcc-patches
mailing list