aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/config/s390/s390.c68
2 files changed, 73 insertions, 5 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 5d0dd0b..5850f00 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,13 @@
+2017-10-18 Robin Dapp <rdapp@linux.vnet.ibm.com>
+
+ * config/s390/s390.c (NUM_SIDES): New variable.
+ (LONGRUNNING_THRESHOLD): New variable.
+ (LATENCY_FACTOR): New variable.
+ (s390_sched_score): Decrease score for long-running instructions on
+ wrong side.
+ (s390_sched_variable_issue): Perform bookkeeping for long-running
+ instructions.
+
2017-10-18 Richard Biener <rguenther@suse.de>
* graphite-isl-ast-to-gimple.c (gcc_expression_from_isl_ast_expr_id):
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index 6e3ac3b..021993f 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -355,6 +355,18 @@ static rtx_insn *last_scheduled_insn;
#define MAX_SCHED_UNITS 3
static int last_scheduled_unit_distance[MAX_SCHED_UNITS];
+#define NUM_SIDES 2
+static int current_side = 1;
+#define LONGRUNNING_THRESHOLD 5
+
+/* Estimate of number of cycles a long-running insn occupies an
+ execution unit. */
+static unsigned fxu_longrunning[NUM_SIDES];
+static unsigned vfu_longrunning[NUM_SIDES];
+
+/* Factor to scale latencies by, determined by measurements. */
+#define LATENCY_FACTOR 4
+
/* The maximum score added for an instruction whose unit hasn't been
in use for MAX_SCHED_MIX_DISTANCE steps. Increase this value to
give instruction mix scheduling more priority over instruction
@@ -14755,7 +14767,24 @@ s390_sched_score (rtx_insn *insn)
if (m & unit_mask)
score += (last_scheduled_unit_distance[i] * MAX_SCHED_MIX_SCORE /
MAX_SCHED_MIX_DISTANCE);
+
+ unsigned latency = insn_default_latency (insn);
+
+ int other_side = 1 - current_side;
+
+ /* Try to delay long-running insns when side is busy. */
+ if (latency > LONGRUNNING_THRESHOLD)
+ {
+ if (get_attr_z13_unit_fxu (insn) && fxu_longrunning[current_side]
+ && fxu_longrunning[other_side] <= fxu_longrunning[current_side])
+ score = MAX (0, score - 10);
+
+ if (get_attr_z13_unit_vfu (insn) && vfu_longrunning[current_side]
+ && vfu_longrunning[other_side] <= vfu_longrunning[current_side])
+ score = MAX (0, score - 10);
+ }
}
+
return score;
}
@@ -14874,6 +14903,8 @@ s390_sched_variable_issue (FILE *file, int verbose, rtx_insn *insn, int more)
{
last_scheduled_insn = insn;
+ bool starts_group = false;
+
if (s390_tune >= PROCESSOR_2827_ZEC12
&& reload_completed
&& recog_memoized (insn) >= 0)
@@ -14881,6 +14912,11 @@ s390_sched_variable_issue (FILE *file, int verbose, rtx_insn *insn, int more)
unsigned int mask = s390_get_sched_attrmask (insn);
if ((mask & S390_SCHED_ATTR_MASK_CRACKED) != 0
+ || (mask & S390_SCHED_ATTR_MASK_EXPANDED) != 0
+ || (mask & S390_SCHED_ATTR_MASK_GROUPALONE) != 0)
+ starts_group = true;
+
+ if ((mask & S390_SCHED_ATTR_MASK_CRACKED) != 0
|| (mask & S390_SCHED_ATTR_MASK_EXPANDED) != 0)
s390_sched_state = S390_SCHED_STATE_CRACKED;
else if ((mask & S390_SCHED_ATTR_MASK_ENDGROUP) != 0
@@ -14892,14 +14928,15 @@ s390_sched_variable_issue (FILE *file, int verbose, rtx_insn *insn, int more)
switch (s390_sched_state)
{
case 0:
+ starts_group = true;
+ /* fallthrough */
case 1:
case 2:
+ s390_sched_state++;
+ break;
case S390_SCHED_STATE_NORMAL:
- if (s390_sched_state == S390_SCHED_STATE_NORMAL)
- s390_sched_state = 1;
- else
- s390_sched_state++;
-
+ starts_group = true;
+ s390_sched_state = 1;
break;
case S390_SCHED_STATE_CRACKED:
s390_sched_state = S390_SCHED_STATE_NORMAL;
@@ -14922,6 +14959,27 @@ s390_sched_variable_issue (FILE *file, int verbose, rtx_insn *insn, int more)
last_scheduled_unit_distance[i]++;
}
+ /* If this insn started a new group, the side flipped. */
+ if (starts_group)
+ current_side = current_side ? 0 : 1;
+
+ for (int i = 0; i < 2; i++)
+ {
+ if (fxu_longrunning[i] >= 1)
+ fxu_longrunning[i] -= 1;
+ if (vfu_longrunning[i] >= 1)
+ vfu_longrunning[i] -= 1;
+ }
+
+ unsigned latency = insn_default_latency (insn);
+ if (latency > LONGRUNNING_THRESHOLD)
+ {
+ if (get_attr_z13_unit_fxu (insn))
+ fxu_longrunning[current_side] = latency * LATENCY_FACTOR;
+ else
+ vfu_longrunning[current_side] = latency * LATENCY_FACTOR;
+ }
+
if (verbose > 5)
{
unsigned int sched_mask;