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