From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 5791 invoked by alias); 16 Dec 2013 21:59:38 -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 5759 invoked by uid 48); 16 Dec 2013 21:59:35 -0000 From: "olegendo at gcc dot gnu.org" To: gcc-bugs@gcc.gnu.org Subject: [Bug target/59533] New: [SH] Missed cmp/pz opportunity Date: Mon, 16 Dec 2013 21:59:00 -0000 X-Bugzilla-Reason: CC X-Bugzilla-Type: new X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: gcc X-Bugzilla-Component: target X-Bugzilla-Version: 4.9.0 X-Bugzilla-Keywords: X-Bugzilla-Severity: enhancement X-Bugzilla-Who: olegendo at gcc dot gnu.org X-Bugzilla-Status: UNCONFIRMED 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: bug_id short_desc product version bug_status bug_severity priority component assigned_to reporter cf_gcctarget Message-ID: 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: 2013-12/txt/msg01444.txt.bz2 http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59533 Bug ID: 59533 Summary: [SH] Missed cmp/pz opportunity Product: gcc Version: 4.9.0 Status: UNCONFIRMED Severity: enhancement Priority: P3 Component: target Assignee: unassigned at gcc dot gnu.org Reporter: olegendo at gcc dot gnu.org Target: sh*-*-* In some cases RTL such as (insn 7 6 8 2 (set (reg:SI 169) (not:SI (reg:SI 168))) sh_tmp.cpp:31 -1 (nil)) (insn 8 7 9 2 (parallel [ (set (reg:SI 167 [ D.1462+-3 ]) (lshiftrt:SI (reg:SI 169) (const_int 31 [0x1f]))) (clobber (reg:SI 147 t)) ]) sh_tmp.cpp:31 -1 (nil)) is expanded to refer to the MSB of a word. In most cases combine can catch such a sequence and generate a cmp/pz insn (set (reg:SI T_REG) (ge:SI (...) (const_int 0))). However, in cases where the extracted MSB is not stored in the T bit, it fails to do so. Here are a few test functions, compiled with -O2 -m4: int test0_OK (unsigned char* a) { return a[0] < 128; /* mov.b @r4,r1 cmp/pz r1 rts movt r0 */ } int test1_NG (unsigned char* a, unsigned char* b) { return a[0] + (a[0] < 128); /* mov.b @r4,r1 extu.b r1,r0 exts.b r1,r1 // the redundant sign extension is another issue not r1,r1 shll r1 // could use 'cmp/pz r1' here. mov #0,r1 rts addc r1,r0 */ } int test2_NG (unsigned char* a, unsigned char* b) { return a[0] + ((a[0] & 0x80) == 0); /* mov.b @r4,r1 extu.b r1,r0 exts.b r1,r1 // the redundant sign extension is another issue not r1,r1 shll r1 // could use 'cmp/pz r1' here. mov #0,r1 rts addc r1,r0 */ } int test3_OK (unsigned char* a, unsigned char* b) { return a[0] + (a[0] > 127); /* mov.b @r4,r1 extu.b r1,r0 exts.b r1,r1 shll r1 mov #0,r1 rts addc r1,r0 */ } int test4_OK (unsigned char* a, unsigned char* b) { return a[0] + ((a[0] & 0x80) != 0); /* mov.b @r4,r1 extu.b r1,r0 exts.b r1,r1 shll r1 mov #0,r1 rts addc r1,r0 */ } int test5_OK (unsigned char* a, int b, int c) { if (a[0] < 128) return c; else return b + 50; /* mov.b @r4,r1 cmp/pz r1 bt .L9 mov r5,r6 add #50,r6 .L9: rts mov r6,r0 */ } unsigned int test6_OK (unsigned int a) { return ~a >> 31; /* cmp/pz r4 rts movt r0 */ } The following patch fixes the issue: Index: gcc/config/sh/sh.md =================================================================== --- gcc/config/sh/sh.md (revision 205971) +++ gcc/config/sh/sh.md (working copy) @@ -4707,13 +4707,28 @@ DONE; }) -(define_insn "shll" +(define_insn_and_split "shll" [(set (match_operand:SI 0 "arith_reg_dest" "=r") (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") (const_int 1))) (set (reg:SI T_REG) (lt:SI (match_dup 1) (const_int 0)))] "TARGET_SH1" "shll %0" + "&& can_create_pseudo_p ()" + [(set (reg:SI T_REG) (ge:SI (match_dup 2) (const_int 0))) + (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 1)))] +{ + rtx i = curr_insn; + rtx s = find_last_value (operands[1], &i, curr_insn, true); + + if (s == operands[1] || i == curr_insn) + FAIL; + + if (GET_CODE (s) == NOT && REG_P (XEXP (s, 0))) + operands[2] = XEXP (s, 0); + else + FAIL; +} [(set_attr "type" "arith")]) (define_insn "*ashlsi_c_void"