arm.md (cmpsi2_addneg): New ARM pattern.

* arm.md (cmpsi2_addneg): New ARM pattern. Add peephole2 to generate
it.
(cbranchne_decr1): New Thumb pattern.
* arm.c (arm_addimm_operand): New insn predicate.
* arm-protos.h: Add a prototype for it.
* arm.h (PREDICATE_CODES): Add it.

From-SVN: r72188
This commit is contained in:
Richard Earnshaw 2003-10-07 08:49:36 +00:00 committed by Richard Earnshaw
parent 79ae11c4a3
commit f9b9980e6d
5 changed files with 176 additions and 0 deletions

View File

@ -1,3 +1,12 @@
2003-10-07 Richard Earnshaw <rearnsha@arm.com>
* arm.md (cmpsi2_addneg): New ARM pattern. Add peephole2 to generate
it.
(cbranchne_decr1): New Thumb pattern.
* arm.c (arm_addimm_operand): New insn predicate.
* arm-protos.h: Add a prototype for it.
* arm.h (PREDICATE_CODES): Add it.
2003-10-07 Dorit Naishlos <dorit@il.ibm.com>
* sched-int.h (sched_info): New field

View File

@ -65,6 +65,7 @@ extern int arm_reload_memory_operand (rtx, enum machine_mode);
extern int arm_rhs_operand (rtx, enum machine_mode);
extern int arm_rhsm_operand (rtx, enum machine_mode);
extern int arm_add_operand (rtx, enum machine_mode);
extern int arm_addimm_operand (rtx, enum machine_mode);
extern int arm_not_operand (rtx, enum machine_mode);
extern int offsettable_memory_operand (rtx, enum machine_mode);
extern int alignable_memory_operand (rtx, enum machine_mode);

View File

@ -3750,6 +3750,15 @@ arm_add_operand (rtx op, enum machine_mode mode)
|| const_ok_for_arm (-INTVAL (op)))));
}
/* Return TRUE for valid ARM constants (or when valid if negated). */
int
arm_addimm_operand (rtx op, enum machine_mode mode)
{
return (GET_CODE (op) == CONST_INT
&& (const_ok_for_arm (INTVAL (op))
|| const_ok_for_arm (-INTVAL (op))));
}
int
arm_not_operand (rtx op, enum machine_mode mode)
{

View File

@ -2681,6 +2681,7 @@ extern int making_const_table;
{"arm_hard_register_operand", {REG}}, \
{"f_register_operand", {SUBREG, REG}}, \
{"arm_add_operand", {SUBREG, REG, CONST_INT}}, \
{"arm_addimm_operand", {CONST_INT}}, \
{"fpa_add_operand", {SUBREG, REG, CONST_DOUBLE}}, \
{"fpa_rhs_operand", {SUBREG, REG, CONST_DOUBLE}}, \
{"arm_rhs_operand", {SUBREG, REG, CONST_INT}}, \

View File

@ -667,6 +667,60 @@
[(set_attr "conds" "set")]
)
;; This is the canonicalization of addsi3_compare0_for_combiner when the
;; addend is a constant.
(define_insn "*cmpsi2_addneg"
[(set (reg:CC CC_REGNUM)
(compare:CC
(match_operand:SI 1 "s_register_operand" "r,r")
(match_operand:SI 2 "arm_addimm_operand" "I,L")))
(set (match_operand:SI 0 "s_register_operand" "=r,r")
(plus:SI (match_dup 1)
(match_operand:SI 3 "arm_addimm_operand" "L,I")))]
"TARGET_ARM && INTVAL (operands[2]) == -INTVAL (operands[3])"
"@
sub%?s\\t%0, %1, %2
add%?s\\t%0, %1, #%n2"
[(set_attr "conds" "set")]
)
;; Convert the sequence
;; sub rd, rn, #1
;; cmn rd, #1 (equivalent to cmp rd, #-1)
;; bne dest
;; into
;; subs rd, rn, #1
;; bcs dest ((unsigned)rn >= 1)
;; similarly for the beq variant using bcc.
;; This is a common looping idiom (while (n--))
(define_peephole2
[(set (match_operand:SI 0 "s_register_operand" "")
(plus:SI (match_operand:SI 1 "s_register_operand" "")
(const_int -1)))
(set (match_operand 2 "cc_register" "")
(compare (match_dup 0) (const_int -1)))
(set (pc)
(if_then_else (match_operator 3 "equality_operator"
[(match_dup 2) (const_int 0)])
(match_operand 4 "" "")
(match_operand 5 "" "")))]
"TARGET_ARM && peep2_reg_dead_p (3, operands[2])"
[(parallel[
(set (match_dup 2)
(compare:CC
(match_dup 1) (const_int 1)))
(set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
(set (pc)
(if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
(match_dup 4)
(match_dup 5)))]
"operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
? GEU : LTU),
VOIDmode,
operands[2], const0_rtx);"
)
;; The next four insns work because they compare the result with one of
;; the operands, and we know that the use of the condition code is
;; either GEU or LTU, so we can use the carry flag from the addition
@ -5192,6 +5246,108 @@
(const_int 8))))]
)
(define_insn "*cbranchne_decr1"
[(set (pc)
(if_then_else (match_operator 3 "equality_operator"
[(match_operand:SI 2 "s_register_operand" "l,l,1,l")
(const_int 0)])
(label_ref (match_operand 4 "" ""))
(pc)))
(set (match_operand:SI 0 "s_register_operand" "=l,?h,?m,?m")
(plus:SI (match_dup 2) (const_int -1)))
(clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
"TARGET_THUMB"
"*
{
rtx cond[2];
cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
? GEU : LTU),
VOIDmode, NULL, NULL);
cond[1] = operands[4];
if (which_alternative == 0)
output_asm_insn (\"sub\\t%0, %2, #1\", operands);
else if (which_alternative == 1)
{
/* We must provide an alternative for a hi reg because reload
cannot handle output reloads on a jump instruction, but we
can't subtract into that. Fortunately a mov from lo to hi
does not clobber the condition codes. */
output_asm_insn (\"sub\\t%1, %2, #1\", operands);
output_asm_insn (\"mov\\t%0, %1\", operands);
}
else
{
/* Similarly, but the target is memory. */
output_asm_insn (\"sub\\t%1, %2, #1\", operands);
output_asm_insn (\"str\\t%1, %0\", operands);
}
switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
{
case 4:
output_asm_insn (\"b%d0\\t%l1\", &cond);
return \"\";
case 6:
output_asm_insn (\"b%D0\\t.LCB%=\", &cond);
return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
default:
output_asm_insn (\"b%D0\\t.LCB%=\", &cond);
return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
}
}
"
[(set (attr "far_jump")
(if_then_else
(ior (and (eq (symbol_ref ("which_alternative"))
(const_int 0))
(eq_attr "length" "8"))
(eq_attr "length" "10"))
(const_string "yes")
(const_string "no")))
(set_attr_alternative "length"
[
;; Alternative 0
(if_then_else
(and (ge (minus (match_dup 4) (pc)) (const_int -250))
(le (minus (match_dup 4) (pc)) (const_int 256)))
(const_int 4)
(if_then_else
(and (ge (minus (match_dup 4) (pc)) (const_int -2040))
(le (minus (match_dup 4) (pc)) (const_int 2048)))
(const_int 6)
(const_int 8)))
;; Alternative 1
(if_then_else
(and (ge (minus (match_dup 4) (pc)) (const_int -248))
(le (minus (match_dup 4) (pc)) (const_int 256)))
(const_int 6)
(if_then_else
(and (ge (minus (match_dup 4) (pc)) (const_int -2038))
(le (minus (match_dup 4) (pc)) (const_int 2048)))
(const_int 8)
(const_int 10)))
;; Alternative 2
(if_then_else
(and (ge (minus (match_dup 4) (pc)) (const_int -248))
(le (minus (match_dup 4) (pc)) (const_int 256)))
(const_int 6)
(if_then_else
(and (ge (minus (match_dup 4) (pc)) (const_int -2038))
(le (minus (match_dup 4) (pc)) (const_int 2048)))
(const_int 8)
(const_int 10)))
;; Alternative 3
(if_then_else
(and (ge (minus (match_dup 4) (pc)) (const_int -248))
(le (minus (match_dup 4) (pc)) (const_int 256)))
(const_int 6)
(if_then_else
(and (ge (minus (match_dup 4) (pc)) (const_int -2038))
(le (minus (match_dup 4) (pc)) (const_int 2048)))
(const_int 8)
(const_int 10)))])]
)
;; Comparison and test insns