From patchwork Sat May 11 08:47:01 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 243117 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 CN "localhost", Issuer "www.qmailtoaster.com" (not verified)) by ozlabs.org (Postfix) with ESMTPS id 606662C00CC for ; Sat, 11 May 2013 18:47:19 +1000 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:cc:subject:message-id:reply-to:references:mime-version :content-type:in-reply-to; q=dns; s=default; b=cf+pzzysOfjQubQOj RuLBqeesgcoDhumU0VBiGNXvWWa0fpzpioWt8cyFVTK7lu7RIYgw4K0E6bCGPr/j Xeve92uVYBpLjeKu8qQKo6cBRBfKIhzubTIrrjexdlK5fue4cIrOycG4Xxb78d0L rrIltpqxGXqLWmOOYcDz6VRuhc= 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:date :from:to:cc:subject:message-id:reply-to:references:mime-version :content-type:in-reply-to; s=default; bh=t4ffly7V4KZEcarnYIKCWQw Ydzk=; b=RUCVTR0d2bJ6vbBKS7vfrKH8XThXJvHp7SwBZfkt6PqsnAG+OcmBzpZ DFqtsCyzWUJV5Jfqo8etjQ6cU+buT2uB7DbeHSmmxAphrZl8jOAgfRPUyhlOVOPc i9/ocCbuwbsDVh9JdH0ynOTOA/G04rL522TTa0dhgIvfObrGjJmA= Received: (qmail 29717 invoked by alias); 11 May 2013 08:47:12 -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 29708 invoked by uid 89); 11 May 2013 08:47:12 -0000 X-Spam-SWARE-Status: No, score=-7.1 required=5.0 tests=AWL, BAYES_00, RCVD_IN_HOSTKARMA_W, RCVD_IN_HOSTKARMA_WL, RP_MATCHES_RCVD, SPF_HELO_PASS, SPF_PASS autolearn=ham version=3.3.1 Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.84/v0.84-167-ge50287c) with ESMTP; Sat, 11 May 2013 08:47:10 +0000 Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id r4B8l86b019092 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Sat, 11 May 2013 04:47:08 -0400 Received: from zalov.cz (vpn-59-174.rdu2.redhat.com [10.10.59.174]) by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id r4B8l6Kk010945 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Sat, 11 May 2013 04:47:07 -0400 Received: from zalov.cz (localhost [127.0.0.1]) by zalov.cz (8.14.5/8.14.5) with ESMTP id r4B8l4Pd013877; Sat, 11 May 2013 10:47:05 +0200 Received: (from jakub@localhost) by zalov.cz (8.14.5/8.14.5/Submit) id r4B8l29j013876; Sat, 11 May 2013 10:47:02 +0200 Date: Sat, 11 May 2013 10:47:01 +0200 From: Jakub Jelinek To: Jeff Law , Richard Biener Cc: gcc-patches@gcc.gnu.org Subject: [PATCH] Fix up rotate expansion (take 2) Message-ID: <20130511084701.GT1377@tucnak.redhat.com> Reply-To: Jakub Jelinek References: <20130510145355.GR1377@tucnak.redhat.com> <518D804A.9080609@redhat.com> <20130511070552.GS1377@tucnak.redhat.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20130511070552.GS1377@tucnak.redhat.com> User-Agent: Mutt/1.5.21 (2010-09-15) On Sat, May 11, 2013 at 09:05:52AM +0200, Jakub Jelinek wrote: > > Seems that we ought to have a testcase, even though it probably > > means scanning the tree dumps to pick up the undefined behaviour. > > Approved with a testcase. > > I have added lots of testcases recently, for rotation by zero perhaps > something similar to rotate-1a.c from above can be added as rotate-2b.c > and rotate-4b.c, and test zero rotation. Thanks for forcing me to do more testcases, I've actually found a serious bug in my recent patch. The (X << Y) OP (X >> ((-Y) & (B - 1))) style patterns can only be recognized as rotates if OP is |, because while they act as rotates for Y != 0, they act differently for Y == 0. For (X << Y) OP (X >> (B - Y)) that is not an issue, because for Y == 0 they trigger undefined behavior. Fixed thusly, plus added coverage for rotates by 0. And rotate-5.c testcase is to test the expmed.c change. 2013-05-10 Jakub Jelinek PR tree-optimization/45216 PR tree-optimization/57157 * tree-ssa-forwprop.c (simplify_rotate): Only recognize the (-Y) & (B - 1) variant if OP is |. * expmed.c (expand_shift_1): For rotations by const0_rtx just return shifted. Use (-op1) & (prec - 1) as other_amount instead of prec - op1. * c-c++-common/rotate-1.c: Add 32 tests with +. * c-c++-common/rotate-1a.c: Adjust. * c-c++-common/rotate-2.c: Add 32 tests with +, expect only 48 rotates. * c-c++-common/rotate-2b.c: New test. * c-c++-common/rotate-3.c: Add 32 tests with +. * c-c++-common/rotate-4.c: Add 32 tests with +, expect only 48 rotates. * c-c++-common/rotate-4b.c: New test. * c-c++-common/rotate-5.c: New test. Jakub --- gcc/tree-ssa-forwprop.c.jj 2013-05-10 10:39:13.000000000 +0200 +++ gcc/tree-ssa-forwprop.c 2013-05-11 09:57:39.627194037 +0200 @@ -2135,10 +2135,10 @@ simplify_bitwise_binary (gimple_stmt_ite (X << (int) Y) OP (X >> (int) (B - Y)) ((T) ((T2) X << Y)) OP ((T) ((T2) X >> (B - Y))) ((T) ((T2) X << (int) Y)) OP ((T) ((T2) X >> (int) (B - Y))) - (X << Y) OP (X >> ((-Y) & (B - 1))) - (X << (int) Y) OP (X >> (int) ((-Y) & (B - 1))) - ((T) ((T2) X << Y)) OP ((T) ((T2) X >> ((-Y) & (B - 1)))) - ((T) ((T2) X << (int) Y)) OP ((T) ((T2) X >> (int) ((-Y) & (B - 1)))) + (X << Y) | (X >> ((-Y) & (B - 1))) + (X << (int) Y) | (X >> (int) ((-Y) & (B - 1))) + ((T) ((T2) X << Y)) | ((T) ((T2) X >> ((-Y) & (B - 1)))) + ((T) ((T2) X << (int) Y)) | ((T) ((T2) X >> (int) ((-Y) & (B - 1)))) and transform these into: X r<< CNT1 @@ -2293,7 +2293,8 @@ simplify_rotate (gimple_stmt_iterator *g && host_integerp (cdef_arg2[i], 0) && tree_low_cst (cdef_arg2[i], 0) == TYPE_PRECISION (rtype) - 1 - && TREE_CODE (cdef_arg1[i]) == SSA_NAME) + && TREE_CODE (cdef_arg1[i]) == SSA_NAME + && gimple_assign_rhs_code (stmt) == BIT_IOR_EXPR) { tree tem; enum tree_code code; --- gcc/expmed.c.jj 2013-05-07 10:26:46.000000000 +0200 +++ gcc/expmed.c 2013-05-11 09:11:54.087412982 +0200 @@ -2166,7 +2166,8 @@ expand_shift_1 (enum tree_code code, enu { /* If we have been unable to open-code this by a rotation, do it as the IOR of two shifts. I.e., to rotate A - by N bits, compute (A << N) | ((unsigned) A >> (C - N)) + by N bits, compute + (A << N) | ((unsigned) A >> ((-N) & (C - 1))) where C is the bitsize of A. It is theoretically possible that the target machine might @@ -2181,14 +2182,22 @@ expand_shift_1 (enum tree_code code, enu rtx temp1; new_amount = op1; - if (CONST_INT_P (op1)) + if (op1 == const0_rtx) + return shifted; + else if (CONST_INT_P (op1)) other_amount = GEN_INT (GET_MODE_BITSIZE (mode) - INTVAL (op1)); else - other_amount - = simplify_gen_binary (MINUS, GET_MODE (op1), - GEN_INT (GET_MODE_PRECISION (mode)), - op1); + { + other_amount + = simplify_gen_unary (NEG, GET_MODE (op1), + op1, GET_MODE (op1)); + other_amount + = simplify_gen_binary (AND, GET_MODE (op1), + other_amount, + GEN_INT (GET_MODE_PRECISION (mode) + - 1)); + } shifted = force_reg (mode, shifted); --- gcc/testsuite/c-c++-common/rotate-1.c.jj 2013-05-10 10:39:13.000000000 +0200 +++ gcc/testsuite/c-c++-common/rotate-1.c 2013-05-11 10:11:22.725252954 +0200 @@ -1,7 +1,7 @@ /* Check rotate pattern detection. */ /* { dg-do compile } */ /* { dg-options "-O2 -fdump-tree-optimized" } */ -/* { dg-final { scan-tree-dump-times "r\[<>]\[<>]" 64 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "r\[<>]\[<>]" 96 "optimized" } } */ /* { dg-final { cleanup-tree-dump "optimized" } } */ unsigned int @@ -387,3 +387,195 @@ f64 (unsigned char x, unsigned long int { return (x << (__CHAR_BIT__ * sizeof (unsigned char) - y)) ^ (x >> y); } + +unsigned int +f65 (unsigned int x, unsigned int y) +{ + return (x << y) + (x >> (__CHAR_BIT__ * __SIZEOF_INT__ - y)); +} + +unsigned int +f66 (unsigned int x, unsigned long int y) +{ + return (x << y) + (x >> (__CHAR_BIT__ * __SIZEOF_INT__ - y)); +} + +unsigned int +f67 (unsigned int x, int y __attribute__((unused))) +{ + return (x << 1) + (x >> (__CHAR_BIT__ * __SIZEOF_INT__ - 1)); +} + +unsigned int +f68 (unsigned int x, int y __attribute__((unused))) +{ + return (x << (__CHAR_BIT__ * __SIZEOF_INT__ - 1)) + (x >> 1); +} + +unsigned short int +f69 (unsigned short int x, unsigned int y) +{ + return (x << y) + (x >> (__CHAR_BIT__ * __SIZEOF_SHORT__ - y)); +} + +unsigned short int +f70 (unsigned short int x, unsigned long int y) +{ + return (x << y) + (x >> (__CHAR_BIT__ * __SIZEOF_SHORT__ - y)); +} + +unsigned char +f71 (unsigned char x, unsigned int y) +{ + return (x << y) + (x >> (__CHAR_BIT__ - y)); +} + +unsigned char +f72 (unsigned char x, unsigned long int y) +{ + return (x << y) + (x >> (__CHAR_BIT__ - y)); +} + +unsigned int +f73 (unsigned int x, unsigned int y) +{ + return (x << y) + (x >> (__CHAR_BIT__ * sizeof (unsigned int) - y)); +} + +unsigned int +f74 (unsigned int x, unsigned long int y) +{ + return (x << y) + (x >> (__CHAR_BIT__ * sizeof (unsigned int) - y)); +} + +unsigned int +f75 (unsigned int x, int y __attribute__((unused))) +{ + return (x << 1) + (x >> (__CHAR_BIT__ * sizeof (unsigned int) - 1)); +} + +unsigned int +f76 (unsigned int x, int y __attribute__((unused))) +{ + return (x << (__CHAR_BIT__ * sizeof (unsigned int) - 1)) + (x >> 1); +} + +unsigned short int +f77 (unsigned short int x, unsigned int y) +{ + return (x << y) + (x >> (__CHAR_BIT__ * sizeof (unsigned short) - y)); +} + +unsigned short int +f78 (unsigned short int x, unsigned long int y) +{ + return (x << y) + (x >> (__CHAR_BIT__ * sizeof (unsigned short) - y)); +} + +unsigned char +f79 (unsigned char x, unsigned int y) +{ + return (x << y) + (x >> (__CHAR_BIT__ * sizeof (unsigned char) - y)); +} + +unsigned char +f80 (unsigned char x, unsigned long int y) +{ + return (x << y) + (x >> (__CHAR_BIT__ * sizeof (unsigned char) - y)); +} + +unsigned int +f81 (unsigned int x, unsigned int y) +{ + return (x << (__CHAR_BIT__ * __SIZEOF_INT__ - y)) + (x >> y); +} + +unsigned int +f82 (unsigned int x, unsigned long int y) +{ + return (x << (__CHAR_BIT__ * __SIZEOF_INT__ - y)) + (x >> y); +} + +unsigned int +f83 (unsigned int x, int y __attribute__((unused))) +{ + return (x << (__CHAR_BIT__ * __SIZEOF_INT__ - 1)) + (x >> 1); +} + +unsigned int +f84 (unsigned int x, int y __attribute__((unused))) +{ + return (x << 1) + (x >> (__CHAR_BIT__ * __SIZEOF_INT__ - 1)); +} + +unsigned short int +f85 (unsigned short int x, unsigned int y) +{ + return (x << (__CHAR_BIT__ * __SIZEOF_SHORT__ - y)) + (x >> y); +} + +unsigned short int +f86 (unsigned short int x, unsigned long int y) +{ + return (x << (__CHAR_BIT__ * __SIZEOF_SHORT__ - y)) + (x >> y); +} + +unsigned char +f87 (unsigned char x, unsigned int y) +{ + return (x << (__CHAR_BIT__ - y)) + (x >> y); +} + +unsigned char +f88 (unsigned char x, unsigned long int y) +{ + return (x << (__CHAR_BIT__ - y)) + (x >> y); +} + +unsigned int +f89 (unsigned int x, unsigned int y) +{ + return (x << (__CHAR_BIT__ * sizeof (unsigned int) - y)) + (x >> y); +} + +unsigned int +f90 (unsigned int x, unsigned long int y) +{ + return (x << (__CHAR_BIT__ * sizeof (unsigned int) - y)) + (x >> y); +} + +unsigned int +f91 (unsigned int x, int y __attribute__((unused))) +{ + return (x << (__CHAR_BIT__ * sizeof (unsigned int) - 1)) + (x >> 1); +} + +unsigned int +f92 (unsigned int x, int y __attribute__((unused))) +{ + return (x << 1) + (x >> (__CHAR_BIT__ * sizeof (unsigned int) - 1)); +} + +unsigned short int +f93 (unsigned short int x, unsigned int y) +{ + return (x << (__CHAR_BIT__ * sizeof (unsigned short) - y)) + (x >> y); +} + +unsigned short int +f94 (unsigned short int x, unsigned long int y) +{ + return (x << (__CHAR_BIT__ * sizeof (unsigned short) - y)) + (x >> y); +} + +unsigned char +f95 (unsigned char x, unsigned int y) +{ + return (x << (__CHAR_BIT__ * sizeof (unsigned char) - y)) + (x >> y); +} + +unsigned char +f96 (unsigned char x, unsigned long int y) +{ + return (x << (__CHAR_BIT__ * sizeof (unsigned char) - y)) + (x >> y); +} --- gcc/testsuite/c-c++-common/rotate-1a.c.jj 2013-05-10 10:39:13.000000000 +0200 +++ gcc/testsuite/c-c++-common/rotate-1a.c 2013-05-11 10:16:15.702552070 +0200 @@ -21,13 +21,18 @@ unsigned int expected[] = { 0x2468acf, 0x2468acf, 0x91a2b3c, 0x2468acf0, 0xacf, 0xacf, 0xf, 0xf, 0x2468acf, 0x2468acf, 0x91a2b3c, 0x2468acf0, 0xacf, 0xacf, 0xf, 0xf, 0x2468acf, 0x2468acf, 0x91a2b3c, 0x2468acf0, 0xacf, 0xacf, 0xf, 0xf, +0x2468acf, 0x2468acf, 0x91a2b3c, 0x2468acf0, 0xacf, 0xacf, 0xf, 0xf, +0x91a2b3c0, 0x91a2b3c0, 0x2468acf0, 0x91a2b3c, 0xb3c2, 0xb3c2, 0xc3, 0xc3, +0x91a2b3c0, 0x91a2b3c0, 0x2468acf0, 0x91a2b3c, 0xb3c2, 0xb3c2, 0xc3, 0xc3, +0x2468acf, 0x2468acf, 0x91a2b3c, 0x2468acf0, 0xacf, 0xacf, 0xf, 0xf, 0x2468acf, 0x2468acf, 0x91a2b3c, 0x2468acf0, 0xacf, 0xacf, 0xf, 0xf }; #define F(n) __typeof (f##n) f##n __attribute__((noinline, noclone)); #define D(n) F(n##0) F(n##1) F(n##2) F(n##3) F(n##4) F(n##5) F(n##6) F(n##7) F(n##8) F(n##9) #define ALL \ F(1) F(2) F(3) F(4) F(5) F(6) F(7) F(8) F(9) \ -D(1) D(2) D(3) D(4) D(5) F(60) F(61) F(62) F(63) F(64) +D(1) D(2) D(3) D(4) D(5) D(6) D(7) D(8) \ +F(90) F(91) F(92) F(93) F(94) F(95) F(96) ALL int --- gcc/testsuite/c-c++-common/rotate-2.c.jj 2013-05-10 10:39:13.000000000 +0200 +++ gcc/testsuite/c-c++-common/rotate-2.c 2013-05-11 10:35:38.127716820 +0200 @@ -1,7 +1,9 @@ /* Check rotate pattern detection. */ /* { dg-do compile } */ /* { dg-options "-O2 -fdump-tree-optimized" } */ -/* { dg-final { scan-tree-dump-times "r\[<>]\[<>]" 64 "optimized" } } */ +/* Rotates should be recognized only in functions with | instead of + or ^, + or in functions that have constant shift counts (unused attribute on y). */ +/* { dg-final { scan-tree-dump-times "r\[<>]\[<>]" 48 "optimized" } } */ /* { dg-final { cleanup-tree-dump "optimized" } } */ unsigned int @@ -387,3 +389,195 @@ f64 (unsigned char x, unsigned long int { return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) ^ (x >> y); } + +unsigned int +f65 (unsigned int x, unsigned int y) +{ + return (x << y) + (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))); +} + +unsigned int +f66 (unsigned int x, unsigned long int y) +{ + return (x << y) + (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))); +} + +unsigned int +f67 (unsigned int x, int y __attribute__((unused))) +{ + return (x << 1) + (x >> ((-1) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))); +} + +unsigned int +f68 (unsigned int x, int y __attribute__((unused))) +{ + return (x << ((-1) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) + (x >> 1); +} + +unsigned short int +f69 (unsigned short int x, unsigned int y) +{ + return (x << y) + (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))); +} + +unsigned short int +f70 (unsigned short int x, unsigned long int y) +{ + return (x << y) + (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))); +} + +unsigned char +f71 (unsigned char x, unsigned int y) +{ + return (x << y) + (x >> ((-y) & (__CHAR_BIT__ - 1))); +} + +unsigned char +f72 (unsigned char x, unsigned long int y) +{ + return (x << y) + (x >> ((-y) & (__CHAR_BIT__ - 1))); +} + +unsigned int +f73 (unsigned int x, unsigned int y) +{ + return (x << y) + (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))); +} + +unsigned int +f74 (unsigned int x, unsigned long int y) +{ + return (x << y) + (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))); +} + +unsigned int +f75 (unsigned int x, int y __attribute__((unused))) +{ + return (x << 1) + (x >> ((-1) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))); +} + +unsigned int +f76 (unsigned int x, int y __attribute__((unused))) +{ + return (x << ((-1) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) + (x >> 1); +} + +unsigned short int +f77 (unsigned short int x, unsigned int y) +{ + return (x << y) + (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1))); +} + +unsigned short int +f78 (unsigned short int x, unsigned long int y) +{ + return (x << y) + (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1))); +} + +unsigned char +f79 (unsigned char x, unsigned int y) +{ + return (x << y) + (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1))); +} + +unsigned char +f80 (unsigned char x, unsigned long int y) +{ + return (x << y) + (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1))); +} + +unsigned int +f81 (unsigned int x, unsigned int y) +{ + return (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) + (x >> y); +} + +unsigned int +f82 (unsigned int x, unsigned long int y) +{ + return (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) + (x >> y); +} + +unsigned int +f83 (unsigned int x, int y __attribute__((unused))) +{ + return (x << ((-1) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) + (x >> 1); +} + +unsigned int +f84 (unsigned int x, int y __attribute__((unused))) +{ + return (x << 1) + (x >> ((-1) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))); +} + +unsigned short int +f85 (unsigned short int x, unsigned int y) +{ + return (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))) + (x >> y); +} + +unsigned short int +f86 (unsigned short int x, unsigned long int y) +{ + return (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))) + (x >> y); +} + +unsigned char +f87 (unsigned char x, unsigned int y) +{ + return (x << ((-y) & (__CHAR_BIT__ - 1))) + (x >> y); +} + +unsigned char +f88 (unsigned char x, unsigned long int y) +{ + return (x << ((-y) & (__CHAR_BIT__ - 1))) + (x >> y); +} + +unsigned int +f89 (unsigned int x, unsigned int y) +{ + return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) + (x >> y); +} + +unsigned int +f90 (unsigned int x, unsigned long int y) +{ + return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) + (x >> y); +} + +unsigned int +f91 (unsigned int x, int y __attribute__((unused))) +{ + return (x << ((-1) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) + (x >> 1); +} + +unsigned int +f92 (unsigned int x, int y __attribute__((unused))) +{ + return (x << 1) + (x >> ((-1) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))); +} + +unsigned short int +f93 (unsigned short int x, unsigned int y) +{ + return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1))) + (x >> y); +} + +unsigned short int +f94 (unsigned short int x, unsigned long int y) +{ + return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1))) + (x >> y); +} + +unsigned char +f95 (unsigned char x, unsigned int y) +{ + return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) + (x >> y); +} + +unsigned char +f96 (unsigned char x, unsigned long int y) +{ + return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) + (x >> y); +} --- gcc/testsuite/c-c++-common/rotate-2b.c.jj 2013-05-11 09:46:48.588912339 +0200 +++ gcc/testsuite/c-c++-common/rotate-2b.c 2013-05-11 10:19:22.767376497 +0200 @@ -0,0 +1,49 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -Wno-overflow" } */ + +extern +#ifdef __cplusplus +"C" +#endif +void abort (void); + +#ifndef ROTATE_N +#define ROTATE_N "rotate-2.c" +#endif + +#include ROTATE_N + +unsigned int expected[] = { +0x12345678, 0x12345678, 0x2468acf0, 0x91a2b3c, 0x5678, 0x5678, 0x78, 0x78, +0x12345678, 0x12345678, 0x2468acf0, 0x91a2b3c, 0x5678, 0x5678, 0x78, 0x78, +0x0, 0x0, 0x2468acf0, 0x91a2b3c, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x2468acf0, 0x91a2b3c, 0x0, 0x0, 0x0, 0x0, +0x12345678, 0x12345678, 0x91a2b3c, 0x2468acf0, 0x5678, 0x5678, 0x78, 0x78, +0x12345678, 0x12345678, 0x91a2b3c, 0x2468acf0, 0x5678, 0x5678, 0x78, 0x78, +0x0, 0x0, 0x91a2b3c, 0x2468acf0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x91a2b3c, 0x2468acf0, 0x0, 0x0, 0x0, 0x0, +0x2468acf0, 0x2468acf0, 0x2468acf0, 0x91a2b3c, 0xacf0, 0xacf0, 0xf0, 0xf0, +0x2468acf0, 0x2468acf0, 0x2468acf0, 0x91a2b3c, 0xacf0, 0xacf0, 0xf0, 0xf0, +0x2468acf0, 0x2468acf0, 0x91a2b3c, 0x2468acf0, 0xacf0, 0xacf0, 0xf0, 0xf0, +0x2468acf0, 0x2468acf0, 0x91a2b3c, 0x2468acf0, 0xacf0, 0xacf0, 0xf0, 0xf0 }; + +#define F(n) __typeof (f##n) f##n __attribute__((noinline, noclone)); +#define D(n) F(n##0) F(n##1) F(n##2) F(n##3) F(n##4) F(n##5) F(n##6) F(n##7) F(n##8) F(n##9) +#define ALL \ +F(1) F(2) F(3) F(4) F(5) F(6) F(7) F(8) F(9) \ +D(1) D(2) D(3) D(4) D(5) D(6) D(7) D(8) \ +F(90) F(91) F(92) F(93) F(94) F(95) F(96) +ALL + +int +main () +{ +#if __CHAR_BIT__ != 8 || __SIZEOF_SHORT__ != 2 || __SIZEOF_INT__ != 4 + return 0; +#else +#undef F +#define F(n) if ((unsigned int) f##n (0x12345678U, 0) != expected[n - 1]) abort (); + ALL + return 0; +#endif +} --- gcc/testsuite/c-c++-common/rotate-3.c.jj 2013-05-10 10:39:13.000000000 +0200 +++ gcc/testsuite/c-c++-common/rotate-3.c 2013-05-11 10:14:41.003101647 +0200 @@ -1,7 +1,7 @@ /* Check rotate pattern detection. */ /* { dg-do compile } */ /* { dg-options "-O2 -fdump-tree-optimized" } */ -/* { dg-final { scan-tree-dump-times "r\[<>]\[<>]" 64 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "r\[<>]\[<>]" 96 "optimized" } } */ /* { dg-final { cleanup-tree-dump "optimized" } } */ unsigned int @@ -387,3 +387,195 @@ f64 (unsigned char x, long int y) { return (x << (__CHAR_BIT__ * sizeof (unsigned char) - y)) ^ (x >> y); } + +unsigned int +f65 (unsigned int x, int y) +{ + return (x << y) + (x >> (__CHAR_BIT__ * __SIZEOF_INT__ - y)); +} + +unsigned int +f66 (unsigned int x, long int y) +{ + return (x << y) + (x >> (__CHAR_BIT__ * __SIZEOF_INT__ - y)); +} + +unsigned int +f67 (unsigned int x, int y __attribute__((unused))) +{ + return (x << 1) + (x >> (__CHAR_BIT__ * __SIZEOF_INT__ - 1)); +} + +unsigned int +f68 (unsigned int x, int y __attribute__((unused))) +{ + return (x << (__CHAR_BIT__ * __SIZEOF_INT__ - 1)) + (x >> 1); +} + +unsigned short int +f69 (unsigned short int x, int y) +{ + return (x << y) + (x >> (__CHAR_BIT__ * __SIZEOF_SHORT__ - y)); +} + +unsigned short int +f70 (unsigned short int x, long int y) +{ + return (x << y) + (x >> (__CHAR_BIT__ * __SIZEOF_SHORT__ - y)); +} + +unsigned char +f71 (unsigned char x, int y) +{ + return (x << y) + (x >> (__CHAR_BIT__ - y)); +} + +unsigned char +f72 (unsigned char x, long int y) +{ + return (x << y) + (x >> (__CHAR_BIT__ - y)); +} + +unsigned int +f73 (unsigned int x, int y) +{ + return (x << y) + (x >> (__CHAR_BIT__ * sizeof (unsigned int) - y)); +} + +unsigned int +f74 (unsigned int x, long int y) +{ + return (x << y) + (x >> (__CHAR_BIT__ * sizeof (unsigned int) - y)); +} + +unsigned int +f75 (unsigned int x, int y __attribute__((unused))) +{ + return (x << 1) + (x >> (__CHAR_BIT__ * sizeof (unsigned int) - 1)); +} + +unsigned int +f76 (unsigned int x, int y __attribute__((unused))) +{ + return (x << (__CHAR_BIT__ * sizeof (unsigned int) - 1)) + (x >> 1); +} + +unsigned short int +f77 (unsigned short int x, int y) +{ + return (x << y) + (x >> (__CHAR_BIT__ * sizeof (unsigned short) - y)); +} + +unsigned short int +f78 (unsigned short int x, long int y) +{ + return (x << y) + (x >> (__CHAR_BIT__ * sizeof (unsigned short) - y)); +} + +unsigned char +f79 (unsigned char x, int y) +{ + return (x << y) + (x >> (__CHAR_BIT__ * sizeof (unsigned char) - y)); +} + +unsigned char +f80 (unsigned char x, long int y) +{ + return (x << y) + (x >> (__CHAR_BIT__ * sizeof (unsigned char) - y)); +} + +unsigned int +f81 (unsigned int x, int y) +{ + return (x << (__CHAR_BIT__ * __SIZEOF_INT__ - y)) + (x >> y); +} + +unsigned int +f82 (unsigned int x, long int y) +{ + return (x << (__CHAR_BIT__ * __SIZEOF_INT__ - y)) + (x >> y); +} + +unsigned int +f83 (unsigned int x, int y __attribute__((unused))) +{ + return (x << (__CHAR_BIT__ * __SIZEOF_INT__ - 1)) + (x >> 1); +} + +unsigned int +f84 (unsigned int x, int y __attribute__((unused))) +{ + return (x << 1) + (x >> (__CHAR_BIT__ * __SIZEOF_INT__ - 1)); +} + +unsigned short int +f85 (unsigned short int x, int y) +{ + return (x << (__CHAR_BIT__ * __SIZEOF_SHORT__ - y)) + (x >> y); +} + +unsigned short int +f86 (unsigned short int x, long int y) +{ + return (x << (__CHAR_BIT__ * __SIZEOF_SHORT__ - y)) + (x >> y); +} + +unsigned char +f87 (unsigned char x, int y) +{ + return (x << (__CHAR_BIT__ - y)) + (x >> y); +} + +unsigned char +f88 (unsigned char x, long int y) +{ + return (x << (__CHAR_BIT__ - y)) + (x >> y); +} + +unsigned int +f89 (unsigned int x, int y) +{ + return (x << (__CHAR_BIT__ * sizeof (unsigned int) - y)) + (x >> y); +} + +unsigned int +f90 (unsigned int x, long int y) +{ + return (x << (__CHAR_BIT__ * sizeof (unsigned int) - y)) + (x >> y); +} + +unsigned int +f91 (unsigned int x, int y __attribute__((unused))) +{ + return (x << (__CHAR_BIT__ * sizeof (unsigned int) - 1)) + (x >> 1); +} + +unsigned int +f92 (unsigned int x, int y __attribute__((unused))) +{ + return (x << 1) + (x >> (__CHAR_BIT__ * sizeof (unsigned int) - 1)); +} + +unsigned short int +f93 (unsigned short int x, int y) +{ + return (x << (__CHAR_BIT__ * sizeof (unsigned short) - y)) + (x >> y); +} + +unsigned short int +f94 (unsigned short int x, long int y) +{ + return (x << (__CHAR_BIT__ * sizeof (unsigned short) - y)) + (x >> y); +} + +unsigned char +f95 (unsigned char x, int y) +{ + return (x << (__CHAR_BIT__ * sizeof (unsigned char) - y)) + (x >> y); +} + +unsigned char +f96 (unsigned char x, long int y) +{ + return (x << (__CHAR_BIT__ * sizeof (unsigned char) - y)) + (x >> y); +} --- gcc/testsuite/c-c++-common/rotate-4.c.jj 2013-05-10 10:39:13.000000000 +0200 +++ gcc/testsuite/c-c++-common/rotate-4.c 2013-05-11 10:35:56.784601368 +0200 @@ -1,7 +1,9 @@ /* Check rotate pattern detection. */ /* { dg-do compile } */ /* { dg-options "-O2 -fdump-tree-optimized" } */ -/* { dg-final { scan-tree-dump-times "r\[<>]\[<>]" 64 "optimized" } } */ +/* Rotates should be recognized only in functions with | instead of + or ^, + or in functions that have constant shift counts (unused attribute on y). */ +/* { dg-final { scan-tree-dump-times "r\[<>]\[<>]" 48 "optimized" } } */ /* { dg-final { cleanup-tree-dump "optimized" } } */ unsigned int @@ -387,3 +389,195 @@ f64 (unsigned char x, long int y) { return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) ^ (x >> y); } + +unsigned int +f65 (unsigned int x, int y) +{ + return (x << y) + (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))); +} + +unsigned int +f66 (unsigned int x, long int y) +{ + return (x << y) + (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))); +} + +unsigned int +f67 (unsigned int x, int y __attribute__((unused))) +{ + return (x << 1) + (x >> ((-1) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))); +} + +unsigned int +f68 (unsigned int x, int y __attribute__((unused))) +{ + return (x << ((-1) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) + (x >> 1); +} + +unsigned short int +f69 (unsigned short int x, int y) +{ + return (x << y) + (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))); +} + +unsigned short int +f70 (unsigned short int x, long int y) +{ + return (x << y) + (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))); +} + +unsigned char +f71 (unsigned char x, int y) +{ + return (x << y) + (x >> ((-y) & (__CHAR_BIT__ - 1))); +} + +unsigned char +f72 (unsigned char x, long int y) +{ + return (x << y) + (x >> ((-y) & (__CHAR_BIT__ - 1))); +} + +unsigned int +f73 (unsigned int x, int y) +{ + return (x << y) + (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))); +} + +unsigned int +f74 (unsigned int x, long int y) +{ + return (x << y) + (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))); +} + +unsigned int +f75 (unsigned int x, int y __attribute__((unused))) +{ + return (x << 1) + (x >> ((-1) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))); +} + +unsigned int +f76 (unsigned int x, int y __attribute__((unused))) +{ + return (x << ((-1) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) + (x >> 1); +} + +unsigned short int +f77 (unsigned short int x, int y) +{ + return (x << y) + (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1))); +} + +unsigned short int +f78 (unsigned short int x, long int y) +{ + return (x << y) + (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1))); +} + +unsigned char +f79 (unsigned char x, int y) +{ + return (x << y) + (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1))); +} + +unsigned char +f80 (unsigned char x, long int y) +{ + return (x << y) + (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1))); +} + +unsigned int +f81 (unsigned int x, int y) +{ + return (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) + (x >> y); +} + +unsigned int +f82 (unsigned int x, long int y) +{ + return (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) + (x >> y); +} + +unsigned int +f83 (unsigned int x, int y __attribute__((unused))) +{ + return (x << ((-1) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) + (x >> 1); +} + +unsigned int +f84 (unsigned int x, int y __attribute__((unused))) +{ + return (x << 1) + (x >> ((-1) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))); +} + +unsigned short int +f85 (unsigned short int x, int y) +{ + return (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))) + (x >> y); +} + +unsigned short int +f86 (unsigned short int x, long int y) +{ + return (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))) + (x >> y); +} + +unsigned char +f87 (unsigned char x, int y) +{ + return (x << ((-y) & (__CHAR_BIT__ - 1))) + (x >> y); +} + +unsigned char +f88 (unsigned char x, long int y) +{ + return (x << ((-y) & (__CHAR_BIT__ - 1))) + (x >> y); +} + +unsigned int +f89 (unsigned int x, int y) +{ + return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) + (x >> y); +} + +unsigned int +f90 (unsigned int x, long int y) +{ + return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) + (x >> y); +} + +unsigned int +f91 (unsigned int x, int y __attribute__((unused))) +{ + return (x << ((-1) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) + (x >> 1); +} + +unsigned int +f92 (unsigned int x, int y __attribute__((unused))) +{ + return (x << 1) + (x >> ((-1) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))); +} + +unsigned short int +f93 (unsigned short int x, int y) +{ + return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1))) + (x >> y); +} + +unsigned short int +f94 (unsigned short int x, long int y) +{ + return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1))) + (x >> y); +} + +unsigned char +f95 (unsigned char x, int y) +{ + return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) + (x >> y); +} + +unsigned char +f96 (unsigned char x, long int y) +{ + return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) + (x >> y); +} --- gcc/testsuite/c-c++-common/rotate-4b.c.jj 2013-05-11 10:19:37.190287705 +0200 +++ gcc/testsuite/c-c++-common/rotate-4b.c 2013-05-11 10:31:46.249115585 +0200 @@ -0,0 +1,6 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -Wno-overflow" } */ + +#define ROTATE_N "rotate-4.c" + +#include "rotate-2b.c" --- gcc/testsuite/c-c++-common/rotate-5.c.jj 2013-05-11 10:20:17.094179336 +0200 +++ gcc/testsuite/c-c++-common/rotate-5.c 2013-05-11 10:29:06.360066035 +0200 @@ -0,0 +1,43 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +extern +#ifdef __cplusplus +"C" +#endif +void abort (void); + +#if __CHAR_BIT__ * __SIZEOF_LONG_LONG__ == 64 +__attribute__((noinline, noclone)) +unsigned long long +f1 (unsigned long long x, unsigned int y) +{ + return (x << y) | (x >> ((-y) & 63)); +} + +#if __CHAR_BIT__ * __SIZEOF_INT128__ == 128 +__attribute__((noinline, noclone)) +unsigned __int128 +f2 (unsigned __int128 x, unsigned int y) +{ + return (x << y) | (x >> ((-y) & 128)); +} +#endif +#endif + +int +main () +{ +#if __CHAR_BIT__ * __SIZEOF_LONG_LONG__ == 64 + if (f1 (0x123456789abcdef0ULL, 0) != 0x123456789abcdef0ULL) + abort (); +#if __CHAR_BIT__ * __SIZEOF_INT128__ == 128 + if (f2 ((((unsigned __int128) 0x123456789abcdef0ULL) << 64) + | 0x0fedcba987654321ULL, 0) + != ((((unsigned __int128) 0x123456789abcdef0ULL) << 64) + | 0x0fedcba987654321ULL)) + abort (); +#endif +#endif + return 0; +}