diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 712923319ba..e80f460dbb4 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,22 @@ +2017-12-07 Kelvin Nilsen + + Backport from trunk + 2017-05-08 Kelvin Nilsen + + PR target/80101 + * config/rs6000/power6.md: Replace store_data_bypass_p calls with + rs6000_store_data_bypass_p in seven define_bypass directives and + in several comments. + * config/rs6000/rs6000-protos.h: Add prototype for + rs6000_store_data_bypass_p function. + * config/rs6000/rs6000.c (rs6000_store_data_bypass_p): New + function implements slightly different (rs6000-specific) semantics + than store_data_bypass_p, returning false rather than aborting + with assertion error when arguments do not satisfy the + requirements of store data bypass. + (rs6000_adjust_cost): Replace six calls of store_data_bypass_p with + rs6000_store_data_bypass_p. + 2017-12-06 Eric Botcazou Revert diff --git a/gcc/config/rs6000/power6.md b/gcc/config/rs6000/power6.md index eb53246a40e..0d81cdebda5 100644 --- a/gcc/config/rs6000/power6.md +++ b/gcc/config/rs6000/power6.md @@ -108,7 +108,7 @@ power6-store-update-indexed,\ power6-fpstore,\ power6-fpstore-update" - "store_data_bypass_p") + "rs6000_store_data_bypass_p") (define_insn_reservation "power6-load-ext" 4 ; fx (and (eq_attr "type" "load") @@ -128,7 +128,7 @@ power6-store-update-indexed,\ power6-fpstore,\ power6-fpstore-update" - "store_data_bypass_p") + "rs6000_store_data_bypass_p") (define_insn_reservation "power6-load-update" 2 ; fx (and (eq_attr "type" "load") @@ -276,7 +276,7 @@ power6-store-update-indexed,\ power6-fpstore,\ power6-fpstore-update" - "store_data_bypass_p") + "rs6000_store_data_bypass_p") (define_insn_reservation "power6-cntlz" 2 (and (eq_attr "type" "cntlz") @@ -289,7 +289,7 @@ power6-store-update-indexed,\ power6-fpstore,\ power6-fpstore-update" - "store_data_bypass_p") + "rs6000_store_data_bypass_p") (define_insn_reservation "power6-var-rotate" 4 (and (eq_attr "type" "shift") @@ -355,7 +355,7 @@ power6-store-update-indexed,\ power6-fpstore,\ power6-fpstore-update" - "store_data_bypass_p") + "rs6000_store_data_bypass_p") (define_insn_reservation "power6-delayed-compare" 2 ; N/A (and (eq_attr "type" "shift") @@ -420,7 +420,7 @@ power6-store-update-indexed,\ power6-fpstore,\ power6-fpstore-update" - "store_data_bypass_p") + "rs6000_store_data_bypass_p") (define_insn_reservation "power6-idiv" 44 (and (eq_attr "type" "div") @@ -436,7 +436,7 @@ ; power6-store-update-indexed,\ ; power6-fpstore,\ ; power6-fpstore-update" -; "store_data_bypass_p") +; "rs6000_store_data_bypass_p") (define_insn_reservation "power6-ldiv" 56 (and (eq_attr "type" "div") @@ -452,7 +452,7 @@ ; power6-store-update-indexed,\ ; power6-fpstore,\ ; power6-fpstore-update" -; "store_data_bypass_p") +; "rs6000_store_data_bypass_p") (define_insn_reservation "power6-mtjmpr" 2 (and (eq_attr "type" "mtjmpr,mfjmpr") @@ -510,7 +510,7 @@ (define_bypass 1 "power6-fp" "power6-fpstore,power6-fpstore-update" - "store_data_bypass_p") + "rs6000_store_data_bypass_p") (define_insn_reservation "power6-fpcompare" 8 (and (eq_attr "type" "fpcompare") diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h index 74ad733d1b9..0344823db0a 100644 --- a/gcc/config/rs6000/rs6000-protos.h +++ b/gcc/config/rs6000/rs6000-protos.h @@ -226,6 +226,7 @@ extern void rs6000_aix_asm_output_dwarf_table_ref (char *); extern void get_ppc476_thunk_name (char name[32]); extern bool rs6000_overloaded_builtin_p (enum rs6000_builtins); extern const char *rs6000_overloaded_builtin_name (enum rs6000_builtins); +extern int rs6000_store_data_bypass_p (rtx_insn *, rtx_insn *); extern HOST_WIDE_INT rs6000_builtin_mask_calculate (void); extern void rs6000_asm_output_dwarf_pcrel (FILE *file, int size, const char *label); diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index a4e2f1cfbd7..a3a6e5a7a32 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -510,6 +510,91 @@ mode_supports_pre_modify_p (machine_mode mode) != 0); } +/* Given that there exists at least one variable that is set (produced) + by OUT_INSN and read (consumed) by IN_INSN, return true iff + IN_INSN represents one or more memory store operations and none of + the variables set by OUT_INSN is used by IN_INSN as the address of a + store operation. If either IN_INSN or OUT_INSN does not represent + a "single" RTL SET expression (as loosely defined by the + implementation of the single_set function) or a PARALLEL with only + SETs, CLOBBERs, and USEs inside, this function returns false. + + This rs6000-specific version of store_data_bypass_p checks for + certain conditions that result in assertion failures (and internal + compiler errors) in the generic store_data_bypass_p function and + returns false rather than calling store_data_bypass_p if one of the + problematic conditions is detected. */ + +int +rs6000_store_data_bypass_p (rtx_insn *out_insn, rtx_insn *in_insn) +{ + rtx out_set, in_set; + rtx out_pat, in_pat; + rtx out_exp, in_exp; + int i, j; + + in_set = single_set (in_insn); + if (in_set) + { + if (MEM_P (SET_DEST (in_set))) + { + out_set = single_set (out_insn); + if (!out_set) + { + out_pat = PATTERN (out_insn); + if (GET_CODE (out_pat) == PARALLEL) + { + for (i = 0; i < XVECLEN (out_pat, 0); i++) + { + out_exp = XVECEXP (out_pat, 0, i); + if ((GET_CODE (out_exp) == CLOBBER) + || (GET_CODE (out_exp) == USE)) + continue; + else if (GET_CODE (out_exp) != SET) + return false; + } + } + } + } + } + else + { + in_pat = PATTERN (in_insn); + if (GET_CODE (in_pat) != PARALLEL) + return false; + + for (i = 0; i < XVECLEN (in_pat, 0); i++) + { + in_exp = XVECEXP (in_pat, 0, i); + if ((GET_CODE (in_exp) == CLOBBER) || (GET_CODE (in_exp) == USE)) + continue; + else if (GET_CODE (in_exp) != SET) + return false; + + if (MEM_P (SET_DEST (in_exp))) + { + out_set = single_set (out_insn); + if (!out_set) + { + out_pat = PATTERN (out_insn); + if (GET_CODE (out_pat) != PARALLEL) + return false; + for (j = 0; j < XVECLEN (out_pat, 0); j++) + { + out_exp = XVECEXP (out_pat, 0, j); + if ((GET_CODE (out_exp) == CLOBBER) + || (GET_CODE (out_exp) == USE)) + continue; + else if (GET_CODE (out_exp) != SET) + return false; + } + } + } + } + } + return store_data_bypass_p (out_insn, in_insn); +} + /* Return true if we have D-form addressing in altivec registers. */ static inline bool mode_supports_vmx_dform (machine_mode mode) @@ -33091,14 +33176,14 @@ rs6000_adjust_cost (rtx_insn *insn, int dep_type, rtx_insn *dep_insn, int cost, case TYPE_LOAD: case TYPE_CNTLZ: { - if (! store_data_bypass_p (dep_insn, insn)) + if (! rs6000_store_data_bypass_p (dep_insn, insn)) return get_attr_sign_extend (dep_insn) == SIGN_EXTEND_YES ? 6 : 4; break; } case TYPE_SHIFT: { - if (! store_data_bypass_p (dep_insn, insn)) + if (! rs6000_store_data_bypass_p (dep_insn, insn)) return get_attr_var_shift (dep_insn) == VAR_SHIFT_YES ? 6 : 3; break; @@ -33109,7 +33194,7 @@ rs6000_adjust_cost (rtx_insn *insn, int dep_type, rtx_insn *dep_insn, int cost, case TYPE_EXTS: case TYPE_INSERT: { - if (! store_data_bypass_p (dep_insn, insn)) + if (! rs6000_store_data_bypass_p (dep_insn, insn)) return 3; break; } @@ -33118,19 +33203,19 @@ rs6000_adjust_cost (rtx_insn *insn, int dep_type, rtx_insn *dep_insn, int cost, case TYPE_FPSTORE: { if (get_attr_update (dep_insn) == UPDATE_YES - && ! store_data_bypass_p (dep_insn, insn)) + && ! rs6000_store_data_bypass_p (dep_insn, insn)) return 3; break; } case TYPE_MUL: { - if (! store_data_bypass_p (dep_insn, insn)) + if (! rs6000_store_data_bypass_p (dep_insn, insn)) return 17; break; } case TYPE_DIV: { - if (! store_data_bypass_p (dep_insn, insn)) + if (! rs6000_store_data_bypass_p (dep_insn, insn)) return get_attr_size (dep_insn) == SIZE_32 ? 45 : 57; break; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index bdaa3735ea3..ccbd122c2aa 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2017-12-07 Kelvin Nilsen + + Backport from trunk + 2017-05-08 Kelvin Nilsen + + PR target/80101 + * gcc.target/powerpc/pr80101-1.c: New test. + 2017-12-04 Sebastian Peryt H.J. Lu diff --git a/gcc/testsuite/gcc.target/powerpc/pr80101-1.c b/gcc/testsuite/gcc.target/powerpc/pr80101-1.c new file mode 100644 index 00000000000..45011d54ac2 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr80101-1.c @@ -0,0 +1,22 @@ +/* { dg-do compile { target { powerpc*-*-* } } } */ +/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power6" } } */ +/* { dg-require-effective-target dfp_hw } */ +/* { dg-options "-mcpu=power6 -mno-sched-epilog -Ofast" } */ + +/* Prior to resolving PR 80101, this test case resulted in an internal + compiler error. The role of this test program is to assure that + dejagnu's "test for excess errors" does not find any. */ + +int b; + +void e (); + +int c () +{ + struct + { + int a[b]; + } d; + if (d.a[0]) + e (); +}