From patchwork Thu Jul 15 15:15:23 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bernd Schmidt X-Patchwork-Id: 58988 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 27A20B6F15 for ; Fri, 16 Jul 2010 01:16:01 +1000 (EST) Received: (qmail 17927 invoked by alias); 15 Jul 2010 15:15:56 -0000 Received: (qmail 17834 invoked by uid 22791); 15 Jul 2010 15:15:54 -0000 X-SWARE-Spam-Status: No, hits=-1.8 required=5.0 tests=AWL, BAYES_00, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mail.codesourcery.com (HELO mail.codesourcery.com) (38.113.113.100) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Thu, 15 Jul 2010 15:15:48 +0000 Received: (qmail 5059 invoked from network); 15 Jul 2010 15:15:45 -0000 Received: from unknown (HELO ?84.152.221.24?) (bernds@127.0.0.2) by mail.codesourcery.com with ESMTPA; 15 Jul 2010 15:15:45 -0000 Message-ID: <4C3F260B.7060309@codesourcery.com> Date: Thu, 15 Jul 2010 17:15:23 +0200 From: Bernd Schmidt User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.10) Gecko/20100625 Thunderbird/3.0.5 MIME-Version: 1.0 To: Richard Earnshaw CC: GCC Patches Subject: Re: ARM patch: New cbranchqi, cbranchhi patterns for Thumb-1 References: <4C3F0C1F.6020901@codesourcery.com> <1279205019.20995.164.camel@e102346-lin.cambridge.arm.com> In-Reply-To: <1279205019.20995.164.camel@e102346-lin.cambridge.arm.com> Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org 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, cbranch4_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. (cbranch4_insn): New pattern. * config/arm/predicates.md (noov_comparison_operator): New predicate. 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 "cbranch4_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, #", 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)")))