> This patch is a minimal change to prevent (subreg(mem)) from being
> simplified to use the outer mode for WORD_REGISTER_OPERATIONS.  There
> is high probability of refining and/or re-implementing this for GCC 8
> but such a change would be too invasive.  This change at least ensures
> correctness but may prevent simplification of some acceptable cases.

This one causes:

+FAIL: gcc.dg/torture/builtin-complex-1.c   -O3 -fomit-frame-pointer -funroll-
loops -fpeel-loops -ftracer -finline-functions  (test for excess errors)
+WARNING: gcc.dg/torture/builtin-complex-1.c   -O3 -fomit-frame-pointer -
funroll-loops -fpeel-loops -ftracer -finline-functions  compilation failed to 
produce executable
+FAIL: gcc.dg/torture/builtin-complex-1.c   -O3 -g  (test for excess errors)
+WARNING: gcc.dg/torture/builtin-complex-1.c   -O3 -g  compilation failed to 
produce executable
+WARNING: program timed out.
+WARNING: program timed out.

on SPARC 32-bit, i.e. LRA hangs.  Reduced testcase attached, compile at -O3 
with a cc1 configured for sparc-sun-solaris2.10.

> gcc/
>       PR target/78660
>       * lra-constraints.c (simplify_operand_subreg): Handle
>       WORD_REGISTER_OPERATIONS targets.
> ---
>  gcc/lra-constraints.c | 17 ++++++++++++-----
>  1 file changed, 12 insertions(+), 5 deletions(-)
> 
> diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c
> index 66ff2bb..484a70d 100644
> --- a/gcc/lra-constraints.c
> +++ b/gcc/lra-constraints.c
> @@ -1541,11 +1541,18 @@ simplify_operand_subreg (int nop, machine_mode
> reg_mode) subregs as we don't substitute such equiv memory (see processing
> equivalences in function lra_constraints) and because for spilled pseudos
> we allocate stack memory enough for the biggest
> -          corresponding paradoxical subreg.  */
> -       if (!(MEM_ALIGN (subst) < GET_MODE_ALIGNMENT (mode)
> -             && SLOW_UNALIGNED_ACCESS (mode, MEM_ALIGN (subst)))
> -           || (MEM_ALIGN (reg) < GET_MODE_ALIGNMENT (innermode)
> -               && SLOW_UNALIGNED_ACCESS (innermode, MEM_ALIGN (reg))))
> +          corresponding paradoxical subreg.
> +
> +          However, never simplify a (subreg (mem ...)) for
> +          WORD_REGISTER_OPERATIONS targets as this may lead to loading junk
> +          data into a register when the inner is narrower than outer or
> +          missing important data from memory when the inner is wider than
> +          outer.  */
> +       if (!WORD_REGISTER_OPERATIONS
> +           && (!(MEM_ALIGN (subst) < GET_MODE_ALIGNMENT (mode)
> +                 && SLOW_UNALIGNED_ACCESS (mode, MEM_ALIGN (subst)))
> +               || (MEM_ALIGN (reg) < GET_MODE_ALIGNMENT (innermode)
> +                   && SLOW_UNALIGNED_ACCESS (innermode, MEM_ALIGN 
(reg)))))
>           return true;
> 
>         *curr_id->operand_loc[nop] = operand;

I think that we might need:

  if (!(GET_MODE_PRECISION (mode) > GET_MODE_PRECISION (innermode)
        && WORD_REGISTER_OPERATIONS)
      && (!(MEM_ALIGN (subst) < GET_MODE_ALIGNMENT (mode)
            && SLOW_UNALIGNED_ACCESS (mode, MEM_ALIGN (subst)))
          || (MEM_ALIGN (reg) < GET_MODE_ALIGNMENT (innermode)
              && SLOW_UNALIGNED_ACCESS (innermode, MEM_ALIGN (reg)))))
    return true;

i.e. we force the reloading only for paradoxical subregs.

-- 
Eric Botcazou
extern void abort (void);

static void
comparel (long double a, long double b)
{
  long double s1 = __builtin_copysignl ((long double) 1.0, a);
  long double s2 = __builtin_copysignl ((long double) 1.0, b);

  if (s1 != s2)
    abort ();
  if ((a != b) != (__builtin_isnan (a) != 0))
    abort ();
}

void
comparecl (_Complex long double a, long double r, long double i)
{
  comparel (__real__ a, r);
  comparel (__imag__ a, i);
}

Reply via email to