Hi Vlad,

Vladimir Makarov <vmaka...@redhat.com> writes:
> The following patch fixes
>
>    https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87305
>
> The patch was bootstrapped and tested on x86-64 and ppc64 (be).
>
> Committed as rev. 267823.
>
> Index: ChangeLog
> ===================================================================
> --- ChangeLog (revision 267822)
> +++ ChangeLog (working copy)
> @@ -1,3 +1,12 @@
> +2019-01-10  Vladimir Makarov  <vmaka...@redhat.com>
> +
> +     PR rtl-optimization/87305
> +     * lra-assigns.c
> +     (setup_live_pseudos_and_spill_after_risky_transforms): Check
> +     allocation for big endian pseudos used as paradoxical subregs and
> +     spill them if it is wrong.
> +     * lra-constraints.c (lra_constraints): Add a comment.
> +
>  2019-01-10  Richard Biener  <rguent...@suse.de>
>  
>       PR tree-optimization/88792
> Index: lra-assigns.c
> ===================================================================
> --- lra-assigns.c     (revision 267822)
> +++ lra-assigns.c     (working copy)
> @@ -1146,12 +1146,12 @@ static void
>  setup_live_pseudos_and_spill_after_risky_transforms (bitmap
>                                                    spilled_pseudo_bitmap)
>  {
> -  int p, i, j, n, regno, hard_regno;
> +  int p, i, j, n, regno, hard_regno, biggest_nregs, nregs_diff;
>    unsigned int k, conflict_regno;
>    poly_int64 offset;
>    int val;
>    HARD_REG_SET conflict_set;
> -  machine_mode mode;
> +  machine_mode mode, biggest_mode;
>    lra_live_range_t r;
>    bitmap_iterator bi;
>    int max_regno = max_reg_num ();
> @@ -1166,8 +1166,26 @@ setup_live_pseudos_and_spill_after_risky
>    for (n = 0, i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
>      if ((pic_offset_table_rtx == NULL_RTX
>        || i != (int) REGNO (pic_offset_table_rtx))
> -     && reg_renumber[i] >= 0 && lra_reg_info[i].nrefs > 0)
> -      sorted_pseudos[n++] = i;
> +     && (hard_regno = reg_renumber[i]) >= 0 && lra_reg_info[i].nrefs > 0)
> +      {
> +     biggest_mode = lra_reg_info[i].biggest_mode;
> +     biggest_nregs = hard_regno_nregs (hard_regno, biggest_mode);
> +     nregs_diff = (biggest_nregs
> +                   - hard_regno_nregs (hard_regno, PSEUDO_REGNO_MODE (i)));
> +     enum reg_class rclass = lra_get_allocno_class (i);
> +
> +     if (WORDS_BIG_ENDIAN
> +         && (hard_regno - nregs_diff < 0
> +             || !TEST_HARD_REG_BIT (reg_class_contents[rclass],
> +                                    hard_regno - nregs_diff)))
> +       {
> +         /* Hard registers of paradoxical sub-registers are out of
> +            range of pseudo register class.  Spill the pseudo.  */
> +         reg_renumber[i] = -1;
> +         continue;
> +       }

I think for !WORDS_BIG_ENDIAN the equivalent problem to:

                || !TEST_HARD_REG_BIT (reg_class_contents[rclass],
                                       hard_regno - nregs_diff)))

would be:

                || !TEST_HARD_REG_BIT (reg_class_contents[rclass],
                                       hard_regno + biggest_nregs - 1)))

Where does that little-endian check happen?  I wasn't sure why
"biggest_mode goes outside the class" problems only occured here
for big-endian.

Thanks,
Richard

Reply via email to