From patchwork Mon Oct 28 21:27:22 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oleg Endo X-Patchwork-Id: 286642 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 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 44F672C00E3 for ; Tue, 29 Oct 2013 08:27:47 +1100 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:subject:from:to:date:content-type:mime-version; q= dns; s=default; b=oy7YKRHu8rm1ovRyLMpNVgv51w6hGPVcGpdj20QcqaN30W fBF87UucaQ8kYL9jYf63YjsdSov4qIOqnZ56/fr6SeJlvLK8xOrDt6nwAUqYU2oE VFEV9PYs7bdNzGZe71dHscm3u3q8eJecfJOT+3aKT5Rti3n0xsRzgBCf/dJ64= 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 :message-id:subject:from:to:date:content-type:mime-version; s= default; bh=OsB6/HxGAy1gRn/EnVFHQMdgZTQ=; b=Hfkp8uOY56MoSVLHpmE2 EhS07sH2ddq6d0U4hLZlC+deDpVjMe9GKp98pQLdv0iQy4CXezNq0TFAhd6ZL2Wu 1g/VbnU2vggEK0pcuKignoGjzCAhkvOfm5lMU8VlGul0Y2utlOu+dgFZ3s6n87nr +UTIAXme7xqLpLmq56Pbtmc= Received: (qmail 9688 invoked by alias); 28 Oct 2013 21:27:40 -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 9678 invoked by uid 89); 28 Oct 2013 21:27:40 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.6 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_NONE, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 X-HELO: mailout05.t-online.de Received: from mailout05.t-online.de (HELO mailout05.t-online.de) (194.25.134.82) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 28 Oct 2013 21:27:35 +0000 Received: from fwd10.aul.t-online.de (fwd10.aul.t-online.de ) by mailout05.t-online.de with smtp id 1VauLS-0003Fl-D6; Mon, 28 Oct 2013 22:27:30 +0100 Received: from [192.168.0.103] (EXDNbiZrQh4qnVqtEbodZntxcj3ODX0ULO3u0-nl5EzJSGD9OdTvarD8pEpxPv2Qlo@[84.175.207.133]) by fwd10.t-online.de with esmtp id 1VauLR-0VVTRA0; Mon, 28 Oct 2013 22:27:29 +0100 Message-ID: <1382995642.2445.271.camel@yam-132-YW-E178-FTW> Subject: [SH] PR 54236 - add some more addc patterns From: Oleg Endo To: gcc-patches Date: Mon, 28 Oct 2013 22:27:22 +0100 Mime-Version: 1.0 X-IsSubscribed: yes Hello, This adds some more patterns to utilize the SH addc instruction. Tested on rev 204111 with make -k check RUNTESTFLAGS="--target_board=sh-sim \{-m2a/-mb,-m2a-single/-mb,-m4/-ml,-m4-single/-ml,-m4/-mb,-m4-single/-mb}" and no new failures. OK for trunk? Cheers, Oleg gcc/ChangeLog: PR target/54236 * config/sh/sh.md (*addc): Add more addc related insn and splits. * config/sh/sh.c (addsubcosts): Handle some addc special cases. testsuite/ChangeLog: PR target/54236 * gcc.target/sh/pr54236-2: New. * gcc.target/sh/pr54089-6: Add another rotl special case. Index: gcc/config/sh/sh.md =================================================================== --- gcc/config/sh/sh.md (revision 204098) +++ gcc/config/sh/sh.md (working copy) @@ -1910,6 +1910,126 @@ (match_dup 1))) (clobber (reg:SI T_REG))])]) +;; Use shlr-addc to do 'reg + (reg & 1)'. +(define_insn_and_split "*addc" + [(set (match_operand:SI 0 "arith_reg_dest") + (plus:SI (and:SI (match_operand:SI 1 "arith_reg_operand") + (const_int 1)) + (match_operand:SI 2 "arith_reg_operand"))) + (clobber (reg:SI T_REG))] + "TARGET_SH1" + "#" + "&& can_create_pseudo_p ()" + [(parallel [(set (match_dup 0) (plus:SI (reg:SI T_REG) (match_dup 2))) + (clobber (reg:SI T_REG))])] +{ + emit_insn (gen_shlr (gen_reg_rtx (SImode), operands[1])); +}) + +;; Use shlr-addc to do 'reg + reg + (reg & 1)'. +(define_insn_and_split "*addc" + [(set (match_operand:SI 0 "arith_reg_dest") + (plus:SI (plus:SI (and:SI (match_operand:SI 1 "arith_reg_operand") + (const_int 1)) + (match_operand:SI 2 "arith_reg_operand")) + (match_operand:SI 3 "arith_reg_operand"))) + (clobber (reg:SI T_REG))] + "TARGET_SH1" + "#" + "&& can_create_pseudo_p ()" + [(parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 2) (match_dup 3)) + (reg:SI T_REG))) + (clobber (reg:SI T_REG))])] +{ + emit_insn (gen_shlr (gen_reg_rtx (SImode), operands[1])); +}) + +;; Canonicalize 'reg + (reg & 1) + reg' into 'reg + reg + (reg & 1)'. +(define_insn_and_split "*addc" + [(set (match_operand:SI 0 "arith_reg_dest") + (plus:SI (and:SI (match_operand:SI 1 "arith_reg_operand") + (const_int 1)) + (plus:SI (match_operand:SI 2 "arith_reg_operand") + (match_operand:SI 3 "arith_reg_operand")))) + (clobber (reg:SI T_REG))] + "TARGET_SH1" + "#" + "&& can_create_pseudo_p ()" + [(parallel [(set (match_dup 0) + (plus:SI (plus:SI (and:SI (match_dup 1) (const_int 1)) + (match_dup 2)) + (match_dup 3))) + (clobber (reg:SI T_REG))])]) + +;; Canonicalize '2 * reg + (reg & 1)' into 'reg + reg + (reg & 1)'. +(define_insn_and_split "*addc" + [(set (match_operand:SI 0 "arith_reg_dest") + (plus:SI (and:SI (match_operand:SI 1 "arith_reg_operand") + (const_int 1)) + (mult:SI (match_operand:SI 2 "arith_reg_operand") + (const_int 2)))) + (clobber (reg:SI T_REG))] + "TARGET_SH1" + "#" + "&& can_create_pseudo_p ()" + [(parallel [(set (match_dup 0) + (plus:SI (plus:SI (and:SI (match_dup 1) (const_int 1)) + (match_dup 2)) + (match_dup 2))) + (clobber (reg:SI T_REG))])]) + +;; Use shll-addc to do 'reg + ((unsigned int)reg >> 31)'. +(define_insn_and_split "*addc" + [(set (match_operand:SI 0 "arith_reg_dest") + (plus:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand") + (const_int 31)) + (match_operand:SI 2 "arith_reg_operand"))) + (clobber (reg:SI T_REG))] + "TARGET_SH1" + "#" + "&& can_create_pseudo_p ()" + [(parallel [(set (match_dup 0) (plus:SI (reg:SI T_REG) (match_dup 2))) + (clobber (reg:SI T_REG))])] +{ + emit_insn (gen_shll (gen_reg_rtx (SImode), operands[1])); +}) + +;; Use shll-addc to do 'reg + reg + ((unsigned int)reg >> 31)'. +(define_insn_and_split "*addc" + [(set (match_operand:SI 0 "arith_reg_dest") + (plus:SI (plus:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand") + (const_int 31)) + (match_operand:SI 2 "arith_reg_operand")) + (match_operand:SI 3 "arith_reg_operand"))) + (clobber (reg:SI T_REG))] + "TARGET_SH1" + "#" + "&& can_create_pseudo_p ()" + [(parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 2) (match_dup 3)) + (reg:SI T_REG))) + (clobber (reg:SI T_REG))])] +{ + emit_insn (gen_shll (gen_reg_rtx (SImode), operands[1])); +}) + +;; Canonicalize '2 * reg + ((unsigned int)reg >> 31)' +;; into 'reg + reg + (reg & 1)'. +(define_insn_and_split "*addc" + [(set (match_operand:SI 0 "arith_reg_dest") + (plus:SI (mult:SI (match_operand:SI 1 "arith_reg_operand") + (const_int 2)) + (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand") + (const_int 31)))) + (clobber (reg:SI T_REG))] + "TARGET_SH1" + "#" + "&& can_create_pseudo_p ()" + [(parallel [(set (match_dup 0) + (plus:SI (plus:SI (lshiftrt:SI (match_dup 2) (const_int 31)) + (match_dup 1)) + (match_dup 1))) + (clobber (reg:SI T_REG))])]) + (define_expand "addsi3" [(set (match_operand:SI 0 "arith_reg_operand" "") (plus:SI (match_operand:SI 1 "arith_operand" "") Index: gcc/config/sh/sh.c =================================================================== --- gcc/config/sh/sh.c (revision 204096) +++ gcc/config/sh/sh.c (working copy) @@ -3162,6 +3162,35 @@ static inline int addsubcosts (rtx x) { + if (GET_MODE (x) == SImode) + { + /* The addc or subc patterns will eventually become one or two + instructions. Below are some costs for some of the patterns + which combine would reject because the costs of the individual + insns in the patterns are lower. + + FIXME: It would be much easier if we had something like insn cost + attributes and the cost calculation machinery used those attributes + in the first place. This would eliminate redundant recog-like C + code to calculate costs of complex patterns. */ + rtx op0 = XEXP (x, 0); + rtx op1 = XEXP (x, 1); + + if (GET_CODE (x) == PLUS) + { + if (GET_CODE (op0) == AND + && XEXP (op0, 1) == const1_rtx + && (GET_CODE (op1) == PLUS + || (GET_CODE (op1) == MULT && XEXP (op1, 1) == const2_rtx))) + return 1; + + if (GET_CODE (op0) == MULT && XEXP (op0, 1) == const2_rtx + && GET_CODE (op1) == LSHIFTRT + && CONST_INT_P (XEXP (op1, 1)) && INTVAL (XEXP (op1, 1)) == 31) + return 1; + } + } + /* On SH1-4 we have only max. SImode operations. Double the cost for modes > SImode. */ const int cost_scale = !TARGET_SHMEDIA Index: gcc/testsuite/gcc.target/sh/pr54236-2.c =================================================================== --- gcc/testsuite/gcc.target/sh/pr54236-2.c (revision 0) +++ gcc/testsuite/gcc.target/sh/pr54236-2.c (revision 0) @@ -0,0 +1,270 @@ +/* Tests to check the utilization of the addc instruction in special cases. + If everything works as expected we won't see any movt instructions in + these cases. */ +/* { dg-do compile { target "sh*-*-*" } } */ +/* { dg-options "-O1" } */ +/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */ +/* { dg-final { scan-assembler-times "addc" 37 } } */ +/* { dg-final { scan-assembler-times "shlr" 23 } } */ +/* { dg-final { scan-assembler-times "shll" 14 } } */ +/* { dg-final { scan-assembler-times "add\t" 12 } } */ +/* { dg-final { scan-assembler-not "movt" } } */ + +int +test_000 (int a, int c, int b, int d) +{ + // 1x shlr, 1x addc + return a + (b & 1); +} + +int +test_001 (int a, int c, int b, int d) +{ + // 1x shlr, 1x addc + return a + b + (c & 1); +} + +int +test_002 (int a, int c, int b, int d) +{ + // 1x shlr, 1x add, 1x addc + return a + b + c + (d & 1); +} + +int +test_003 (int a, int c, int b, int d) +{ + // 1x shlr, 1x addc + return (b & 1) + a; +} + +int +test_004 (int a, int c, int b, int d) +{ + // 1x shlr, 1x addc + return a + (c & 1) + b; +} + +int +test_005 (int a, int c, int b, int d) +{ + // 1x shlr, 1x add, 1x addc + return a + b + (d & 1) + c; +} + +int +test_006 (int a, int c, int b, int d) +{ + // 1x shlr, 1x addc + return (c & 1) + a + b; +} + +int +test_007 (int a, int c, int b, int d) +{ + // 1x shlr, 1x add, 1x addc + return a + (d & 1) + b + c; +} + +int +test_008 (int a, int c, int b, int d) +{ + // 1x shlr, 1x add, 1x addc + return (d & 1) + a + b + c; +} + +int +test_009 (int a, int c, int b, int d) +{ + // 1x shlr, 1x addc + return a + b + (b & 1); +} + +int +test_010 (int a, int c, int b, int d) +{ + // 1x shlr, 1x addc + return a + (b & 1) + b; +} + +int +test_011 (int a, int c, int b, int d) +{ + // 1x shlr, 1x addc + return (b & 1) + a + b; +} + +int +test_012 (int a, int c, int b, int d) +{ + // 1x shlr, 1x add, 1x addc + return a + b + d + (b & 1); +} + +int +test_013 (int a, int c, int b, int d) +{ + // 1x shlr, 1x add, 1x addc + return a + d + (b & 1) + b; +} + +int +test_014 (int a, int c, int b, int d) +{ + // 1x shlr, 1x add, 1x addc + return a + (b & 1) + d + b; +} + +int +test_015 (int a, int c, int b, int d) +{ + // 1x shlr, 1x add, 1x addc + return (b & 1) + a + d + b; +} + +int +test_016 (int a, int b, int c, int d) +{ + // 1x shlr, 1x addc + return a + (a & 1); +} + +int +test_017 (int a, int b, int c, int d) +{ + // 1x shlr, 1x addc + return a + a + (a & 1); +} + +int +test_018 (int a, int b, int c, int d) +{ + // 1x shlr, 1x addc + return a + (a & 1) + a; +} + +int +test_019 (int a, int b, int c, int d) +{ + // 1x shlr, 1x addc + return (a & 1) + a + a; +} + +int +test_020 (int a, int b, int c, int d) +{ + // 1x shlr, 1x addc + return b + b + (a & 1); +} + +int +test_021 (int a, int b, int c, int d) +{ + // 1x shlr, 1x addc + return b + (a & 1) + b; +} + +int +test_022 (int a, int b, int c, int d) +{ + // 1x shlr, 1x addc + return (a & 1) + b + b; +} + +int +test_023 (int a, int b, int c, int d) +{ + // 1x shll, 1x addc + return a + ((b >> 31) & 1); +} + +int +test_024 (int a, int b, int c, int d) +{ + // 1x shll, 1x addc + return ((b >> 31) & 1) + a; +} + +int +test_025 (int a, int b, int c, int d) +{ + // 1x shll, 1x addc + return ((a >> 31) & 1) + a; +} + +int +test_026 (int a, int b, int c, int d) +{ + // 1x shll, 1x addc + return a + ((a >> 31) & 1); +} + +int +test_027 (int a, int b, int c, int d) +{ + // 1x shll, 1x addc + return a + b + ((c >> 31) & 1); +} + +int +test_028 (int a, int b, int c, int d) +{ + // 1x shll, 1x addc + return a + ((c >> 31) & 1) + b; +} + +int +test_029 (int a, int b, int c, int d) +{ + // 1x shll, 1x addc + return ((c >> 31) & 1) + a + b; +} + +int +test_030 (int a, int b, int c, int d) +{ + // 1x shll, 1x addc, 1x add + return a + b + c + ((d >> 31) & 1); +} + +int +test_031 (int a, int b, int c, int d) +{ + // 1x shll, 1x addc, 1x add + return a + b + ((d >> 31) & 1) + c; +} + +int +test_032 (int a, int b, int c, int d) +{ + // 1x shll, 1x addc, 1x add + return a + ((d >> 31) & 1) + b + c; +} + +int +test_033 (int a, int b, int c, int d) +{ + // 1x shll, 1x addc, 1x add + return ((d >> 31) & 1) + a + b + c; +} + +int +test_034 (int a, int b, int c, int d) +{ + // 1x shll, 1x addc + return a + a + ((d >> 31) & 1); +} + +int +test_035 (int a, int b, int c, int d) +{ + // 1x shll, 1x addc + return a + ((d >> 31) & 1) + a; +} + +int +test_036 (int a, int b, int c, int d) +{ + // 1x shll, 1x addc + return ((d >> 31) & 1) + a + a; +} Index: gcc/testsuite/gcc.target/sh/pr54089-6.c =================================================================== --- gcc/testsuite/gcc.target/sh/pr54089-6.c (revision 204096) +++ gcc/testsuite/gcc.target/sh/pr54089-6.c (working copy) @@ -3,7 +3,7 @@ /* { dg-options "-O1" } */ /* { dg-skip-if "" { "sh*-*-*" } { "-m5*" } { "" } } */ /* { dg-final { scan-assembler-times "rotr" 2 } } */ -/* { dg-final { scan-assembler-times "rotl" 2 } } */ +/* { dg-final { scan-assembler-times "rotl" 3 } } */ int test_00 (int a) @@ -28,3 +28,9 @@ { return ((a >> 1) & 0x7FFFFFFF) | (a << 31); } + +int +test_04 (int a) +{ + return a + a + ((a >> 31) & 1); +}