This is the mail archive of the gcc@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]

Re: interaction between shorten_branches and delay slot scheduling


Daniel Towner <daniel.towner@picochip.com> writes:
> Am I doing something fundamentally wrong with the way I am defining the
> length attribute, or the delay slot attribute?

No, I think this just The Way Things Are.  I had a similar problem
with the h8sx delayed branch, and ended up reversing the delay slot
and branch if the branch turned out to be too long.  Maybe a similar
thing will work for your port?

The full code is in config/h8300, but I've snipped the most relevant
parts below.  And no, it's not pretty. ;)  I don't think it's too bad
conceptually though.  There was never any guarantee that the delay slot
insn would be emitted at the very end; if the target has a limited range
of conditional branch (as MIPS does) then we generate a branch around an
unconditional jump, and the delay slot goes in the branch-around instead.

Richard


(define_attr "length" ""
  (cond [(eq_attr "type" "branch")
	 ;; In a forward delayed branch, (pc) represents the end of the
	 ;; delay sequence, not the end of the branch itself.
	 (if_then_else (and (ge (minus (match_dup 0) (pc))
				(const_int -126))
			    (le (plus (minus (match_dup 0) (pc))
				      (symbol_ref "DELAY_SLOT_LENGTH (insn)"))
				(const_int 126)))
		       (const_int 2)
                       ...

;; Only allow jumps to have a delay slot if we think they might
;; be short enough.  This is just an optimization: we don't know
;; for certain whether they will be or not.
(define_delay (and (eq_attr "delay_slot" "jump")
		   (eq (symbol_ref "get_attr_length (insn)") (const_int 2)))
  [(eq_attr "can_delay" "yes")
   (nil)
   (nil)])

(define_insn "jump"
  [(set (pc)
	(label_ref (match_operand 0 "" "")))]
  ""
  "*
{
  if (final_sequence != 0)
    {
      if (get_attr_length (insn) == 2)
	return \"bra/s	%l0\";
      else
	{
	  /* The branch isn't short enough to use bra/s.  Output the
	     branch and delay slot in their normal order.

	     If this is a backward branch, it will now be branching two
	     bytes further than previously thought.  The length-based
	     test for bra vs. jump is very conservative though, so the
	     branch will still be within range.  */
	  rtvec vec;
	  int seen;

	  vec = XVEC (final_sequence, 0);
	  final_sequence = 0;
	  final_scan_insn (RTVEC_ELT (vec, 1), asm_out_file, optimize, 1, & seen);
	  final_scan_insn (RTVEC_ELT (vec, 0), asm_out_file, optimize, 1, & seen);
	  INSN_DELETED_P (RTVEC_ELT (vec, 1)) = 1;
	  return \"\";
	}
    }
  ...
}"
  [(set_attr "type" "branch")
   (set (attr "delay_slot")
	(if_then_else (ne (symbol_ref "TARGET_H8300SX") (const_int 0))
		      (const_string "jump")
		      (const_string "none")))
   (set_attr "cc" "none")])


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