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.
@@ -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