From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 100353 invoked by alias); 19 Jul 2015 13:11:13 -0000 Mailing-List: contact gcc-bugs-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-bugs-owner@gcc.gnu.org Received: (qmail 100310 invoked by uid 48); 19 Jul 2015 13:11:08 -0000 From: "olegendo at gcc dot gnu.org" To: gcc-bugs@gcc.gnu.org Subject: [Bug target/64345] [SH] Improve single bit extraction Date: Sun, 19 Jul 2015 13:11:00 -0000 X-Bugzilla-Reason: CC X-Bugzilla-Type: changed X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: gcc X-Bugzilla-Component: target X-Bugzilla-Version: 5.0 X-Bugzilla-Keywords: X-Bugzilla-Severity: normal X-Bugzilla-Who: olegendo at gcc dot gnu.org X-Bugzilla-Status: UNCONFIRMED X-Bugzilla-Resolution: X-Bugzilla-Priority: P3 X-Bugzilla-Assigned-To: unassigned at gcc dot gnu.org X-Bugzilla-Target-Milestone: --- X-Bugzilla-Flags: X-Bugzilla-Changed-Fields: Message-ID: In-Reply-To: References: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: 7bit X-Bugzilla-URL: http://gcc.gnu.org/bugzilla/ Auto-Submitted: auto-generated MIME-Version: 1.0 X-SW-Source: 2015-07/txt/msg01662.txt.bz2 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64345 --- Comment #3 from Oleg Endo --- (In reply to Oleg Endo from comment #2) The following pattern seems to fix the test case. =================================================================== --- gcc/config/sh/sh.md (revision 225987) +++ gcc/config/sh/sh.md (working copy) @@ -14220,6 +14220,31 @@ [(set (reg:SI T_REG) (zero_extract:SI (match_dup 0) (const_int 1) (match_dup 1)))]) +(define_insn_and_split "*zero_extract_3" + [(set (match_operand:SI 0 "arith_reg_dest") + (and:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand") + (match_operand 2 "const_int_operand")) + (match_operand 3 "const_int_operand"))) + (clobber (reg:SI T_REG))] + "TARGET_SH1 && can_create_pseudo_p () + && exact_log2 (INTVAL (operands[3])) >= 0" + "#" + "&& 1" + [(const_int 0)] +{ + int rshift = INTVAL (operands[2]); + int lshift = exact_log2 (INTVAL (operands[3])); + + rtx tmp = gen_reg_rtx (SImode); + emit_insn (gen_rtx_PARALLEL (VOIDmode, + gen_rtvec (2, + gen_rtx_SET (tmp, + gen_rtx_ZERO_EXTRACT (SImode, operands[1], const1_rtx, + GEN_INT (rshift + lshift))), + gen_rtx_CLOBBER (VOIDmode, get_t_reg_rtx ())))); + emit_insn (gen_ashlsi3 (operands[0], tmp, GEN_INT (lshift))); +}) + ;; ------------------------------------------------------------------------- ;; SH2A instructions for bitwise operations. ;; FIXME: Convert multiple instruction insns to insn_and_split. However, in some cases it might indeed be better to emit a shift-and sequence, especially if the shift value is 1,2,8,16. For instance return (((vi >> 6) & 0x01) << 3); results in mov r4,r0 tst #64,r0 mov #-1,r0 negc r0,r0 shll2 r0 rts add r0,r0 which is better as: mov r4,r0 shll2 r0 shlr r0 rts and #8,r0 Even more so when the bit test constant doesn't fit into 8 bits: return (((vi >> 10) & 0x01) << 1); mov.w .L2,r1 mov #-1,r0 tst r1,r4 negc r0,r0 rts add r0,r0 .align 1 .L2: .short 1024 better: mov r4,r0 shlr8 r0 shlr r0 rts and #2,r0 Generally, it seems better to use an shift-and sequence, unless the tst-negc sequence can simplify the trailing shift for SH variants without dynamic shifts.