[6/7] S/390: Add handling for group-of-two instructions.

Message ID 20190311125327.20093-7-rdapp@linux.ibm.com
State New
Headers show
Series
  • S/390: Rework instruction scheduling.
Related show

Commit Message

Robin Dapp March 11, 2019, 12:53 p.m.
This patch adds handling of group-of-two instructions.

---
 gcc/config/s390/s390.c | 36 +++++++++++++++++++++++++++++++++++-
 1 file changed, 35 insertions(+), 1 deletion(-)

-- 
2.17.0

Patch

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;
     }
 }