From patchwork Fri Jan 14 16:08:26 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 78944 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 2E57BB7088 for ; Sat, 15 Jan 2011 03:11:50 +1100 (EST) Received: (qmail 27070 invoked by alias); 14 Jan 2011 16:09:55 -0000 Received: (qmail 26772 invoked by uid 22791); 14 Jan 2011 16:09:47 -0000 X-SWARE-Spam-Status: No, hits=-1.8 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_NONE X-Spam-Check-By: sourceware.org Received: from b.mail.sonic.net (HELO b.mail.sonic.net) (64.142.19.5) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 14 Jan 2011 16:09:40 +0000 Received: from are.twiddle.net (are.twiddle.net [75.101.38.216]) by b.mail.sonic.net (8.13.8.Beta0-Sonic/8.13.7) with ESMTP id p0EG9cDv028906 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Fri, 14 Jan 2011 08:09:38 -0800 Received: from anchor.twiddle.home (anchor.twiddle.home [172.31.0.4]) by are.twiddle.net (8.14.4/8.14.4) with ESMTP id p0EG9cSR002092; Fri, 14 Jan 2011 08:09:38 -0800 Received: from anchor.twiddle.home (localhost.localdomain [127.0.0.1]) by anchor.twiddle.home (8.14.4/8.14.4) with ESMTP id p0EG9VAU028713; Fri, 14 Jan 2011 08:09:33 -0800 Received: (from rth@localhost) by anchor.twiddle.home (8.14.4/8.14.4/Submit) id p0EG9Tlu028712; Fri, 14 Jan 2011 08:09:29 -0800 From: rth@redhat.com To: gcc-patches@gcc.gnu.org Cc: nickc@redhat.com, Richard Henderson Subject: [PATCH 11/14] rx: Rewrite the bit manipulation patterns. Date: Fri, 14 Jan 2011 08:08:26 -0800 Message-Id: <1295021309-28608-12-git-send-email-rth@redhat.com> In-Reply-To: <1295021309-28608-1-git-send-email-rth@redhat.com> References: <1295021309-28608-1-git-send-email-rth@redhat.com> X-IsSubscribed: yes 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 From: Richard Henderson The patterns represented with ashift 1 canonically need to have the ashift as the first operand of the logical operation. Leave insv represented as a zero_extract store. Implement a variable store to a 1 bit field as tst+bmne. Implement a variable store of a condition into a 1 bit field with bmcc. --- gcc/config/rx/predicates.md | 4 + gcc/config/rx/rx-protos.h | 1 - gcc/config/rx/rx.c | 42 --------- gcc/config/rx/rx.md | 207 +++++++++++++++++++++++++++++++++--------- 4 files changed, 166 insertions(+), 88 deletions(-) diff --git a/gcc/config/rx/predicates.md b/gcc/config/rx/predicates.md index 0ab4df3..5ae5d22 100644 --- a/gcc/config/rx/predicates.md +++ b/gcc/config/rx/predicates.md @@ -310,3 +310,7 @@ (define_predicate "rx_fp_comparison_operator" (match_code "eq,ne,lt,ge,ordered,unordered,uneq,unlt,unge,ltgt") ) + +(define_predicate "rshift_operator" + (match_code "ashiftrt,lshiftrt") +) diff --git a/gcc/config/rx/rx-protos.h b/gcc/config/rx/rx-protos.h index 9bb76b2..3c3f2d4 100644 --- a/gcc/config/rx/rx-protos.h +++ b/gcc/config/rx/rx-protos.h @@ -33,7 +33,6 @@ extern int rx_initial_elimination_offset (int, int); extern void rx_emit_stack_popm (rtx *, bool); extern void rx_emit_stack_pushm (rtx *); extern void rx_expand_epilogue (bool); -extern bool rx_expand_insv (rtx *); extern char * rx_gen_move_template (rtx *, bool); extern bool rx_is_legitimate_constant (rtx); extern bool rx_is_mode_dependent_addr (rtx); diff --git a/gcc/config/rx/rx.c b/gcc/config/rx/rx.c index 16646ae..8cc46e7 100644 --- a/gcc/config/rx/rx.c +++ b/gcc/config/rx/rx.c @@ -2339,48 +2339,6 @@ rx_is_ms_bitfield_layout (const_tree record_type ATTRIBUTE_UNUSED) /* The packed attribute overrides the MS behaviour. */ return ! TYPE_PACKED (record_type); } - -/* Try to generate code for the "isnv" pattern which inserts bits - into a word. - operands[0] => Location to be altered. - operands[1] => Number of bits to change. - operands[2] => Starting bit. - operands[3] => Value to insert. - Returns TRUE if successful, FALSE otherwise. */ - -bool -rx_expand_insv (rtx * operands) -{ - if (INTVAL (operands[1]) != 1 - || ! CONST_INT_P (operands[3])) - return false; - - if (MEM_P (operands[0]) - && INTVAL (operands[2]) > 7) - return false; - - switch (INTVAL (operands[3])) - { - case 0: - if (MEM_P (operands[0])) - emit_insn (gen_bitclr_in_memory (operands[0], operands[0], - operands[2])); - else - emit_insn (gen_bitclr (operands[0], operands[0], operands[2])); - break; - case 1: - case -1: - if (MEM_P (operands[0])) - emit_insn (gen_bitset_in_memory (operands[0], operands[0], - operands[2])); - else - emit_insn (gen_bitset (operands[0], operands[0], operands[2])); - break; - default: - return false; - } - return true; -} /* Returns true if X a legitimate constant for an immediate operand on the RX. X is already known to satisfy CONSTANT_P. */ diff --git a/gcc/config/rx/rx.md b/gcc/config/rx/rx.md index 864b4a5..7fa8668 100644 --- a/gcc/config/rx/rx.md +++ b/gcc/config/rx/rx.md @@ -1518,91 +1518,208 @@ ) ;; Bit manipulation instructions. -;; Note - there are two versions of each pattern because the memory -;; accessing versions use QImode whilst the register accessing -;; versions use SImode. -;; The peephole are here because the combiner only looks at a maximum -;; of three instructions at a time. -(define_insn "bitset" +;; ??? The *_in_memory patterns will not be matched without further help. +;; At one time we had the insv expander generate them, but I suspect that +;; in general we get better performance by exposing the register load to +;; the optimizers. +;; +;; An alternate solution would be to re-organize these patterns such +;; that allow both register and memory operands. This would allow the +;; register allocator to spill and not load the register operand. This +;; would be possible only for operations for which we have a constant +;; bit offset, so that we can adjust the address by ofs/8 and replace +;; the offset in the insn by ofs%8. + +(define_insn "*bitset" [(set (match_operand:SI 0 "register_operand" "=r") - (ior:SI (match_operand:SI 1 "register_operand" "0") - (ashift:SI (const_int 1) - (match_operand:SI 2 "nonmemory_operand" "ri"))))] + (ior:SI (ashift:SI (const_int 1) + (match_operand:SI 1 "rx_shift_operand" "ri")) + (match_operand:SI 2 "register_operand" "0")))] "" - "bset\t%2, %0" + "bset\t%1, %0" [(set_attr "length" "3")] ) -(define_insn "bitset_in_memory" - [(set (match_operand:QI 0 "memory_operand" "=m") - (ior:QI (match_operand:QI 1 "memory_operand" "0") - (ashift:QI (const_int 1) - (match_operand:QI 2 "nonmemory_operand" "ri"))))] +(define_insn "*bitset_in_memory" + [(set (match_operand:QI 0 "memory_operand" "+Q") + (ior:QI (ashift:QI (const_int 1) + (match_operand:QI 1 "nonmemory_operand" "ri")) + (match_dup 0)))] "" - "bset\t%2, %0.B" + "bset\t%1, %0.B" [(set_attr "length" "3") (set_attr "timings" "34")] ) (define_insn "*bitinvert" [(set (match_operand:SI 0 "register_operand" "=r") - (xor:SI (match_operand:SI 1 "register_operand" "0") - (ashift:SI (const_int 1) - (match_operand:SI 2 "nonmemory_operand" "ri"))))] + (xor:SI (ashift:SI (const_int 1) + (match_operand:SI 1 "rx_shift_operand" "ri")) + (match_operand:SI 2 "register_operand" "0")))] "" - "bnot\t%2, %0" + "bnot\t%1, %0" [(set_attr "length" "3")] ) -(define_insn "bitinvert_in_memory" - [(set (match_operand:QI 0 "memory_operand" "+m") - (xor:QI (match_operand:QI 1 "register_operand" "0") - (ashift:QI (const_int 1) - (match_operand:QI 2 "nonmemory_operand" "ri"))))] +(define_insn "*bitinvert_in_memory" + [(set (match_operand:QI 0 "memory_operand" "+Q") + (xor:QI (ashift:QI (const_int 1) + (match_operand:QI 1 "nonmemory_operand" "ri")) + (match_dup 0)))] "" - "bnot\t%2, %0.B" + "bnot\t%1, %0.B" [(set_attr "length" "5") (set_attr "timings" "33")] ) -(define_insn "bitclr" +(define_insn "*bitclr" [(set (match_operand:SI 0 "register_operand" "=r") - (and:SI (match_operand:SI 1 "register_operand" "0") - (not:SI + (and:SI (not:SI (ashift:SI (const_int 1) - (match_operand:SI 2 "nonmemory_operand" "ri")))))] + (match_operand:SI 1 "rx_shift_operand" "ri"))) + (match_operand:SI 2 "register_operand" "0")))] "" - "bclr\t%2, %0" + "bclr\t%1, %0" [(set_attr "length" "3")] ) -(define_insn "bitclr_in_memory" - [(set (match_operand:QI 0 "memory_operand" "=m") - (and:QI (match_operand:QI 1 "memory_operand" "0") - (not:QI +(define_insn "*bitclr_in_memory" + [(set (match_operand:QI 0 "memory_operand" "+Q") + (and:QI (not:QI (ashift:QI (const_int 1) - (match_operand:QI 2 "nonmemory_operand" "ri")))))] + (match_operand:QI 1 "nonmemory_operand" "ri"))) + (match_dup 0)))] "" - "bclr\t%2, %0.B" + "bclr\t%1, %0.B" [(set_attr "length" "3") (set_attr "timings" "34")] ) +(define_insn "*insv_imm" + [(set (zero_extract:SI + (match_operand:SI 0 "register_operand" "+r") + (const_int 1) + (match_operand:SI 1 "rx_shift_operand" "ri")) + (match_operand:SI 2 "const_int_operand" ""))] + "" +{ + if (INTVAL (operands[2]) & 1) + return "bset\t%1, %0"; + else + return "bclr\t%1, %0"; +} + [(set_attr "length" "3")] +) + +(define_insn_and_split "rx_insv_reg" + [(set (zero_extract:SI + (match_operand:SI 0 "register_operand" "+r") + (const_int 1) + (match_operand:SI 1 "const_int_operand" "")) + (match_operand:SI 2 "register_operand" "r")) + (clobber (reg:CC CC_REG))] + "" + "#" + "reload_completed" + [(set (zero_extract:SI (match_dup 0) (const_int 1) (match_dup 1)) + (match_dup 3))] +{ + rtx flags, x; + + /* Emit tst #1, op2. */ + flags = gen_rtx_REG (CC_ZSmode, CC_REG); + x = gen_rtx_AND (SImode, operands[2], const1_rtx); + x = gen_rtx_COMPARE (CC_ZSmode, x, const0_rtx); + x = gen_rtx_SET (VOIDmode, flags, x); + emit_insn (x); + + /* Emit bmne. */ + operands[3] = gen_rtx_NE (SImode, flags, const0_rtx); +}) + +(define_insn_and_split "*insv_cond" + [(set (zero_extract:SI + (match_operand:SI 0 "register_operand" "+r") + (const_int 1) + (match_operand:SI 1 "const_int_operand" "")) + (match_operator:SI 4 "comparison_operator" + [(match_operand:SI 2 "register_operand" "r") + (match_operand:SI 3 "rx_source_operand" "riQ")])) + (clobber (reg:CC CC_REG))] + "" + "#" + "reload_completed" + [(set (zero_extract:SI (match_dup 0) (const_int 1) (match_dup 1)) + (match_dup 4))] +{ + rtx flags, x; + + flags = gen_rtx_REG (CCmode, CC_REG); + x = gen_rtx_COMPARE (CCmode, operands[2], operands[3]); + x = gen_rtx_SET (VOIDmode, flags, x); + emit_insn (x); + + operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[4]), SImode, + flags, const0_rtx); +}) + +(define_insn "*bmcc" + [(set (zero_extract:SI + (match_operand:SI 0 "register_operand" "+r") + (const_int 1) + (match_operand:SI 1 "const_int_operand" "")) + (match_operator:SI 2 "comparison_operator" + [(reg CC_REG) (const_int 0)]))] + "reload_completed" + "bm%B2\t%1, %0" + [(set_attr "length" "3")] +) + +;; Work around the fact that X=Y<0 is preferentially expanded as a shift. +(define_insn_and_split "*insv_cond_lt" + [(set (zero_extract:SI + (match_operand:SI 0 "register_operand" "+r") + (const_int 1) + (match_operand:SI 1 "const_int_operand" "")) + (match_operator:SI 3 "rshift_operator" + [(match_operand:SI 2 "register_operand" "r") + (const_int 31)])) + (clobber (reg:CC CC_REG))] + "" + "#" + "" + [(parallel [(set (zero_extract:SI (match_dup 0) (const_int 1) (match_dup 1)) + (lt:SI (match_dup 2) (const_int 0))) + (clobber (reg:CC CC_REG))])] + "" +) + (define_expand "insv" - [(set (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand") ;; Destination - (match_operand 1 "immediate_operand") ;; # of bits to set - (match_operand 2 "immediate_operand")) ;; Starting bit - (match_operand 3 "immediate_operand"))] ;; Bits to insert + [(set (zero_extract:SI + (match_operand:SI 0 "register_operand") ;; Destination + (match_operand:SI 1 "const_int_operand") ;; # of bits to set + (match_operand:SI 2 "nonmemory_operand")) ;; Starting bit + (match_operand:SI 3 "nonmemory_operand"))] ;; Bits to insert "" - { - if (rx_expand_insv (operands)) +{ + /* We only handle single-bit inserts. */ + if (!CONST_INT_P (operands[1]) || INTVAL (operands[1]) != 1) + FAIL; + + /* Either the bit to insert or the position must be constant. */ + if (CONST_INT_P (operands[3])) + operands[3] = GEN_INT (INTVAL (operands[3]) & 1); + else if (CONST_INT_P (operands[2])) + { + emit_insn (gen_rx_insv_reg (operands[0], operands[2], operands[3])); DONE; + } + else FAIL; - } -) +}) ;; Atomic exchange operation.