arc.c (arc_predicate_delay_insns): New function.
authorJoern Rennecke <joern.rennecke@embecosm.com>
Sat, 16 Nov 2013 11:53:21 +0000 (11:53 +0000)
committerJoern Rennecke <amylaar@gcc.gnu.org>
Sat, 16 Nov 2013 11:53:21 +0000 (11:53 +0000)
        * config/arc/arc.c (arc_predicate_delay_insns): New function.
        (pass_data_arc_predicate_delay_insns): New pass_data instance.
        (pass_arc_predicate_delay_insns): New subclass of rtl_opt_class.
        (make_pass_arc_predicate_delay_insns): New function.
        (arc_init): Register pass_arc_predicate_delay_insns if
        flag_delayed_branch is active.

From-SVN: r204901

gcc/ChangeLog
gcc/config/arc/arc.c

index e53a995..5cb07b7 100644 (file)
@@ -1,5 +1,14 @@
 2013-11-16  Joern Rennecke  <joern.rennecke@embecosm.com>
 
+       * config/arc/arc.c (arc_predicate_delay_insns): New function.
+       (pass_data_arc_predicate_delay_insns): New pass_data instance.
+       (pass_arc_predicate_delay_insns): New subclass of rtl_opt_class.
+       (make_pass_arc_predicate_delay_insns): New function.
+       (arc_init): Register pass_arc_predicate_delay_insns if
+       flag_delayed_branch is active.
+
+2013-11-16  Joern Rennecke  <joern.rennecke@embecosm.com>
+
        * config/arc/constraints.md (Rcq): Simplify register number test.
 
 2013-11-15  Aldy Hernandez  <aldyh@redhat.com>
index 7b1853b..f813c90 100644 (file)
@@ -632,6 +632,44 @@ make_pass_arc_ifcvt (gcc::context *ctxt)
   return new pass_arc_ifcvt (ctxt);
 }
 
+static unsigned arc_predicate_delay_insns (void);
+
+namespace {
+
+const pass_data pass_data_arc_predicate_delay_insns =
+{
+  RTL_PASS,
+  "arc_predicate_delay_insns",         /* name */
+  OPTGROUP_NONE,                       /* optinfo_flags */
+  false,                               /* has_gate */
+  true,                                        /* has_execute */
+  TV_IFCVT2,                           /* tv_id */
+  0,                                   /* properties_required */
+  0,                                   /* properties_provided */
+  0,                                   /* properties_destroyed */
+  0,                                   /* todo_flags_start */
+  TODO_df_finish                       /* todo_flags_finish */
+};
+
+class pass_arc_predicate_delay_insns : public rtl_opt_pass
+{
+public:
+  pass_arc_predicate_delay_insns(gcc::context *ctxt)
+  : rtl_opt_pass(pass_data_arc_predicate_delay_insns, ctxt)
+  {}
+
+  /* opt_pass methods: */
+  unsigned int execute () { return arc_predicate_delay_insns (); }
+};
+
+} // anon namespace
+
+rtl_opt_pass *
+make_pass_arc_predicate_delay_insns (gcc::context *ctxt)
+{
+  return new pass_arc_predicate_delay_insns (ctxt);
+}
+
 /* Called by OVERRIDE_OPTIONS to initialize various things.  */
 
 void
@@ -752,6 +790,16 @@ arc_init (void)
       register_pass (&arc_ifcvt4_info);
       register_pass (&arc_ifcvt5_info);
     }
+
+  if (flag_delayed_branch)
+    {
+      opt_pass *pass_arc_predicate_delay_insns
+       = make_pass_arc_predicate_delay_insns (g);
+      struct register_pass_info arc_predicate_delay_info
+       = { pass_arc_predicate_delay_insns, "dbr", 1, PASS_POS_INSERT_AFTER };
+
+      register_pass (&arc_predicate_delay_info);
+    }
 }
 
 /* Check ARC options, generate derived target attributes.  */
@@ -8297,6 +8345,74 @@ arc_ifcvt (void)
   return 0;
 }
 
+/* Find annulled delay insns and convert them to use the appropriate predicate.
+   This allows branch shortening to size up these insns properly.  */
+
+static unsigned
+arc_predicate_delay_insns (void)
+{
+  for (rtx insn = get_insns (); insn; insn = NEXT_INSN (insn))
+    {
+      rtx pat, jump, dlay, src, cond, *patp;
+      int reverse;
+
+      if (!NONJUMP_INSN_P (insn)
+         || GET_CODE (pat = PATTERN (insn)) != SEQUENCE)
+       continue;
+      jump = XVECEXP (pat, 0, 0);
+      dlay = XVECEXP (pat, 0, 1);
+      if (!JUMP_P (jump) || !INSN_ANNULLED_BRANCH_P (jump))
+       continue;
+      /* If the branch insn does the annulling, leave the delay insn alone.  */
+      if (!TARGET_AT_DBR_CONDEXEC && !INSN_FROM_TARGET_P (dlay))
+       continue;
+      /* ??? Could also leave DLAY un-conditionalized if its target is dead
+        on the other path.  */
+      gcc_assert (GET_CODE (PATTERN (jump)) == SET);
+      gcc_assert (SET_DEST (PATTERN (jump)) == pc_rtx);
+      src = SET_SRC (PATTERN (jump));
+      gcc_assert (GET_CODE (src) == IF_THEN_ELSE);
+      cond = XEXP (src, 0);
+      if (XEXP (src, 2) == pc_rtx)
+       reverse = 0;
+      else if (XEXP (src, 1) == pc_rtx)
+       reverse = 1;
+      else
+       gcc_unreachable ();
+      if (!INSN_FROM_TARGET_P (dlay) != reverse)
+       {
+         enum machine_mode ccm = GET_MODE (XEXP (cond, 0));
+         enum rtx_code code = reverse_condition (GET_CODE (cond));
+         if (code == UNKNOWN || ccm == CC_FP_GTmode || ccm == CC_FP_GEmode)
+           code = reverse_condition_maybe_unordered (GET_CODE (cond));
+
+         cond = gen_rtx_fmt_ee (code, GET_MODE (cond),
+                                copy_rtx (XEXP (cond, 0)),
+                                copy_rtx (XEXP (cond, 1)));
+       }
+      else
+       cond = copy_rtx (cond);
+      patp = &PATTERN (dlay);
+      pat = *patp;
+      /* dwarf2out.c:dwarf2out_frame_debug_expr doesn't know
+        what to do with COND_EXEC.  */
+      if (RTX_FRAME_RELATED_P (dlay))
+       {
+         /* As this is the delay slot insn of an anulled branch,
+            dwarf2out.c:scan_trace understands the anulling semantics
+            without the COND_EXEC.  */
+         rtx note = alloc_reg_note (REG_FRAME_RELATED_EXPR, pat,
+                                    REG_NOTES (dlay));
+         validate_change (dlay, &REG_NOTES (dlay), note, 1);
+       }
+      pat = gen_rtx_COND_EXEC (VOIDmode, cond, pat);
+      validate_change (dlay, patp, pat, 1);
+      if (!apply_change_group ())
+       gcc_unreachable ();
+    }
+  return 0;
+}
+
 /* For ARC600: If a write to a core reg >=32 appears in a delay slot
   (other than of a forward brcc), it creates a hazard when there is a read
   of the same register at the branch target.  We can't know what is at the