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

[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

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