Commit 99457156 by Jeff Law

pa.md (smin, [...]): New patterns.

	* pa.md (smin, umin, smax, umax): New patterns.

	* pa.md (cbranch define_delay): Enable nullification of
	conditional branch delay slots (based upon branch direction).
	(conditional branch patterns): Call output_cbranch to get the
	correct output template.  Long conditional branches with an
	annulled delay slot have a length of 3.
	(branch on bit patterns): Call output_bb to get the correct
	output template.  Long branches with an annulled delay slot have
	a length of 3.
	(decrement and branch pattern): Handle nullification of long

From-SVN: r3906
parent f2878c6b
......@@ -65,19 +65,36 @@
(const_string "true")
(const_string "false")))
;; Disallow instructions which use the FPU since they will tie up the FPU
;; even if the instruction is nullified.
(define_attr "in_nullified_branch_delay" "false,true"
(if_then_else (and (eq_attr "type" "!branch,cbranch,fbranch,call,dyncall,multi,milli,fpcc,fpalu,fpmul,fpdivsgl,fpdivdbl,fpsqrtsgl,fpsqrtdbl")
(eq_attr "length" "1"))
(const_string "true")
(const_string "false")))
;; Unconditional branch, call, and millicode call delay slot description.
(define_delay (eq_attr "type" "branch,call,milli")
[(eq_attr "in_branch_delay" "true") (nil) (nil)])
;; Floating point conditional branch delay slot description.
;; Floating point conditional branch delay slot description and
(define_delay (eq_attr "type" "fbranch")
[(eq_attr "in_branch_delay" "true")
(eq_attr "in_branch_delay" "true")
(eq_attr "in_nullified_branch_delay" "true")
(nil)])
;; Integer conditional branch delay slot description.
;; Nullification of conditional branches on the PA is dependent on the
;; direction of the branch. Forward branches nullify true (direction > 0),
;; and backward branches nullify false (direction < 0).
;; If direction == 0, then the direction is unknown and we do not allow
;; any nullification.
(define_delay (eq_attr "type" "cbranch")
[(eq_attr "in_branch_delay" "true") (nil) (nil)])
[(eq_attr "in_branch_delay" "true")
(and (eq_attr "in_nullified_branch_delay" "true")
(attr_flag "forward"))
(and (eq_attr "in_nullified_branch_delay" "true")
(attr_flag "backward"))])
;; Function units of the HPPA. The following data is for the "Snake"
;; (Mustang CPU + Timex FPU) because that's what I have the docs for.
......@@ -463,6 +480,52 @@
[(set_attr "type" "binary,binary")
(set_attr "length" "2,3")])
;; Signed/Unsigned minimum and maximum patterns.
(define_insn "sminsi3"
[(set (match_operand:SI 0 "register_operand" "=r,r,r")
(smin:SI (match_operand:SI 1 "register_operand" "%r,0,0")
(match_operand:SI 2 "arith11_operand" "M,r,I")))]
""
"@
comclr,> %1,%2,%0\;copy %1,%0
comclr,> %2,%0,0\;copy %2,%0
comiclr,> %2,%0,0\;ldi %2,%0"
[(set_attr "type" "multi,multi,multi")
(set_attr "length" "2,2,2")])
(define_insn "uminsi3"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(umin:SI (match_operand:SI 1 "register_operand" "%0,0")
(match_operand:SI 2 "arith11_operand" "r,I")))]
""
"@
comclr,>> %2,%0,0\;copy %2,%0
comiclr,>> %2,%0,0\;ldi %2,%0"
[(set_attr "type" "multi,multi")
(set_attr "length" "2,2")])
(define_insn "smaxsi3"
[(set (match_operand:SI 0 "register_operand" "=r,r,r")
(smax:SI (match_operand:SI 1 "register_operand" "%r,0,0")
(match_operand:SI 2 "arith11_operand" "M,r,I")))]
""
"@
comclr,< %1,%2,%0\;copy %1,%0
comclr,< %2,%0,0\;copy %2,%0
comiclr,< %2,%0,0\;ldi %2,%0"
[(set_attr "type" "multi,multi,multi")
(set_attr "length" "2,2,2")])
(define_insn "umaxsi3"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(umax:SI (match_operand:SI 1 "register_operand" "%0,0")
(match_operand:SI 2 "arith11_operand" "r,I")))]
""
"@
comclr,<< %2,%0,0\;copy %2,%0
comiclr,<< %2,%0,0\;ldi %2,%0"
[(set_attr "type" "multi,multi")
(set_attr "length" "2,2")])
;;; Experimental conditional move patterns
; We need the first constraint alternative in order to avoid
......@@ -676,6 +739,9 @@
;; Match the branch patterns.
;; Note a long backward conditional branch with an annulled delay slot
;; has a length of 3.
(define_insn ""
[(set (pc)
(if_then_else
......@@ -687,14 +753,18 @@
""
"*
{
return (get_attr_length (insn) == 1
? \"com%I2b,%S3 %2,%1,%0%#\" : \"com%I2clr,%B3 %2,%1,0\;bl %0,0%#\");
return output_cbranch (operands, INSN_ANNULLED_BRANCH_P (insn),
get_attr_length (insn), 0, insn);
}"
[(set_attr "type" "cbranch")
(set (attr "length") (if_then_else (lt (abs (minus (match_dup 0)
(plus (pc) (const_int 2))))
[(set_attr "type" "cbranch")
(set (attr "length")
(cond [(lt (abs (minus (match_dup 0) (plus (pc) (const_int 2))))
(const_int 1023))
(const_int 1)
(and (lt (match_dup 0) (pc))
(eq (symbol_ref "INSN_ANNULLED_BRANCH_P (insn)")
(const_int 1)))
(const_int 3)]
(const_int 2)))])
;; Match the negated branch.
......@@ -710,18 +780,21 @@
""
"*
{
return (get_attr_length (insn) == 1
? \"com%I2b,%B3 %2,%1,%0%#\" : \"com%I2clr,%S3 %2,%1,0%#\;bl %0,0%#\");
return output_cbranch (operands, INSN_ANNULLED_BRANCH_P (insn),
get_attr_length (insn), 1, insn);
}"
[(set_attr "type" "cbranch")
(set (attr "length") (if_then_else (lt (abs (minus (match_dup 0)
(plus (pc) (const_int 2))))
[(set_attr "type" "cbranch")
(set (attr "length")
(cond [(lt (abs (minus (match_dup 0) (plus (pc) (const_int 2))))
(const_int 1023))
(const_int 1)
(and (lt (match_dup 0) (pc))
(eq (symbol_ref "INSN_ANNULLED_BRANCH_P (insn)")
(const_int 1)))
(const_int 3)]
(const_int 2)))])
;; Branch on bit patterns
;; Branch on Bit patterns.
(define_insn ""
[(set (pc)
(if_then_else
......@@ -734,18 +807,20 @@
""
"*
{
if (operands[3] == pc_rtx)
return (get_attr_length (insn) == 1
? \"bb,< %0,%1,%2%#\" : \"extrs,>= %0,%1,1,0\;bl %2,0%#\");
else
return (get_attr_length (insn) == 1
? \"bb,>= %0,%1,%3%#\" : \"extrs,< %0,%1,1,0\;bl %3,0%#\");
return output_bb (operands, INSN_ANNULLED_BRANCH_P (insn),
get_attr_length (insn),
(operands[3] != pc_rtx),
insn, 0);
}"
[(set_attr "type" "cbranch")
(set (attr "length") (if_then_else (lt (abs (minus (match_dup 0)
(plus (pc) (const_int 2))))
[(set_attr "type" "cbranch")
(set (attr "length")
(cond [(lt (abs (minus (match_dup 0) (plus (pc) (const_int 2))))
(const_int 1023))
(const_int 1)
(and (lt (match_dup 0) (pc))
(eq (symbol_ref "INSN_ANNULLED_BRANCH_P (insn)")
(const_int 1)))
(const_int 3)]
(const_int 2)))])
(define_insn ""
......@@ -760,19 +835,22 @@
""
"*
{
if (operands[3] == pc_rtx)
return (get_attr_length (insn) == 1
? \"bb,>= %0,%1,%2%#\" : \"extrs,< %0,%1,1,0\;bl %2,0%#\");
else
return (get_attr_length (insn) == 1
? \"bb,< %0,%1,%3%#\" : \"extrs,>= %0,%1,1,0\;bl %3,0%#\");
return output_bb (operands, INSN_ANNULLED_BRANCH_P (insn),
get_attr_length (insn),
(operands[3] != pc_rtx),
insn, 1);
}"
[(set_attr "type" "cbranch")
(set (attr "length") (if_then_else (lt (abs (minus (match_dup 0)
(plus (pc) (const_int 2))))
[(set_attr "type" "cbranch")
(set (attr "length")
(cond [(lt (abs (minus (match_dup 0) (plus (pc) (const_int 2))))
(const_int 1023))
(const_int 1)
(and (lt (match_dup 0) (pc))
(eq (symbol_ref "INSN_ANNULLED_BRANCH_P (insn)")
(const_int 1)))
(const_int 3)]
(const_int 2)))])
;; Floating point branches
(define_insn ""
......@@ -2744,13 +2822,13 @@
return \"depi %3,%2+%1-1,%1,%0\";
}")
;; The dbra pattern from hell.
;; This insn is used for some loop tests, typically loops reversed when
;; strength reduction is used. It is actually created when the instruction
;; combination phase combines the special loop test. Since this insn
;; is both a jump insn and has an output, it must deal with it's own
;; reloads, hence the `m' constraints. The `!' constraints direct reload
;; to not choose the register alternatives in the event a reload is needed.
(define_insn "decrement_and_branch_until_zero"
[(set (pc)
(if_then_else
......@@ -2766,41 +2844,98 @@
"find_reg_note (insn, REG_NONNEG, 0)"
"*
{
if (INSN_ANNULLED_BRANCH_P (insn))
{
/* Loop counter is in a register. */
if (which_alternative == 0)
/* Short branch. Normal handling of nullification. */
if (get_attr_length (insn) == 1)
return \"addib,>=,n -1,%0,%1\";
/* Long Conditional branch forward with delay slot nullified if
branch is taken. */
else if (get_attr_length (insn) == 2)
return \"addi,< -1,%0,%0\;bl,n %1,0\";
/* Long Conditional branch backwards with delay slot nullified
if branch is not taken. */
else
return \"addib,< -1,%0,.+16\;nop\;bl %1,0\";
else
{
/* Must reload loop counter from memory. Ugly. */
output_asm_insn (\"ldw %0,%2\;ldo -1(%2),%2\;stw %2,%0\", operands);
/* Short branch. Normal handling of nullification. */
if (get_attr_length (insn) == 4)
return \"comb,>,n 0,%2,%1\";
/* Long Conditional branch forward with delay slot nullified if
branch is taken. */
else if (get_attr_length (insn) == 5)
return \"comclr,<= 0,%2,0\;bl,n %1,0\";
else
/* Long Conditional branch backwards with delay slot nullified
if branch is not taken. */
return \"comb,<= 0,%2,.+16\;nop\;bl %1,0\";
}
}
else
{
/* We are not nullifying the delay slot. Much simpler. */
if (which_alternative == 0)
if (get_attr_length (insn) == 1)
/* Short form. */
return \"addib,>= -1,%0,%1%#\";
else
return \"addi,< -1,%0,%0\;bl %1,0%#\";
/* Long form. */
return \"addi,< -1,%0,%0\;bl%* %1,0\";
else
{
/* Reload loop counter from memory. */
output_asm_insn (\"ldw %0,%2\;ldo -1(%2),%2\;stw %2,%0\", operands);
/* Short form. */
if (get_attr_length (insn) == 4)
return \"comb,> 0,%2,%1%#\";
/* Long form. */
else
return \"comclr,<= 0,%2,0\;bl %1,0%#\";
return \"comclr,<= 0,%2,0\;bl%* %1,0\";
}
}
}"
;; Do not expect to understand this the first time through.
[(set_attr "type" "cbranch")
(set (attr "length")
(if_then_else (eq (symbol_ref "which_alternative") (const_int 0))
(if_then_else (lt (abs (minus (match_dup 1)
(plus (pc) (const_int 2))))
(if_then_else
(eq_attr "alternative" "0")
;; Loop counter in register case.
(cond [(lt (abs (minus (match_dup 1) (plus (pc) (const_int 2))))
(const_int 1023))
;; Short branch has a length of 1.
(const_int 1)
;; Long backward branch with nullified delay slot has length of 3.
(and (lt (match_dup 1) (pc))
(eq (symbol_ref "INSN_ANNULLED_BRANCH_P (insn)")
(const_int 1)))
(const_int 3)]
;; Default others to 2.
;; Long branches with unfilled delay slots --or--
;; Long forward with nullified delay slot.
(const_int 2))
(if_then_else (lt (match_dup 1)
(pc))
(if_then_else
(lt (abs (minus (match_dup 1)
(plus (pc)
(const_int 5))))
;; Loop counter in memory case. Similar to above except we pay
;; 3 extra insns in each case for reloading the counter into a register.
(if_then_else (lt (match_dup 1) (pc))
(cond [(lt (abs (minus (match_dup 1) (plus (pc) (const_int 5))))
(const_int 1023))
;; Short branch has length of 4 (the reloading costs 3 insns)
(const_int 4)
(and (lt (match_dup 1) (pc))
(eq (symbol_ref "INSN_ANNULLED_BRANCH_P (insn)")
(const_int 1)))
;; Long backward branch with nullified delay slot has length of 6.
(const_int 6)]
;; Default others to 5.
;; Long branches with unfilled delay slots --or--
;; Long forward with nullified delay slot.
(const_int 5))
(if_then_else
(lt (abs (minus (match_dup 1)
(plus (pc)
(const_int 2))))
(if_then_else (lt (abs (minus (match_dup 1)
(plus (pc) (const_int 2))))
(const_int 1023))
(const_int 4)
(const_int 5)))))])
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment