Hi!

[ I missed this patch the first time around; please cc: me to prevent this ]

On Thu, May 18, 2017 at 07:25:57AM -0300, Alexandre Oliva wrote:
> When an insn used by combine has multiple SETs, only the non-REG_UNUSED
> set is used: others will end up dropped on the floor.

Sometimes, yes; not always.

> We have to take
> note of the dropped REG_UNUSED SETs, clearing their cached values, so
> that, even if the REGs remain used (e.g. because they were referenced
> in the used SET_SRC), we will not use properties of the latest value
> as if they applied to the earlier one.

The reg_stat stuff is no end of pain, sigh.

>       PR rtl-optimization/80693
>       * combine.c (distribute_notes): Add IDEST parameter.  Reset any
>       REG_UNUSED REGs that are not IDEST, if IDEST is given.  Adjust
>       all callers.

Most callers use NULL_RTX for idest.  It isn't obvious to me that this
is correct.

> @@ -14087,6 +14090,26 @@ distribute_notes (rtx notes, rtx_insn *from_insn, 
> rtx_insn *i3, rtx_insn *i2,
>             PUT_REG_NOTE_KIND (note, REG_DEAD);
>             place = i3;
>           }
> +
> +       /* If there were any parallel sets in FROM_INSN other than
> +          the one setting IDEST, it must be REG_UNUSED, otherwise
> +          we could not have used FROM_INSN in combine.  Since this
> +          combine attempt succeeded, we know this unused SET was
> +          dropped on the floor, because the insn was either deleted
> +          or created from a new pattern that does not use its
> +          SET_DEST.  We must forget whatever we knew about the
> +          value that was stored by that SET, since the prior value
> +          may still be present in IDEST's src expression or
> +          elsewhere, and we do not want to use properties of the
> +          dropped value as if they applied to the prior one when
> +          simplifying e.g. subsequent combine attempts.  */
> +       if (idest && XEXP (note, 0) != idest)

Would it work to just have "else" instead if this "if"?  Or hrm, we'll
need to kill the recorded reg_stat value in the last case before this
as well?

> +         {
> +           gcc_assert (REG_P (XEXP (note, 0)));
> +           record_value_for_reg (XEXP (note, 0), NULL, NULL_RTX);
> +           INC_REG_N_SETS (REGNO (XEXP (note, 0)), -1);
> +         }
> +
>         break;

Could you try that out?  Or I can do it, let me know what you prefer.

Thanks,


Segher

Reply via email to