summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorrearnsha <rearnsha@138bc75d-0d04-0410-961f-82ee72b054a4>2003-10-07 08:49:36 +0000
committerrearnsha <rearnsha@138bc75d-0d04-0410-961f-82ee72b054a4>2003-10-07 08:49:36 +0000
commit203c488f0c263a82d6361c6327a5abf27b9253f7 (patch)
tree94033a97e8335ca491ff5dd3f927129749d163e9 /gcc
parent095421966c9288b044416b914fe115fb9f23fefd (diff)
downloadgcc-203c488f0c263a82d6361c6327a5abf27b9253f7.tar.gz
* 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@72188 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/config/arm/arm-protos.h1
-rw-r--r--gcc/config/arm/arm.c9
-rw-r--r--gcc/config/arm/arm.h1
-rw-r--r--gcc/config/arm/arm.md156
5 files changed, 176 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 3298828987b..f8e3e054510 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
index fe424d7c22e..c16deb63a24 100644
--- a/gcc/config/arm/arm-protos.h
+++ b/gcc/config/arm/arm-protos.h
@@ -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);
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index a810791291e..f2441a0ee22 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -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)
{
diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index dc21b534e2e..77debec618d 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -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}}, \
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 4a72c69ef3c..177d54b89aa 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -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