This patch adds handling of group-of-two instructions. --- gcc/config/s390/s390.c | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-)
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index 4dcf1be4445..78a707267e8 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -14266,14 +14266,17 @@ struct s390_sched_state int group_state; /* Execution side of the group. */ int side; + /* Group can only hold two insns. */ + bool group_of_two; } s390_sched_state; -static struct s390_sched_state sched_state = {0, 1}; +static struct s390_sched_state sched_state = {0, 1, false}; #define S390_SCHED_ATTR_MASK_CRACKED 0x1 #define S390_SCHED_ATTR_MASK_EXPANDED 0x2 #define S390_SCHED_ATTR_MASK_ENDGROUP 0x4 #define S390_SCHED_ATTR_MASK_GROUPALONE 0x8 +#define S390_SCHED_ATTR_MASK_GROUPOFTWO 0x10 static unsigned int s390_get_sched_attrmask (rtx_insn *insn) @@ -14301,6 +14304,8 @@ s390_get_sched_attrmask (rtx_insn *insn) mask |= S390_SCHED_ATTR_MASK_ENDGROUP; if (get_attr_z13_groupalone (insn)) mask |= S390_SCHED_ATTR_MASK_GROUPALONE; + if (get_attr_z13_groupoftwo (insn)) + mask |= S390_SCHED_ATTR_MASK_GROUPOFTWO; break; case PROCESSOR_3906_Z14: if (get_attr_z14_cracked (insn)) @@ -14311,6 +14316,8 @@ s390_get_sched_attrmask (rtx_insn *insn) mask |= S390_SCHED_ATTR_MASK_ENDGROUP; if (get_attr_z14_groupalone (insn)) mask |= S390_SCHED_ATTR_MASK_GROUPALONE; + if (get_attr_z14_groupoftwo (insn)) + mask |= S390_SCHED_ATTR_MASK_GROUPOFTWO; break; default: gcc_unreachable (); @@ -14393,6 +14400,11 @@ s390_sched_score (rtx_insn *insn) score += 10; if ((mask & S390_SCHED_ATTR_MASK_ENDGROUP) == 0) score += 5; + /* If we are in a group of two already, try to schedule another + group-of-two insn to avoid shortening another group. */ + if (sched_state.group_of_two + && (mask & S390_SCHED_ATTR_MASK_GROUPOFTWO) != 0) + score += 15; break; case 2: /* Prefer not cracked insns while trying to put together a @@ -14404,6 +14416,10 @@ s390_sched_score (rtx_insn *insn) /* Prefer endgroup insns in the last slot. */ if ((mask & S390_SCHED_ATTR_MASK_ENDGROUP) != 0) score += 10; + /* Try to avoid group-of-two insns in the last slot as they will + shorten this group as well as the next one. */ + if ((mask & S390_SCHED_ATTR_MASK_GROUPOFTWO) != 0) + score = MAX (0, score - 15); break; } @@ -14595,6 +14611,17 @@ 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_GROUPOFTWO) != 0) + sched_state.group_of_two = true; + + /* If this is a group-of-two insn, we actually ended the last group + and this insn is the first one of the new group. */ + if (sched_state.group_state == 2 && sched_state.group_of_two) + { + sched_state.side = sched_state.side ? 0 : 1; + sched_state.group_state = 0; + } + /* Longrunning and side bookkeeping. */ for (int i = 0; i < 2; i++) { @@ -14645,6 +14672,11 @@ s390_sched_variable_issue (FILE *file, int verbose, rtx_insn *insn, int more) break; case 1: sched_state.group_state++; + if (sched_state.group_of_two) + { + sched_state.group_state = 0; + ends_group = true; + } break; case 2: sched_state.group_state++; @@ -14700,6 +14732,7 @@ s390_sched_variable_issue (FILE *file, int verbose, rtx_insn *insn, int more) { sched_state.group_state = 0; sched_state.side = sched_state.side ? 0 : 1; + sched_state.group_of_two = false; } } @@ -14733,6 +14766,7 @@ s390_sched_init (FILE *file ATTRIBUTE_UNUSED, memset (last_scheduled_unit_distance, 0, MAX_SCHED_UNITS * NUM_SIDES * sizeof (int)); sched_state.group_state = 0; + sched_state.group_of_two = false; } } -- 2.17.0