From patchwork Wed Jul 20 12:59:45 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Georg-Johann Lay X-Patchwork-Id: 650657 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]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3rvcTJ6nbkz9t14 for ; Wed, 20 Jul 2016 23:00:20 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=cu2RoGlq; dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:to:cc :from:subject:message-id:date:mime-version:content-type; q=dns; s=default; b=kJiI1U0BYvf19Utm2R07uVnUeXU4BP81Id4Ksy/k12/ENDbm3w vAGef4XtGuNlav9En/QXyX3yXL3LHLWsLQloUR+/mHe2du5qqEvsqIbwL1Ra0B+T /c1IO7REFYIvtkaD0nwygE9Fzq4a195YMaBHhmULmynDTmea1GCW/+E3E= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:to:cc :from:subject:message-id:date:mime-version:content-type; s= default; bh=odzO/xUtrlaLXS4ajdG75jWQm84=; b=cu2RoGlqlcoR45SK2HbW zcZFR2mjat02pSnHatdCuJ9bc3mkLQwexnQx7h1oH0xYX1Xk1nv2cVUsxN1S0mhG PkbWBT64LQVEAlnN9ThQAd/cbZRaCm0YDeEJ3gevO6NrHSdLRTV3aozDwpxPIyPe 7Y6IwBiJ3KQR5UQDV2X8bCA= Received: (qmail 49951 invoked by alias); 20 Jul 2016 13:00:04 -0000 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 Received: (qmail 49733 invoked by uid 89); 20 Jul 2016 13:00:03 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.3 required=5.0 tests=AWL, BAYES_00, KAM_ASCII_DIVIDERS, RCVD_IN_DNSWL_LOW autolearn=no version=3.3.2 spammy=composed, UD:avr.c, avr.c, avrc X-HELO: mo4-p00-ob.smtp.rzone.de Received: from mo4-p00-ob.smtp.rzone.de (HELO mo4-p00-ob.smtp.rzone.de) (81.169.146.161) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Wed, 20 Jul 2016 12:59:51 +0000 X-RZG-AUTH: :LXoWVUeid/7A29J/hMvvT3ol15ykJcYwR/bcHRirORRW3yMcVao= X-RZG-CLASS-ID: mo00 Received: from [192.168.0.123] (mail.hightec-rt.com [213.135.1.215]) by smtp.strato.de (RZmta 38.13 DYNA|AUTH) with ESMTPSA id q04ba9s6KCxkqf8 (using TLSv1.2 with cipher ECDHE-RSA-AES256-SHA (curve secp521r1 with 521 ECDH bits, eq. 15360 bits RSA)) (Client did not present a certificate); Wed, 20 Jul 2016 14:59:46 +0200 (CEST) To: gcc-patches@gcc.gnu.org Cc: Senthil Kumar Selvaraj , Denis Chertykov From: Georg-Johann Lay Subject: [patch,avr] More insns to handle (inverted) bit-bit moves Message-ID: Date: Wed, 20 Jul 2016 14:59:45 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.2.0 MIME-Version: 1.0 X-IsSubscribed: yes This adds some insns that set a destination bit expressed as zero_extract to a source bit expressed as extract, right shift, and simple combinations thereof. Purpose is smaller code and to avoid costly extracts or shifts. This applies mostly to bitfields; for open-coded bit insertions the patterns that I'm seeing are sometimes too complicated, i.e. IOR of AND and SHIFTRT and XOR and SUBREGs and all sorts of arithmetic that are not canonicalized in any way by the middle end (insn combiner, if conversion, ...) Ok for trunk? Johann * config/avr/avr.md (any_extract, any_shiftrt): New code iterators. (*insv.extract, *insv.shiftrt, *insv.not-bit.0, *insv.not-bit.7) (*insv.xor-extract, *insv.xor1-bit.0): New insns. (adjust_len) [insv_notbit, insv_notbit_0, insv_notbit_7]: New values for insn attribute. * config/avr/avr.c (avr_out_insert_notbit): New function. (avr_adjust_insn_length): Handle ADJUST_LEN_INSV_NOTBIT, ADJUST_LEN_INSV_NOTBIT_0/_7. * config/avr/avr-protos.h (avr_out_insert_notbit): New proto. Index: config/avr/avr-protos.h =================================================================== --- config/avr/avr-protos.h (revision 238425) +++ config/avr/avr-protos.h (working copy) @@ -57,6 +57,7 @@ extern const char *avr_out_compare64 (rt extern const char *ret_cond_branch (rtx x, int len, int reverse); extern const char *avr_out_movpsi (rtx_insn *, rtx*, int*); extern const char *avr_out_sign_extend (rtx_insn *, rtx*, int*); +extern const char *avr_out_insert_notbit (rtx_insn *, rtx*, rtx, int*); extern const char *ashlqi3_out (rtx_insn *insn, rtx operands[], int *len); extern const char *ashlhi3_out (rtx_insn *insn, rtx operands[], int *len); Index: config/avr/avr.c =================================================================== --- config/avr/avr.c (revision 238425) +++ config/avr/avr.c (working copy) @@ -7928,6 +7928,76 @@ avr_out_addto_sp (rtx *op, int *plen) } +/* Output instructions to insert an inverted bit into OPERANDS[0]: + $0.$1 = ~$2.$3 if XBITNO = NULL + $0.$1 = ~$2.XBITNO if XBITNO != NULL. + If PLEN = NULL then output the respective instruction sequence which + is a combination of BST / BLD and some instruction(s) to invert the bit. + If PLEN != NULL then store the length of the sequence (in words) in *PLEN. + Return "". */ + +const char* +avr_out_insert_notbit (rtx_insn *insn, rtx operands[], rtx xbitno, int *plen) +{ + rtx op[4] = { operands[0], operands[1], operands[2], + xbitno == NULL_RTX ? operands [3] : xbitno }; + + if (INTVAL (op[1]) == 7 + && test_hard_reg_class (LD_REGS, op[0])) + { + /* If the inserted bit number is 7 and we have a d-reg, then invert + the bit after the insertion by means of SUBI *,0x80. */ + + if (INTVAL (op[3]) == 7 + && REGNO (op[0]) == REGNO (op[2])) + { + avr_asm_len ("subi %0,0x80", op, plen, -1); + } + else + { + avr_asm_len ("bst %2,%3" CR_TAB + "bld %0,%1" CR_TAB + "subi %0,0x80", op, plen, -3); + } + } + else if (test_hard_reg_class (LD_REGS, op[0]) + && (INTVAL (op[1]) != INTVAL (op[3]) + || !reg_overlap_mentioned_p (op[0], op[2]))) + { + /* If the destination bit is in a d-reg we can jump depending + on the source bit and use ANDI / ORI. This just applies if we + have not an early-clobber situation with the bit. */ + + avr_asm_len ("andi %0,~(1<<%1)" CR_TAB + "sbrs %2,%3" CR_TAB + "ori %0,1<<%1", op, plen, -3); + } + else + { + /* Otherwise, invert the bit by means of COM before we store it with + BST and then undo the COM if needed. */ + + avr_asm_len ("com %2" CR_TAB + "bst %2,%3", op, plen, -2); + + if (!reg_unused_after (insn, op[2]) + // A simple 'reg_unused_after' is not enough because that function + // assumes that the destination register is overwritten completely + // and hence is in order for our purpose. This is not the case + // with BLD which just changes one bit of the destination. + || reg_overlap_mentioned_p (op[0], op[2])) + { + /* Undo the COM from above. */ + avr_asm_len ("com %2", op, plen, 1); + } + + avr_asm_len ("bld %0,%1", op, plen, 1); + } + + return ""; +} + + /* Outputs instructions needed for fixed point type conversion. This includes converting between any fixed point type, as well as converting to any integer type. Conversion between integer @@ -8765,6 +8835,16 @@ avr_adjust_insn_length (rtx_insn *insn, case ADJUST_LEN_INSERT_BITS: avr_out_insert_bits (op, &len); break; + case ADJUST_LEN_INSV_NOTBIT: + avr_out_insert_notbit (insn, op, NULL_RTX, &len); + break; + case ADJUST_LEN_INSV_NOTBIT_0: + avr_out_insert_notbit (insn, op, const0_rtx, &len); + break; + case ADJUST_LEN_INSV_NOTBIT_7: + avr_out_insert_notbit (insn, op, GEN_INT (7), &len); + break; + default: gcc_unreachable(); } Index: config/avr/avr.md =================================================================== --- config/avr/avr.md (revision 238425) +++ config/avr/avr.md (working copy) @@ -156,7 +156,7 @@ (define_attr "adjust_len" ashlhi, ashrhi, lshrhi, ashlsi, ashrsi, lshrsi, ashlpsi, ashrpsi, lshrpsi, - insert_bits, + insert_bits, insv_notbit, insv_notbit_0, insv_notbit_7, no" (const_string "no")) @@ -264,6 +264,8 @@ (define_mode_iterator ORDERED234 [HI SI ;; Define two incarnations so that we can build the cross product. (define_code_iterator any_extend [sign_extend zero_extend]) (define_code_iterator any_extend2 [sign_extend zero_extend]) +(define_code_iterator any_extract [sign_extract zero_extract]) +(define_code_iterator any_shiftrt [lshiftrt ashiftrt]) (define_code_iterator xior [xor ior]) (define_code_iterator eqne [eq ne]) @@ -6485,6 +6487,11 @@ (define_expand "insv" (match_operand:QI 3 "nonmemory_operand" ""))] "optimize") +;; Some more patterns to support moving around one bit which can be accomplished +;; by BST + BLD in most situations. Unfortunately, there is no canonical +;; representation, and we just implement some more cases that are not too +;; complicated. + ;; Insert bit $2.0 into $0.$1 (define_insn "*insv.reg" [(set (zero_extract:QI (match_operand:QI 0 "register_operand" "+r,d,d,l,l") @@ -6501,6 +6508,103 @@ (define_insn "*insv.reg" [(set_attr "length" "2,1,1,2,2") (set_attr "cc" "none,set_zn,set_zn,none,none")]) +;; Insert bit $2.$3 into $0.$1 +(define_insn "*insv.extract" + [(set (zero_extract:QI (match_operand:QI 0 "register_operand" "+r") + (const_int 1) + (match_operand:QI 1 "const_0_to_7_operand" "n")) + (any_extract:QI (match_operand:QI 2 "register_operand" "r") + (const_int 1) + (match_operand:QI 3 "const_0_to_7_operand" "n")))] + "" + "bst %2,%3\;bld %0,%1" + [(set_attr "length" "2") + (set_attr "cc" "none")]) + +;; Insert bit $2.$3 into $0.$1 +(define_insn "*insv.shiftrt" + [(set (zero_extract:QI (match_operand:QI 0 "register_operand" "+r") + (const_int 1) + (match_operand:QI 1 "const_0_to_7_operand" "n")) + (any_shiftrt:QI (match_operand:QI 2 "register_operand" "r") + (match_operand:QI 3 "const_0_to_7_operand" "n")))] + "" + "bst %2,%3\;bld %0,%1" + [(set_attr "length" "2") + (set_attr "cc" "none")]) + +;; Same, but with a NOT inverting the source bit. +;; Insert bit ~$2.$3 into $0.$1 +(define_insn "*insv.not-shiftrt" + [(set (zero_extract:QI (match_operand:QI 0 "register_operand" "+r") + (const_int 1) + (match_operand:QI 1 "const_0_to_7_operand" "n")) + (not:QI (any_shiftrt:QI (match_operand:QI 2 "register_operand" "r") + (match_operand:QI 3 "const_0_to_7_operand" "n"))))] + "" + { + return avr_out_insert_notbit (insn, operands, NULL_RTX, NULL); + } + [(set_attr "adjust_len" "insv_notbit") + (set_attr "cc" "clobber")]) + +;; Insert bit ~$2.0 into $0.$1 +(define_insn "*insv.xor1-bit.0" + [(set (zero_extract:QI (match_operand:QI 0 "register_operand" "+r") + (const_int 1) + (match_operand:QI 1 "const_0_to_7_operand" "n")) + (xor:QI (match_operand:QI 2 "register_operand" "r") + (const_int 1)))] + "" + { + return avr_out_insert_notbit (insn, operands, const0_rtx, NULL); + } + [(set_attr "adjust_len" "insv_notbit_0") + (set_attr "cc" "clobber")]) + +;; Insert bit ~$2.0 into $0.$1 +(define_insn "*insv.not-bit.0" + [(set (zero_extract:QI (match_operand:QI 0 "register_operand" "+r") + (const_int 1) + (match_operand:QI 1 "const_0_to_7_operand" "n")) + (not:QI (match_operand:QI 2 "register_operand" "r")))] + "" + { + return avr_out_insert_notbit (insn, operands, const0_rtx, NULL); + } + [(set_attr "adjust_len" "insv_notbit_0") + (set_attr "cc" "clobber")]) + +;; Insert bit ~$2.7 into $0.$1 +(define_insn "*insv.not-bit.7" + [(set (zero_extract:QI (match_operand:QI 0 "register_operand" "+r") + (const_int 1) + (match_operand:QI 1 "const_0_to_7_operand" "n")) + (ge:QI (match_operand:QI 2 "register_operand" "r") + (const_int 0)))] + "" + { + return avr_out_insert_notbit (insn, operands, GEN_INT (7), NULL); + } + [(set_attr "adjust_len" "insv_notbit_7") + (set_attr "cc" "clobber")]) + +;; Insert bit ~$2.$3 into $0.$1 +(define_insn "*insv.xor-extract" + [(set (zero_extract:QI (match_operand:QI 0 "register_operand" "+r") + (const_int 1) + (match_operand:QI 1 "const_0_to_7_operand" "n")) + (any_extract:QI (xor:QI (match_operand:QI 2 "register_operand" "r") + (match_operand:QI 4 "const_int_operand" "n")) + (const_int 1) + (match_operand:QI 3 "const_0_to_7_operand" "n")))] + "INTVAL (operands[4]) & (1 << INTVAL (operands[3]))" + { + return avr_out_insert_notbit (insn, operands, NULL_RTX, NULL); + } + [(set_attr "adjust_len" "insv_notbit") + (set_attr "cc" "clobber")]) + ;; Some combine patterns that try to fix bad code when a value is composed ;; from byte parts like in PR27663.