This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH, ARM] Improve testing low bits of register on Thumb
- From: Richard Earnshaw <rearnsha at arm dot com>
- To: gcc patches <gcc-patches at gcc dot gnu dot org>
- Date: Thu, 09 Feb 2006 15:26:02 +0000
- Subject: [PATCH, ARM] Improve testing low bits of register on Thumb
On thumb we can test an arbitrary number of low bits in a register by
shifting the value up and then branching on equality. This is much more
efficient than trying to generate a mask value in a register (which can
take several instructions).
So, for example
if (a & 7)
xxx
can be implemented as
lsls scratch, a, #29
beq yyy
xxx
Tested on an arm-elf cross and installed on the trunk.
R.
2006-02-09 Richard Earnshaw <richard.earnshaw@arm.com>
* arm.md (tlobits_cbranch): New pattern.
* arm.h (arm_select_cc_mode): For thumb, only return CC_Nmode if
testing a single bit.
*** arm.c (revision 110810)
--- arm.c (local)
*************** arm_select_cc_mode (enum rtx_code op, rt
*** 6748,6754 ****
if (TARGET_THUMB
&& GET_MODE (x) == SImode
&& (op == EQ || op == NE)
! && (GET_CODE (x) == ZERO_EXTRACT))
return CC_Nmode;
/* An operation that sets the condition codes as a side-effect, the
--- 6748,6755 ----
if (TARGET_THUMB
&& GET_MODE (x) == SImode
&& (op == EQ || op == NE)
! && GET_CODE (x) == ZERO_EXTRACT
! && XEXP (x, 1) == const1_rtx)
return CC_Nmode;
/* An operation that sets the condition codes as a side-effect, the
*** arm.md (revision 110810)
--- arm.md (local)
*************** (define_insn "*tbit_cbranch"
*** 6028,6033 ****
--- 6028,6077 ----
(const_int 8))))]
)
+ (define_insn "*tlobits_cbranch"
+ [(set (pc)
+ (if_then_else
+ (match_operator 0 "equality_operator"
+ [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
+ (match_operand:SI 2 "const_int_operand" "i")
+ (const_int 0))
+ (const_int 0)])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))
+ (clobber (match_scratch:SI 4 "=l"))]
+ "TARGET_THUMB"
+ "*
+ {
+ rtx op[3];
+ op[0] = operands[4];
+ op[1] = operands[1];
+ op[2] = GEN_INT (32 - INTVAL (operands[2]));
+
+ output_asm_insn (\"lsl\\t%0, %1, %2\", op);
+ switch (get_attr_length (insn))
+ {
+ case 4: return \"b%d0\\t%l3\";
+ case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
+ default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
+ }
+ }"
+ [(set (attr "far_jump")
+ (if_then_else
+ (eq_attr "length" "8")
+ (const_string "yes")
+ (const_string "no")))
+ (set (attr "length")
+ (if_then_else
+ (and (ge (minus (match_dup 3) (pc)) (const_int -250))
+ (le (minus (match_dup 3) (pc)) (const_int 256)))
+ (const_int 4)
+ (if_then_else
+ (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
+ (le (minus (match_dup 3) (pc)) (const_int 2048)))
+ (const_int 6)
+ (const_int 8))))]
+ )
+
(define_insn "*tstsi3_cbranch"
[(set (pc)
(if_then_else