diff mbox

ARM patch: New cbranchqi, cbranchhi patterns for Thumb-1

Message ID 4C3F260B.7060309@codesourcery.com
State New
Headers show

Commit Message

Bernd Schmidt July 15, 2010, 3:15 p.m. UTC
On 07/15/2010 04:43 PM, Richard Earnshaw wrote:
> 
> On Thu, 2010-07-15 at 15:24 +0200, Bernd Schmidt wrote:
>> On Thumb-1, comparisons of integer values smaller than a word can be
>> done by shifting the value to the left.  This patch adds a new macroized
>> pattern, cbranch<mode>4_insn, which is used for QImode and HImode, and
>> does exactly that.  Effects:
>>
>> -       lsl     r2, r1, #24
>> -       lsr     r2, r2, #24
>> -       cmp     r2, #0
>> +       lsl     r1, #24
>>         bne     .L195

> This is going to only set the N and Z flags correctly.  V and C will
> have different values.

You're right.  A while ago I posted another patch which introduced
noov_comparison_operator; it seems like that could be used here as well.
 We can handle the other cases by inserting an extra compare with zero.
 New patch attached, this also makes use of the fact that constant
shifts are three-operand even on Thumb-1, so we can use any register as
scratch.

> Also note, the same trick should be usable on ARM and Thumb2 if we don't
> do that already.

On the whole my impression is that being able to manipulate comparison
insns directly makes things a lot easier for the compiler in
TARGET_32BIT mode.  I'm not sure we need this trick, I'd expect the
combiner can already do this.


Bernd
* config/arm/arm.md (QHI): New define_mode_iterator.
	(cbranch<mode>4_insn): New pattern.
	* config/arm/predicates.md (noov_comparison_operator): New predicate.

Comments

Bernd Schmidt Aug. 2, 2010, 10:44 a.m. UTC | #1
>>> On Thumb-1, comparisons of integer values smaller than a word can be
>>> done by shifting the value to the left.  This patch adds a new macroized
>>> pattern, cbranch<mode>4_insn, which is used for QImode and HImode, and
>>> does exactly that.  Effects:
>>>
>>> -       lsl     r2, r1, #24
>>> -       lsr     r2, r2, #24
>>> -       cmp     r2, #0
>>> +       lsl     r1, #24
>>>         bne     .L195

http://gcc.gnu.org/ml/gcc-patches/2010-07/msg01255.html


Bernd
Bernd Schmidt Aug. 10, 2010, 6:57 p.m. UTC | #2
On 08/02/2010 12:44 PM, Bernd Schmidt wrote:
>>>> On Thumb-1, comparisons of integer values smaller than a word can be
>>>> done by shifting the value to the left.  This patch adds a new macroized
>>>> pattern, cbranch<mode>4_insn, which is used for QImode and HImode, and
>>>> does exactly that.  Effects:
>>>>
>>>> -       lsl     r2, r1, #24
>>>> -       lsr     r2, r2, #24
>>>> -       cmp     r2, #0
>>>> +       lsl     r1, #24
>>>>         bne     .L195
> 

http://gcc.gnu.org/ml/gcc-patches/2010-07/msg01255.html


Bernd
diff mbox

Patch

Index: config/arm/arm.md
===================================================================
--- config/arm/arm.md.orig
+++ config/arm/arm.md
@@ -393,6 +393,9 @@ 
 ;; The integer modes up to word size
 (define_mode_iterator QHSI [QI HI SI])
 
+;; The integer modes below word size
+(define_mode_iterator QHI [QI HI])
+
 ;;---------------------------------------------------------------------------
 ;; Predicates
 
@@ -6686,6 +6689,63 @@ 
 		(const_int 8))))]
 )
 
+(define_mode_attr mode_lshift [(QI "24") (HI "16")])
+
+(define_insn "cbranch<mode>4_insn"
+  [(set (pc) (if_then_else
+	      (match_operator 0 "arm_comparison_operator"
+	       [(match_operand:QHI 1 "s_register_operand" "l")
+	        (const_int 0)])
+	      (label_ref (match_operand 2 "" ""))
+	      (pc)))
+   (clobber (match_scratch:QHI 3 "=l"))]
+  "TARGET_THUMB1"
+{
+  int len = get_attr_length (insn);
+  output_asm_insn ("lsl\t%3, %1, #<mode_lshift>", operands);
+
+  if (!noov_comparison_operator (operands[0], VOIDmode))
+    {
+      output_asm_insn ("cmp\t%3, #0", operands);
+      len -= 2;
+    }
+
+  switch (len)
+    {
+    case 4:  return "b%d0\t%l2";
+    case 6:  return "b%D0\t.LCB%=\;b\t%l2\t%@long jump\n.LCB%=:";
+    default: return "b%D0\t.LCB%=\;bl\t%l2\t%@far jump\n.LCB%=:";
+    }
+}
+  [(set (attr "far_jump")
+        (if_then_else
+	    (ior (and (match_operand 0 "noov_comparison_operator")
+		      (eq_attr "length" "8"))
+		 (eq_attr "length" "10"))
+	    (const_string "yes")
+            (const_string "no")))
+   (set (attr "length")
+     (if_then_else
+       (match_operand 0 "noov_comparison_operator")
+       (if_then_else
+	 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
+	      (le (minus (match_dup 2) (pc)) (const_int 256)))
+	 (const_int 4)
+	 (if_then_else
+	   (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
+		(le (minus (match_dup 2) (pc)) (const_int 2048)))
+	   (const_int 6)
+	   (const_int 8)))
+       (if_then_else
+	 (and (ge (minus (match_dup 2) (pc)) (const_int -248))
+	      (le (minus (match_dup 2) (pc)) (const_int 256)))
+	 (const_int 6)
+	 (if_then_else
+	   (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
+		(le (minus (match_dup 2) (pc)) (const_int 2048)))
+	   (const_int 8)
+	   (const_int 10)))))])
+
 (define_insn "cbranchsi4_scratch"
   [(set (pc) (if_then_else
 	      (match_operator 4 "arm_comparison_operator"
Index: config/arm/predicates.md
===================================================================
--- config/arm/predicates.md.orig
+++ config/arm/predicates.md
@@ -235,6 +235,9 @@ 
 (define_special_predicate "lt_ge_comparison_operator"
   (match_code "lt,ge"))
 
+(define_special_predicate "noov_comparison_operator"
+  (match_code "lt,ge,eq,ne"))
+
 (define_special_predicate "minmax_operator"
   (and (match_code "smin,smax,umin,umax")
        (match_test "mode == GET_MODE (op)")))