diff mbox

C6X: Fix floating point scheduling scheduling bug

Message ID 4F3AFF25.9010208@codesourcery.com
State New
Headers show

Commit Message

Bernd Schmidt Feb. 15, 2012, 12:41 a.m. UTC
We have code in the backend to predicate instructions with long delays
while scheduling, so that they can be placed in jump delay slots.  For
example,

[a1] b label
     nop 3
     ldw *a2, a0  ;; this insn is from the basic block after the branch
     nop
;; branch occurs here

is not safe even if A0 is not used at the branch target, since the load
will place data into A0 after the branch occurs, and we don't know
whether that conflicts with the code there.

We can make this safe by changing it into

[a1]  b label
      nop 3
[!a1] ldw *a2, a0
      nop
;; branch occurs here

since we know we're scheduling extended basic blocks, so we control the
code in the fallthru path.

This all works except for certain floating point instructions, which not
only store their destination after a given number of cycles, but which
also reserve functional units for multiple cycles. In the testcase I
have, it's a CMPLTDP instruction which can't be allowed to be placed in
the last delay cycle of the branch, since it reserves its units for two
cycles.

Fixed with this patch. Committed.


Bernd
* config/c6x/c6x.md (reserve_cycles): New attribute.
	* config/c6x/c6x.c (c6x_sched_reorder_1): Ensure insns we predicate
	don't reserve functional units after the branch occurs.
diff mbox

Patch

Index: gcc/config/c6x/c6x.c
===================================================================
--- gcc/config/c6x/c6x.c	(revision 184237)
+++ gcc/config/c6x/c6x.c	(working copy)
@@ -4196,13 +4196,14 @@  c6x_sched_reorder_1 (rtx *ready, int *pn
 	  bool is_asm = (icode < 0
 			 && (GET_CODE (PATTERN (insn)) == ASM_INPUT
 			     || asm_noperands (PATTERN (insn)) >= 0));
-	  int this_cycles;
+	  int this_cycles, rsrv_cycles;
 	  enum attr_type type;
 
 	  gcc_assert (!is_asm);
 	  if (icode < 0)
 	    continue;
 	  this_cycles = get_attr_cycles (insn);
+	  rsrv_cycles = get_attr_reserve_cycles (insn);
 	  type = get_attr_type (insn);
 	  /* Treat branches specially; there is also a hazard if two jumps
 	     end at the same cycle.  */
@@ -4211,6 +4212,7 @@  c6x_sched_reorder_1 (rtx *ready, int *pn
 	  if (clock_var + this_cycles <= first_cycle)
 	    continue;
 	  if ((first_jump > 0 && clock_var + this_cycles > second_cycle)
+	      || clock_var + rsrv_cycles > first_cycle
 	      || !predicate_insn (insn, first_cond, false))
 	    {
 	      memmove (ready + 1, ready, (insnp - ready) * sizeof (rtx));
Index: gcc/config/c6x/c6x.md
===================================================================
--- gcc/config/c6x/c6x.md	(revision 184237)
+++ gcc/config/c6x/c6x.md	(working copy)
@@ -201,6 +201,17 @@  (define_attr "cycles" ""
 	 (eq_attr "type" "mpysp2dp") (const_int 5)]
 	(const_int 1)))
 
+;; The number of cycles during which the instruction reserves functional
+;; units.
+(define_attr "reserve_cycles" ""
+  (cond [(eq_attr "type" "cmpdp") (const_int 2)
+	 (eq_attr "type" "adddp") (const_int 2)
+	 (eq_attr "type" "mpydp") (const_int 4)
+	 (eq_attr "type" "mpyi") (const_int 4)
+	 (eq_attr "type" "mpyid") (const_int 4)
+	 (eq_attr "type" "mpyspdp") (const_int 2)]
+	(const_int 1)))
+
 (define_attr "predicable" "no,yes"
   (const_string "yes"))