aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog16
-rw-r--r--gcc/config/rs6000/power6.md18
-rw-r--r--gcc/config/rs6000/rs6000-protos.h1
-rw-r--r--gcc/config/rs6000/rs6000.c97
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr80101-1.c22
6 files changed, 144 insertions, 15 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 2bfe704..4f4af36 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,19 @@
+2017-05-08 Kelvin Nilsen <kelvin@gcc.gnu.org>
+
+ 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-05-08 Max Filippov <jcmvbkbc@gmail.com>
* config/xtensa/xtensa-protos.h
diff --git a/gcc/config/rs6000/power6.md b/gcc/config/rs6000/power6.md
index eb53246..0d81cde 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 74ad733..0344823 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 bac56ab..17b93a6 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -508,6 +508,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)
@@ -33058,14 +33143,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;
@@ -33076,7 +33161,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;
}
@@ -33085,19 +33170,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 3aba70e..597930c 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2017-05-08 Kelvin Nilsen <kelvin@gcc.gnu.org>
+
+ PR target/80101
+ * gcc.target/powerpc/pr80101-1.c: New test.
+
2017-05-08 Thomas Koenig <tkoenig@gcc.gnu.org>
PR fortran/79930
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 0000000..45011d5
--- /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 ();
+}