From patchwork Wed Sep 19 16:22:37 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christophe Lyon X-Patchwork-Id: 185104 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 20FB12C0085 for ; Thu, 20 Sep 2012 02:23:06 +1000 (EST) Comment: DKIM? See http://www.dkim.org DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=gcc.gnu.org; s=default; x=1348676587; h=Comment: DomainKey-Signature:Received:Received:Received:Received: MIME-Version:Received:Received:Date:Message-ID:Subject:From:To: Content-Type:Mailing-List:Precedence:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:Sender:Delivered-To; bh=qd229vQ Yvoyv4Gwz8xUVdwiYUaM=; b=cJdnYs0gmz+w28cZM6rSVisXCjWU1BfLVO/3aYq ZqTyGXTn0yeMJUhBuFi2VgYAAHnfc+541mISvaKTZ0F+5ZVuWemrHTbJ1AMDDKFi ZKOxxXhFi9tmwTTbxSa149uhVbb3XAFLES7qyCFat4HimnSsiHl84FjqAuaEV9c0 D75g= Comment: DomainKeys? See http://antispam.yahoo.com/domainkeys DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=default; d=gcc.gnu.org; h=Received:Received:X-SWARE-Spam-Status:X-Spam-Check-By:Received:Received:X-Google-DKIM-Signature:MIME-Version:Received:Received:Date:Message-ID:Subject:From:To:Content-Type:X-Gm-Message-State:X-IsSubscribed:Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:Sender:Delivered-To; b=ajOTQpobMI/n35iHdn746nNJrqhEKaqQUoDrV5pbYhqqyvRqQ1ymlXDAtbqHB2 se5Vtq6FiTE6gaHxfESic622OvPOSuv5riZmY67olajwjFYuTSSahdeamAFWU4iI 2Art69+xsnNlLzSgrkH8TKoj/Er9JXYC3DVMfw6v6xc8s=; Received: (qmail 17467 invoked by alias); 19 Sep 2012 16:23:00 -0000 Received: (qmail 17441 invoked by uid 22791); 19 Sep 2012 16:22:53 -0000 X-SWARE-Spam-Status: No, hits=-2.2 required=5.0 tests=AWL, BAYES_00, KHOP_RCVD_UNTRUST, RCVD_IN_DNSWL_LOW, RCVD_IN_HOSTKARMA_YE, TW_QE X-Spam-Check-By: sourceware.org Received: from mail-qa0-f54.google.com (HELO mail-qa0-f54.google.com) (209.85.216.54) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 19 Sep 2012 16:22:38 +0000 Received: by qady23 with SMTP id y23so306475qad.20 for ; Wed, 19 Sep 2012 09:22:37 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=mime-version:date:message-id:subject:from:to:content-type :x-gm-message-state; bh=4eHRzcpU/BwYMlKZRMwakN2u4hEDfHETFfsL6JS8cOI=; b=aqrN82lUKKZ5+259MrM9hpMIpi6pC3Yu103x/71tmPXiSKWx9d1OWI48Odv/c2i8he 2bJNAWkYcJEtF1Qg/3IGqP3+7PJiXmKz/u01vdRgu+te3Yy7ynTdLCvnXJNLxYG9oeDo pXoaJRT5zJh5wqov7DJpOmnoeW1qwmXwaRSws3j4/DP1O+/0TSUlA+ktT/PTS9ZEpEgG hAUPEPd3YXQPUxWkLas5T1Zf75DpBCKdB4o5ucp1EFfZeIMejHaDXpWxAsPEnY/WjBPI wcnlVw57gcPztsPBNC8oyDqiWYEl9dlVrbUHaBMDix1aYlMb45My+Af6Kn1imp9268Ve lyHg== MIME-Version: 1.0 Received: by 10.224.212.3 with SMTP id gq3mr8177936qab.52.1348071757398; Wed, 19 Sep 2012 09:22:37 -0700 (PDT) Received: by 10.49.105.168 with HTTP; Wed, 19 Sep 2012 09:22:37 -0700 (PDT) Date: Wed, 19 Sep 2012 18:22:37 +0200 Message-ID: Subject: [Patch] catch builtin_bswap16 construct From: Christophe Lyon To: gcc-patches@gcc.gnu.org X-Gm-Message-State: ALoCoQkxTNgXOjlSPEnf/q9JzzLKJTZMX99HJ0/ZQ+XMqJVCE5rOFLspX0NxiRi+q+N0o4oL1yCN 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 Hi, The attached patch catches C constructs: (A << 8) | (A >> 8) where A is unsigned 16 bits and maps them to builtin_bswap16(A) which can provide more efficient implementations on some targets. The construct above is equivalent to the default bswap16 implementation. I have added a testcase for ARM, and have found no regression with qemu-arm on arm-none-linux-gnueabi. OK? Christophe 2012-09-19 Christophe Lyon gcc/ * fold-const.c (fold_binary_loc): call builtin_bswap16 when the equivalent construct is detected. gcc/testsuite/ * gcc.target/arm/builtin-bswap-2.c: New testcase. diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 2bf5179..0ff7e8b 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -10326,6 +10326,99 @@ fold_binary_loc (location_t loc, } } + /* Catch bswap16 construct: (A << 8) | (A >> 8) where A is + unsigned 16 bits. + This has been expanded into: + (ior:SI (lshift:SI (nop:SI A:HI) 8) + (nop:SI (rshift:HI A:HI 8))) + */ + { + enum tree_code code0, code1; + tree my_arg0 = arg0; + tree my_arg1= arg1; + tree rtype; + + code0 = TREE_CODE (arg0); + code1 = TREE_CODE (arg1); + if (code1 == NOP_EXPR) + { + my_arg1 = TREE_OPERAND (arg1, 0); + code1 = TREE_CODE (my_arg1); + } + else if (code0 == NOP_EXPR) + { + my_arg0 = TREE_OPERAND (arg0, 0); + code0 = TREE_CODE (my_arg0); + } + + /* Handle (A << C1) + (A >> C1). */ + if ((code1 == RSHIFT_EXPR && code0 == LSHIFT_EXPR) + && (TREE_CODE (TREE_OPERAND (my_arg0, 0)) == NOP_EXPR) + && operand_equal_p (TREE_OPERAND (TREE_OPERAND (my_arg0, 0), 0), + TREE_OPERAND (my_arg1, 0), 0) + && (rtype = TREE_TYPE (TREE_OPERAND (my_arg1, 0)), + TYPE_UNSIGNED (rtype))) + { + tree tree01, tree11; + enum tree_code code01, code11; + + tree01 = TREE_OPERAND (my_arg0, 1); + tree11 = TREE_OPERAND (my_arg1, 1); + STRIP_NOPS (tree01); + STRIP_NOPS (tree11); + code01 = TREE_CODE (tree01); + code11 = TREE_CODE (tree11); + + /* Check that shift amount is 8, and input 16 bits wide. */ + if (code01 == INTEGER_CST + && code11 == INTEGER_CST + && TREE_INT_CST_HIGH (tree01) == 0 + && TREE_INT_CST_HIGH (tree11) == 0 + && TREE_INT_CST_LOW (tree01) == TREE_INT_CST_LOW (tree11) + && TREE_INT_CST_LOW (tree01) == 8 + && TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (my_arg1, 0))) == 16) + { + tree bswapfn = builtin_decl_explicit (BUILT_IN_BSWAP16); + return build_call_expr_loc (loc, bswapfn, 1, + TREE_OPERAND (my_arg1, 0)); + } + } + + /* Handle (A >> C1) + (A << C1). */ + else if ((code0 == RSHIFT_EXPR && code1 == LSHIFT_EXPR) + && (TREE_CODE (TREE_OPERAND (my_arg1, 0)) == NOP_EXPR) + && operand_equal_p (TREE_OPERAND (TREE_OPERAND (my_arg1, 0), + 0), + TREE_OPERAND (my_arg0, 0), 0) + && (rtype = TREE_TYPE (TREE_OPERAND (my_arg0, 0)), + TYPE_UNSIGNED (rtype))) + { + tree tree01, tree11; + enum tree_code code01, code11; + + tree01 = TREE_OPERAND (my_arg0, 1); + tree11 = TREE_OPERAND (my_arg1, 1); + STRIP_NOPS (tree01); + STRIP_NOPS (tree11); + code01 = TREE_CODE (tree01); + code11 = TREE_CODE (tree11); + + /* Check that shift amount is 8, and input 16 bits wide. */ + if (code01 == INTEGER_CST + && code11 == INTEGER_CST + && TREE_INT_CST_HIGH (tree01) == 0 + && TREE_INT_CST_HIGH (tree11) == 0 + && TREE_INT_CST_LOW (tree01) == TREE_INT_CST_LOW (tree11) + && TREE_INT_CST_LOW (tree01) == 8 + && TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (my_arg0, 0))) == 16) + { + tree bswapfn = builtin_decl_explicit (BUILT_IN_BSWAP16); + return build_call_expr_loc (loc, bswapfn, 1, + TREE_OPERAND (my_arg0, 0)); + } + } + } + associate: /* In most languages, can't associate operations on floats through parentheses. Rather than remember where the parentheses were, we diff --git a/gcc/testsuite/gcc.target/arm/builtin-bswap-2.c b/gcc/testsuite/gcc.target/arm/builtin-bswap-2.c new file mode 100644 index 0000000..93dbb35 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/builtin-bswap-2.c @@ -0,0 +1,25 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ +/* { dg-require-effective-target arm_arch_v6_ok } */ +/* { dg-add-options arm_arch_v6 } */ +/* { dg-final { scan-assembler-not "orr\[ \t\]" } } */ + +unsigned short swapu16_1 (unsigned short x) +{ + return (x << 8) | (x >> 8); +} + +unsigned short swapu16_2 (unsigned short x) +{ + return (x >> 8) | (x << 8); +} + +unsigned int swapu32_1 (unsigned int x) +{ + return (x << 16) | (x >> 16); +} + +unsigned int swapu32_2 (unsigned int x) +{ + return (x >> 16) | (x << 16); +}