Hi!

On Sun, Nov 25, 2018 at 10:50:27PM +1030, Alan Modra wrote:
> This patch aims to prevent long sequences loading soft-float
> constants.  For 32-bit, it makes sense to load values inline to a gpr
> with lis, addi, but not so much for 64-bit where a 5 insn sequence
> might be needed for each gpr.  For TFmode in particular, a 10 insn
> sequence is reduced to 2 loads from memory plus 1 or 2 address setup
> insns.
> 
> Bootstrapped etc. powerpc64le-linux and powerpc64-linux.  OK for
> next stage1?

It's okay now, even.

>       * config/rs6000/predicates.md (easy_fp_constant): Avoid long
>       dependent insn sequences.
>       * config/rs6000/rs6000.c (num_insns_constant): Support long
>       double constants.
>       * config/rs6000/rs6000.md (mov<mode>_softfloat128) Adjust length
>       attribute.

> -  /* Consider all constants with -msoft-float to be easy.  */
> -  if (TARGET_SOFT_FLOAT)
> +  /* Consider all constants with -msoft-float to be easy when regs are
> +     32-bit and thus can be loaded with a maximum of 2 insns.  For
> +     64-bit avoid long dependent insn sequences.  */
> +  if (TARGET_SOFT_FLOAT
> +      && (!TARGET_POWERPC64
> +       || mode == SFmode || mode == SDmode
> +       || ((mode == DFmode || mode == DDmode)
> +           && (num_insns_constant (op, mode)
> +               <= (TARGET_CMODEL != CMODEL_SMALL ? 3 : 2)))
> +       || ((mode == TFmode || mode == TDmode
> +            || mode == KFmode || mode == IFmode)
> +           && (num_insns_constant (op, mode)
> +               <= (TARGET_CMODEL != CMODEL_SMALL ? 4 : 3)))))
>      return 1;

Maybe this can be written simpler with  MODE_SIZE (mode) >= 16  or such.

  if (TARGET_SOFT_FLOAT)
    {
      if (!TARGET_POWERPC64)
        return 1;

      int size = MODE_SIZE (mode);
      if (size == 4)
        return 1;

      int max_insns = 3;
      if (TARGET_CMODEL == CMODEL_SMALL)
        max_insns--;
      if (size >= 16)
        max_insns++;
      if (num_insns_constant (op, mode) <= max_insns)
        return 1;
    }

Something like that, perhaps.  It's not really shorter :-/

> +     else if (mode == TFmode || mode == TDmode
> +              || mode == KFmode || mode == IFmode)
> +       {
> +         long l[4];
> +         int ins;
> +
> +         if (mode == TDmode)
> +           REAL_VALUE_TO_TARGET_DECIMAL128 (*rv, l);
> +         else
> +           REAL_VALUE_TO_TARGET_LONG_DOUBLE (*rv, l);
> +
> +         val = l[WORDS_BIG_ENDIAN ? 0 : 3] << 32;
> +         val |= l[WORDS_BIG_ENDIAN ? 1 : 2] & 0xffffffffUL;

You can't shift a "long" left by 32 bits.  Cast to HOST_WIDE_INT?
Maybe there is some helper already?

> --- a/gcc/config/rs6000/rs6000.md
> +++ b/gcc/config/rs6000/rs6000.md
> @@ -7729,7 +7729,7 @@ (define_insn_and_split "*mov<mode>_softfloat128"
>           (const_string "8")
>           (const_string "16"))
>       (if_then_else (match_test "TARGET_POWERPC64")
> -         (const_string "40")
> +         (const_string "16")
>           (const_string "32"))
>       (if_then_else (match_test "TARGET_POWERPC64")
>           (const_string "8")

I really would love to see this in stage3 still; it's arguably a bugfix.


Segher

Reply via email to