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

Reply via email to