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