This patch to rs6000.md (which is essentially the same as #3) fixes the problem by removing the early clobber. The patches to predicates.md, and the fusion tests revert my changes on February 9th that originally 'solved' the problem by not allowing fusion of ADDI values. We have tested the fix using a combine profiled and LTO bootstrap build and it does not cause any regressions. Because machine independent changes can mask the bug at times, we also did a profiled/LTO build on the subversion revision that showed up the problem. Is this ok to install in the trunk?
Since gcc 5 contains the exact same early clobber, I would like to also back port the change to GCC 5. [gcc] 2016-02-18 Michael Meissner <meiss...@linux.vnet.ibm.com> PR target/68404 * config/rs6000/predicates.md (fusion_gpr_addis): Revert 2016-02-09 change. * config/rs6000/rs6000.md (fusion_gpr_load_<mode>): Remove earlyclobber from target. Use wF constraint for fused memory address. (fusion_gpr_<P:mode>_<GPR_FUSION:mode>_load): Likewise. [gcc/testsuites] 2016-02-18 Michael Meissner <meiss...@linux.vnet.ibm.com> PR target/68404 * gcc.target/powerpc/fusion.c: Revert the 2016-02-09 change. * gcc.target/powerpc/fusion3.c: Likewise. -- Michael Meissner, IBM IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA email: meiss...@linux.vnet.ibm.com, phone: +1 (978) 899-4797
Index: gcc/config/rs6000/predicates.md =================================================================== --- gcc/config/rs6000/predicates.md (revision 233351) +++ gcc/config/rs6000/predicates.md (working copy) @@ -1708,14 +1708,23 @@ (define_predicate "fusion_gpr_addis" (match_code "const_int,high,plus") { HOST_WIDE_INT value; + rtx int_const; if (GET_CODE (op) == HIGH) return 1; - if (!CONST_INT_P (op)) + if (CONST_INT_P (op)) + int_const = op; + + else if (GET_CODE (op) == PLUS + && base_reg_operand (XEXP (op, 0), Pmode) + && CONST_INT_P (XEXP (op, 1))) + int_const = XEXP (op, 1); + + else return 0; - value = INTVAL (op); + value = INTVAL (int_const); if ((value & (HOST_WIDE_INT)0xffff) != 0) return 0; Index: gcc/config/rs6000/rs6000.md =================================================================== --- gcc/config/rs6000/rs6000.md (revision 233351) +++ gcc/config/rs6000/rs6000.md (working copy) @@ -12915,8 +12915,8 @@ (define_peephole2 ;; reload) (define_insn "fusion_gpr_load_<mode>" - [(set (match_operand:INT1 0 "base_reg_operand" "=&b") - (unspec:INT1 [(match_operand:INT1 1 "fusion_addis_mem_combo_load" "")] + [(set (match_operand:INT1 0 "base_reg_operand" "=b") + (unspec:INT1 [(match_operand:INT1 1 "fusion_addis_mem_combo_load" "wF")] UNSPEC_FUSION_GPR))] "TARGET_P8_FUSION" { @@ -12987,7 +12987,7 @@ (define_insn "fusion_gpr_<P:mode>_<GPR_F (unspec:GPR_FUSION [(match_operand:GPR_FUSION 1 "fusion_addis_mem_combo_load" "wF")] UNSPEC_FUSION_P9)) - (clobber (match_operand:P 2 "base_reg_operand" "=&b"))] + (clobber (match_operand:P 2 "base_reg_operand" "=b"))] "TARGET_P9_FUSION" { /* This insn is a secondary reload insn, which cannot have alternatives. Index: gcc/testsuite/gcc.target/powerpc/fusion3.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/fusion3.c (revision 233351) +++ gcc/testsuite/gcc.target/powerpc/fusion3.c (working copy) @@ -4,24 +4,15 @@ /* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power7" } } */ /* { dg-options "-mcpu=power7 -mtune=power9 -O3" } */ -#define SIZE 4 -struct foo { - float f; - double d; -}; +#define LARGE 0x12345 -static struct foo st[SIZE]; -struct foo *ptr_st = &st[0]; +int fusion_float_read (float *p){ return p[LARGE]; } +int fusion_double_read (double *p){ return p[LARGE]; } -float fusion_float_read (void){ return st[SIZE].f; } -double fusion_float_extend (void){ return (double)st[SIZE].f; } -double fusion_double_read (void){ return st[SIZE].d; } +void fusion_float_write (float *p, float f){ p[LARGE] = f; } +void fusion_double_write (double *p, double d){ p[LARGE] = d; } -void fusion_float_write (float f){ st[SIZE].f = f; } -void fusion_float_truncate (double d){ st[SIZE].f = (float)d; } -void fusion_double_write (double d){ st[SIZE].d = d; } - -/* { dg-final { scan-assembler-times "load fusion, type SF" 2 } } */ -/* { dg-final { scan-assembler-times "load fusion, type DF" 1 } } */ -/* { dg-final { scan-assembler-times "store fusion, type SF" 2 } } */ -/* { dg-final { scan-assembler-times "store fusion, type DF" 1 } } */ +/* { dg-final { scan-assembler "load fusion, type SF" } } */ +/* { dg-final { scan-assembler "load fusion, type DF" } } */ +/* { dg-final { scan-assembler "store fusion, type SF" } } */ +/* { dg-final { scan-assembler "store fusion, type DF" } } */ Index: gcc/testsuite/gcc.target/powerpc/fusion.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/fusion.c (revision 233351) +++ gcc/testsuite/gcc.target/powerpc/fusion.c (working copy) @@ -1,28 +1,17 @@ -/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */ +/* { dg-do compile { target { powerpc*-*-* } } } */ /* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ /* { dg-require-effective-target powerpc_p8vector_ok } */ /* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power7" } } */ -/* { dg-options "-mcpu=power7 -mtune=power8 -O3 -mcmodel=medium" } */ +/* { dg-options "-mcpu=power7 -mtune=power8 -O3" } */ -#define SIZE 4 -struct foo { - unsigned char uc; - signed char sc; - unsigned short us; - short ss; - int i; - unsigned u; -}; +#define LARGE 0x12345 -static struct foo st[SIZE]; -struct foo *ptr_st = &st[0]; - -int fusion_uchar (void){ return st[SIZE-1].uc; } -int fusion_schar (void){ return st[SIZE-1].sc; } -int fusion_ushort (void){ return st[SIZE-1].us; } -int fusion_short (void){ return st[SIZE-1].ss; } -int fusion_int (void){ return st[SIZE-1].i; } -unsigned fusion_uns (void){ return st[SIZE-1].u; } +int fusion_uchar (unsigned char *p){ return p[LARGE]; } +int fusion_schar (signed char *p){ return p[LARGE]; } +int fusion_ushort (unsigned short *p){ return p[LARGE]; } +int fusion_short (short *p){ return p[LARGE]; } +int fusion_int (int *p){ return p[LARGE]; } +unsigned fusion_uns (unsigned *p){ return p[LARGE]; } /* { dg-final { scan-assembler-times "gpr load fusion" 6 } } */ /* { dg-final { scan-assembler-times "lbz" 2 } } */