This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFC, ARM][PATCH 2/5] Try not to split IT-blocks by scheduling conditional insns together


GCC's scheduler has no idea about Thumb-2 IT blocks, which are generated from cond_execs at the stage of emitting assembly code. So it treats conditional instructions independently, and may intermix them with non-conditional instructions, which will cause generation of extra IT instructions.
We have added arm_sched_reorder target hook, which moves conditional instructions to the top of the ready list if the last scheduled insn was conditional, and vice versa. This is only done for insns with the same INSN_PRIORITY, so works only for resolving tie-breaks. Also it required few more target hooks just to save correct can_issue_more value.
This has reduced code size by 144 bytes on SPEC2K INT with -O2 (no regressions).


2011-12-29  Dmitry Melnik <dm@ispras.ru> 

gcc/
    * config/arm/arm.c (arm_variable_issue, arm_sched_init, arm_sched_finish,
      arm_sched_reorder, arm_dfa_post_advance_cycle): New functions.
      (TARGET_SCHED_VARIABLE_ISSUE, TARGET_SCHED_INIT, TARGET_SCHED_FINISH,
      TARGET_SCHED_SCHED_REORDER, TARGET_SCHED_SCHED_REORDER2, 
      TARGET_SCHED_DFA_POST_ADVANCE_CYCLE): Added hooks.
      (last_scheduled_insn): New variable.

diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index ee26c51..cabf343 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -57,6 +57,7 @@
 #include "libfuncs.h"
 #include "params.h"
 #include "opts.h"
+#include "sched-int.h"
 
 /* Forward definitions of types.  */
 typedef struct minipool_node    Mnode;
@@ -133,6 +134,12 @@ static void arm_output_function_prologue (FILE *, HOST_WIDE_INT);
 static int arm_comp_type_attributes (const_tree, const_tree);
 static void arm_set_default_type_attributes (tree);
 static int arm_adjust_cost (rtx, rtx, rtx, int);
+static int arm_variable_issue (FILE *, int, rtx, int);
+static void arm_sched_init (FILE *, int, int);
+static void arm_sched_finish (FILE *, int);
+static int arm_sched_reorder (FILE *, int, rtx *, int *, int);
+static void arm_dfa_post_advance_cycle (state_t state);
+
 static int optimal_immediate_sequence (enum rtx_code code,
 				       unsigned HOST_WIDE_INT val,
 				       struct four_ints *return_sequence);
@@ -361,6 +368,19 @@ static const struct attribute_spec arm_attribute_table[] =
 #undef  TARGET_SCHED_ADJUST_COST
 #define TARGET_SCHED_ADJUST_COST arm_adjust_cost
 
+#undef TARGET_SCHED_VARIABLE_ISSUE
+#define TARGET_SCHED_VARIABLE_ISSUE arm_variable_issue
+#undef TARGET_SCHED_INIT
+#define TARGET_SCHED_INIT arm_sched_init
+#undef TARGET_SCHED_FINISH
+#define TARGET_SCHED_FINISH arm_sched_finish
+#undef TARGET_SCHED_REORDER
+#define TARGET_SCHED_REORDER arm_sched_reorder
+#undef TARGET_SCHED_REORDER2
+#define TARGET_SCHED_REORDER2 arm_sched_reorder
+#undef TARGET_SCHED_DFA_POST_ADVANCE_CYCLE
+#define TARGET_SCHED_DFA_POST_ADVANCE_CYCLE arm_dfa_post_advance_cycle
+
 #undef TARGET_ENCODE_SECTION_INFO
 #ifdef ARM_PE
 #define TARGET_ENCODE_SECTION_INFO  arm_pe_encode_section_info
@@ -804,6 +824,9 @@ int arm_condexec_mask = 0;
 /* The number of bits used in arm_condexec_mask.  */
 int arm_condexec_masklen = 0;
 
+/* Last scheduled instruction.  */
+static rtx last_scheduled_insn;
+
 /* The condition codes of the ARM, and the inverse function.  */
 static const char * const arm_condition_codes[] =
 {
@@ -8428,6 +8451,101 @@ fa726te_sched_adjust_cost (rtx insn, rtx link, rtx dep, int * cost)
   return true;
 }
 
+/* Holds correct CAN_ISSUE_MORE so arm_sched_reorder can return correct value.  */
+static int cached_can_issue_more;
+
+/* Save CAN_ISSUE_MORE in CACHED_CAN_ISSUE_MORE.  Also move the code from 
+   haifa-sched.c that won't work with arm_variable_issue hook defined.  */
+static int
+arm_variable_issue (FILE *dump ATTRIBUTE_UNUSED,
+                    int sched_verbose ATTRIBUTE_UNUSED,
+                    rtx insn,
+                    int can_issue_more)
+{
+  last_scheduled_insn = insn;
+
+  cached_can_issue_more = can_issue_more;
+
+  if (GET_CODE (PATTERN (insn)) != USE
+      && GET_CODE (PATTERN (insn)) != CLOBBER)
+    cached_can_issue_more = can_issue_more - 1;
+
+  return cached_can_issue_more;
+}
+
+/* Init LAST_SCHEDULED_INSN.  */
+static void
+arm_sched_init (FILE *dump ATTRIBUTE_UNUSED,
+                int sched_verbose ATTRIBUTE_UNUSED,
+                int max_ready ATTRIBUTE_UNUSED)
+{
+  last_scheduled_insn = NULL_RTX;
+}
+
+/* Reset LAST_SCHEDULED_INSN.  */
+static void
+arm_sched_finish (FILE *dump ATTRIBUTE_UNUSED, 
+                  int sched_verbose ATTRIBUTE_UNUSED)
+{
+  last_scheduled_insn = NULL_RTX;
+}
+
+/* Remove the instruction at index LOWER from ready queue READY and
+   reinsert it in front of the instruction at index HIGHER.  LOWER must
+   be <= HIGHER.  */
+static void
+arm_promote_ready (rtx *ready, int lower, int higher)
+{
+  rtx new_head;
+  int i;
+
+  new_head = ready[lower];
+  for (i = lower; i < higher; i++)
+    ready[i] = ready[i + 1];
+  ready[i] = new_head;
+}
+
+/* Move conditional instructions to the top of the ready list if the last
+   scheduled insn was conditional, and vice versa.  This is only done for 
+   insns with the same INSN_PRIORITY, so works only for resolving tie-breaks.  */
+static int
+arm_sched_reorder (FILE *dump ATTRIBUTE_UNUSED,
+                   int sched_verbose ATTRIBUTE_UNUSED, rtx *ready,
+                   int *pn_ready, int clock_var ATTRIBUTE_UNUSED)
+{
+  if (reload_completed && last_scheduled_insn != NULL_RTX)
+    {
+      rtx pat_last = PATTERN (last_scheduled_insn);
+      bool cond = (GET_CODE (pat_last) == COND_EXEC);
+      int i, n = *pn_ready;
+
+      /* Find highest (non-)conditional insn (the same as COND).  */
+      for (i = n - 1; i >= 0; i--)
+        {
+          rtx insn = ready[i];
+	  /* Only tie-break order of insns with the same INSN_PRIORITY.  */
+	  if (INSN_PRIORITY (insn) < INSN_PRIORITY (ready[n - 1]))
+	    break;
+
+          if (cond == (GET_CODE (PATTERN (insn)) == COND_EXEC))
+	    {
+	      if (i != n - 1)
+	        arm_promote_ready (ready, i, n - 1);
+	      break;
+	    }
+        }
+    }
+
+  return cached_can_issue_more;
+}
+
+/* Init CACHED_CAN_ISSUE_MORE.  */
+static void
+arm_dfa_post_advance_cycle (state_t state ATTRIBUTE_UNUSED)
+{
+  cached_can_issue_more = arm_issue_rate ();
+}
+
 /* This function implements the target macro TARGET_SCHED_ADJUST_COST.
    It corrects the value of COST based on the relationship between
    INSN and DEP through the dependence LINK.  It returns the new

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]