From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 11548 invoked by alias); 23 Aug 2011 12:06:50 -0000 Received: (qmail 11526 invoked by uid 22791); 23 Aug 2011 12:06:44 -0000 X-SWARE-Spam-Status: No, hits=-6.8 required=5.0 tests=AWL,BAYES_00,RCVD_IN_DNSWL_HI,RP_MATCHES_RCVD,SPF_HELO_PASS,TW_CL X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 23 Aug 2011 12:06:29 +0000 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id p7NC68wf006968 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Tue, 23 Aug 2011 08:06:08 -0400 Received: from tyan-ft48-01.lab.bos.redhat.com (tyan-ft48-01.lab.bos.redhat.com [10.16.42.4]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id p7NC66CK006332 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Tue, 23 Aug 2011 08:06:07 -0400 Received: from tyan-ft48-01.lab.bos.redhat.com (localhost.localdomain [127.0.0.1]) by tyan-ft48-01.lab.bos.redhat.com (8.14.4/8.14.4) with ESMTP id p7NC66Zu010059; Tue, 23 Aug 2011 14:06:06 +0200 Received: (from jakub@localhost) by tyan-ft48-01.lab.bos.redhat.com (8.14.4/8.14.4/Submit) id p7NC65D2010057; Tue, 23 Aug 2011 14:06:05 +0200 Date: Tue, 23 Aug 2011 13:43:00 -0000 From: Jakub Jelinek To: Bernd Schmidt Cc: Eric Botcazou , Richard Sandiford , Richard Henderson , GCC Patches Subject: [PATCH] For FFS/CLZ/CTZ/CLRSB/POPCOUNT/PARITY/BSWAP require operand mode equal to operation mode (or VOIDmode) (PR middle-end/50161) Message-ID: <20110823120605.GE2687@tyan-ft48-01.lab.bos.redhat.com> Reply-To: Jakub Jelinek References: <4DF9FA9A.8040505@codesourcery.com> <4DFA2E85.2030601@redhat.com> <4DFFA1AE.7070405@codesourcery.com> <20110823090549.GC2687@tyan-ft48-01.lab.bos.redhat.com> <4E53744B.6040502@codesourcery.com> <20110823095243.GD2687@tyan-ft48-01.lab.bos.redhat.com> <4E5379A6.1020905@codesourcery.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <4E5379A6.1020905@codesourcery.com> User-Agent: Mutt/1.5.21 (2010-09-15) X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org X-SW-Source: 2011-08/txt/msg01884.txt.bz2 On Tue, Aug 23, 2011 at 11:57:58AM +0200, Bernd Schmidt wrote: > On 08/23/11 11:52, Jakub Jelinek wrote: > > On Tue, Aug 23, 2011 at 11:35:07AM +0200, Bernd Schmidt wrote: > >>> cse_process_notes_1 > >>> perhaps could be changed for VOIDmode new_rtx to try to > >>> simplify_replace_rtx it... > >> > >> Is this where the problem came from? Sounds like it's worth a try. > > > > In this case, yes. But there are many other places all around the > > compiler that need to disallow unary op with VOIDmode operand. > > In cse.c alone e.g. fold_rtx (twice), in combine.c e.g. in do_SUBST, > > subst, etc. Do we want to special case all those 7 unary ops there too? > > Is it really worth it to save one subreg or truncate in the md patterns > > for rarely used rtxes? > > Maybe not. I'll approve a patch to change it back, even if I think it's > not a good representation. We can remove that restriction again once CONST_INTs are no longer VOIDmode. Here is an untested patch, will bootstrap/regtest it now on x86_64-linux and i686-linux, on c6x it should make no difference IMHO (looked like a typo in the expander which wasn't used anyway), can somebody test it on AVR and BFIN? My grepping through *.md didn't find any other places where the operand wouldn't have the same mode as operation. 2011-08-23 Jakub Jelinek PR middle-end/50161 * simplify-rtx.c (simplify_const_unary_operation): If op is CONST_INT, don't look at op_mode, but use instead mode. * optabs.c (add_equal_note): For FFS, CLZ, CTZ, CLRSB, POPCOUNT, PARITY and BSWAP use operand mode for operation and TRUNCATE/ZERO_EXTEND if needed. * doc/rtl.texi (ffs, clrsb, clz, ctz, popcount, parity, bswap): Document that operand mode must be same as operation mode, or VOIDmode. * config/avr/avr.md (paritysi2, *parityqihi2.libgcc, *paritysihi2.libgcc, popcountsi2, *popcountsi2.libgcc, *popcountqihi2.libgcc, clzsi2, *clzsihi2.libgcc, ctzsi2, *ctzsihi2.libgcc, ffssi2, *ffssihi2.libgcc): For unary ops use the mode of operand for the operation and add truncate or zero_extend around if needed. * config/c6x/c6x.md (ctzdi2): Likewise. * config/bfin/bfin.md (clrsbsi2, signbitssi2): Likewise. * gcc.dg/pr50161.c: New test. --- gcc/simplify-rtx.c.jj 2011-08-22 08:17:07.000000000 +0200 +++ gcc/simplify-rtx.c 2011-08-23 13:24:08.000000000 +0200 @@ -1373,8 +1373,7 @@ simplify_const_unary_operation (enum rtx } if (CONST_INT_P (op) - && width <= HOST_BITS_PER_WIDE_INT - && op_width <= HOST_BITS_PER_WIDE_INT && op_width > 0) + && width <= HOST_BITS_PER_WIDE_INT && width > 0) { HOST_WIDE_INT arg0 = INTVAL (op); HOST_WIDE_INT val; @@ -1394,50 +1393,50 @@ simplify_const_unary_operation (enum rtx break; case FFS: - arg0 &= GET_MODE_MASK (op_mode); + arg0 &= GET_MODE_MASK (mode); val = ffs_hwi (arg0); break; case CLZ: - arg0 &= GET_MODE_MASK (op_mode); - if (arg0 == 0 && CLZ_DEFINED_VALUE_AT_ZERO (op_mode, val)) + arg0 &= GET_MODE_MASK (mode); + if (arg0 == 0 && CLZ_DEFINED_VALUE_AT_ZERO (mode, val)) ; else - val = GET_MODE_PRECISION (op_mode) - floor_log2 (arg0) - 1; + val = GET_MODE_PRECISION (mode) - floor_log2 (arg0) - 1; break; case CLRSB: - arg0 &= GET_MODE_MASK (op_mode); + arg0 &= GET_MODE_MASK (mode); if (arg0 == 0) - val = GET_MODE_PRECISION (op_mode) - 1; + val = GET_MODE_PRECISION (mode) - 1; else if (arg0 >= 0) - val = GET_MODE_PRECISION (op_mode) - floor_log2 (arg0) - 2; + val = GET_MODE_PRECISION (mode) - floor_log2 (arg0) - 2; else if (arg0 < 0) - val = GET_MODE_PRECISION (op_mode) - floor_log2 (~arg0) - 2; + val = GET_MODE_PRECISION (mode) - floor_log2 (~arg0) - 2; break; case CTZ: - arg0 &= GET_MODE_MASK (op_mode); + arg0 &= GET_MODE_MASK (mode); if (arg0 == 0) { /* Even if the value at zero is undefined, we have to come up with some replacement. Seems good enough. */ - if (! CTZ_DEFINED_VALUE_AT_ZERO (op_mode, val)) - val = GET_MODE_PRECISION (op_mode); + if (! CTZ_DEFINED_VALUE_AT_ZERO (mode, val)) + val = GET_MODE_PRECISION (mode); } else val = ctz_hwi (arg0); break; case POPCOUNT: - arg0 &= GET_MODE_MASK (op_mode); + arg0 &= GET_MODE_MASK (mode); val = 0; while (arg0) val++, arg0 &= arg0 - 1; break; case PARITY: - arg0 &= GET_MODE_MASK (op_mode); + arg0 &= GET_MODE_MASK (mode); val = 0; while (arg0) val++, arg0 &= arg0 - 1; --- gcc/optabs.c.jj 2011-08-22 08:17:07.000000000 +0200 +++ gcc/optabs.c 2011-08-23 13:37:20.000000000 +0200 @@ -216,7 +216,32 @@ add_equal_note (rtx insns, rtx target, e } if (GET_RTX_CLASS (code) == RTX_UNARY) - note = gen_rtx_fmt_e (code, GET_MODE (target), copy_rtx (op0)); + switch (code) + { + case FFS: + case CLZ: + case CTZ: + case CLRSB: + case POPCOUNT: + case PARITY: + case BSWAP: + if (GET_MODE (op0) != VOIDmode && GET_MODE (target) != GET_MODE (op0)) + { + note = gen_rtx_fmt_e (code, GET_MODE (op0), copy_rtx (op0)); + if (GET_MODE_SIZE (GET_MODE (op0)) + > GET_MODE_SIZE (GET_MODE (target))) + note = simplify_gen_unary (TRUNCATE, GET_MODE (target), + note, GET_MODE (op0)); + else + note = simplify_gen_unary (ZERO_EXTEND, GET_MODE (target), + note, GET_MODE (op0)); + break; + } + /* FALLTHRU */ + default: + note = gen_rtx_fmt_e (code, GET_MODE (target), copy_rtx (op0)); + break; + } else note = gen_rtx_fmt_ee (code, GET_MODE (target), copy_rtx (op0), copy_rtx (op1)); --- gcc/doc/rtl.texi.jj 2011-07-21 09:54:33.000000000 +0200 +++ gcc/doc/rtl.texi 2011-08-23 12:56:44.000000000 +0200 @@ -2408,9 +2408,8 @@ Most often @var{m} will be a floating po @item (ffs:@var{m} @var{x}) Represents one plus the index of the least significant 1-bit in @var{x}, represented as an integer of mode @var{m}. (The value is -zero if @var{x} is zero.) The mode of @var{x} need not be @var{m}; -depending on the target machine, various mode combinations may be -valid. +zero if @var{x} is zero.) The mode of @var{x} must be @var{m} +or @code{VOIDmode}. @findex clrsb @item (clrsb:@var{m} @var{x}) @@ -2418,7 +2417,7 @@ Represents the number of redundant leadi represented as an integer of mode @var{m}, starting at the most significant bit position. This is one less than the number of leading sign bits (either 0 or 1), with no special cases. The mode of @var{x} -will usually be an integer mode and may differ from @var{m}. +must be @var{m} or @code{VOIDmode}. @findex clz @item (clz:@var{m} @var{x}) @@ -2427,7 +2426,7 @@ integer of mode @var{m}, starting at the If @var{x} is zero, the value is determined by @code{CLZ_DEFINED_VALUE_AT_ZERO} (@pxref{Misc}). Note that this is one of the few expressions that is not invariant under widening. The mode of -@var{x} will usually be an integer mode. +@var{x} must be @var{m} or @code{VOIDmode}. @findex ctz @item (ctz:@var{m} @var{x}) @@ -2436,23 +2435,24 @@ integer of mode @var{m}, starting at the If @var{x} is zero, the value is determined by @code{CTZ_DEFINED_VALUE_AT_ZERO} (@pxref{Misc}). Except for this case, @code{ctz(x)} is equivalent to @code{ffs(@var{x}) - 1}. The mode of -@var{x} will usually be an integer mode. +@var{x} must be @var{m} or @code{VOIDmode}. @findex popcount @item (popcount:@var{m} @var{x}) Represents the number of 1-bits in @var{x}, represented as an integer of -mode @var{m}. The mode of @var{x} will usually be an integer mode. +mode @var{m}. The mode of @var{x} must be @var{m} or @code{VOIDmode}. @findex parity @item (parity:@var{m} @var{x}) Represents the number of 1-bits modulo 2 in @var{x}, represented as an -integer of mode @var{m}. The mode of @var{x} will usually be an integer -mode. +integer of mode @var{m}. The mode of @var{x} must be @var{m} or +@code{VOIDmode}. @findex bswap @item (bswap:@var{m} @var{x}) Represents the value @var{x} with the order of bytes reversed, carried out in mode @var{m}, which must be a fixed-point machine mode. +The mode of @var{x} must be @var{m} or @code{VOIDmode}. @end table @node Comparisons --- gcc/config/avr/avr.md.jj 2011-08-18 08:35:54.000000000 +0200 +++ gcc/config/avr/avr.md 2011-08-23 12:46:13.000000000 +0200 @@ -4124,7 +4124,7 @@ (define_expand "paritysi2" [(set (reg:SI 22) (match_operand:SI 1 "register_operand" "")) (set (reg:HI 24) - (parity:HI (reg:SI 22))) + (truncate:HI (parity:SI (reg:SI 22)))) (set (match_dup 2) (reg:HI 24)) (set (match_operand:SI 0 "register_operand" "") @@ -4144,7 +4144,7 @@ (define_insn "*parityhi2.libgcc" (define_insn "*parityqihi2.libgcc" [(set (reg:HI 24) - (parity:HI (reg:QI 24)))] + (zero_extend:HI (parity:QI (reg:QI 24))))] "" "%~call __parityqi2" [(set_attr "type" "xcall") @@ -4152,7 +4152,7 @@ (define_insn "*parityqihi2.libgcc" (define_insn "*paritysihi2.libgcc" [(set (reg:HI 24) - (parity:HI (reg:SI 22)))] + (truncate:HI (parity:SI (reg:SI 22))))] "" "%~call __paritysi2" [(set_attr "type" "xcall") @@ -4175,7 +4175,7 @@ (define_expand "popcountsi2" [(set (reg:SI 22) (match_operand:SI 1 "register_operand" "")) (set (reg:HI 24) - (popcount:HI (reg:SI 22))) + (truncate:HI (popcount:SI (reg:SI 22)))) (set (match_dup 2) (reg:HI 24)) (set (match_operand:SI 0 "register_operand" "") @@ -4195,7 +4195,7 @@ (define_insn "*popcounthi2.libgcc" (define_insn "*popcountsi2.libgcc" [(set (reg:HI 24) - (popcount:HI (reg:SI 22)))] + (truncate:HI (popcount:SI (reg:SI 22))))] "" "%~call __popcountsi2" [(set_attr "type" "xcall") @@ -4211,7 +4211,7 @@ (define_insn "*popcountqi2.libgcc" (define_insn_and_split "*popcountqihi2.libgcc" [(set (reg:HI 24) - (popcount:HI (reg:QI 24)))] + (zero_extend:HI (popcount:QI (reg:QI 24))))] "" "#" "" @@ -4238,7 +4238,7 @@ (define_expand "clzsi2" [(set (reg:SI 22) (match_operand:SI 1 "register_operand" "")) (parallel [(set (reg:HI 24) - (clz:HI (reg:SI 22))) + (truncate:HI (clz:SI (reg:SI 22)))) (clobber (reg:QI 26))]) (set (match_dup 2) (reg:HI 24)) @@ -4260,7 +4260,7 @@ (define_insn "*clzhi2.libgcc" (define_insn "*clzsihi2.libgcc" [(set (reg:HI 24) - (clz:HI (reg:SI 22))) + (truncate:HI (clz:SI (reg:SI 22)))) (clobber (reg:QI 26))] "" "%~call __clzsi2" @@ -4284,7 +4284,7 @@ (define_expand "ctzsi2" [(set (reg:SI 22) (match_operand:SI 1 "register_operand" "")) (parallel [(set (reg:HI 24) - (ctz:HI (reg:SI 22))) + (truncate:HI (ctz:SI (reg:SI 22)))) (clobber (reg:QI 22)) (clobber (reg:QI 26))]) (set (match_dup 2) @@ -4307,7 +4307,7 @@ (define_insn "*ctzhi2.libgcc" (define_insn "*ctzsihi2.libgcc" [(set (reg:HI 24) - (ctz:HI (reg:SI 22))) + (truncate:HI (ctz:SI (reg:SI 22)))) (clobber (reg:QI 22)) (clobber (reg:QI 26))] "" @@ -4332,7 +4332,7 @@ (define_expand "ffssi2" [(set (reg:SI 22) (match_operand:SI 1 "register_operand" "")) (parallel [(set (reg:HI 24) - (ffs:HI (reg:SI 22))) + (truncate:HI (ffs:SI (reg:SI 22)))) (clobber (reg:QI 22)) (clobber (reg:QI 26))]) (set (match_dup 2) @@ -4355,7 +4355,7 @@ (define_insn "*ffshi2.libgcc" (define_insn "*ffssihi2.libgcc" [(set (reg:HI 24) - (ffs:HI (reg:SI 22))) + (truncate:HI (ffs:SI (reg:SI 22)))) (clobber (reg:QI 22)) (clobber (reg:QI 26))] "" --- gcc/config/c6x/c6x.md.jj 2011-07-15 20:46:48.000000000 +0200 +++ gcc/config/c6x/c6x.md 2011-08-23 12:36:20.000000000 +0200 @@ -2012,7 +2012,7 @@ (define_expand "ctzsi2" (define_expand "ctzdi2" [(set (match_operand:DI 0 "register_operand" "") - (ctz:SI (match_operand:DI 1 "register_operand" "")))] + (ctz:DI (match_operand:DI 1 "register_operand" "")))] "TARGET_INSNS_64" { rtx tmpreg = gen_reg_rtx (DImode); --- gcc/config/bfin/bfin.md.jj 2011-07-08 15:09:38.000000000 +0200 +++ gcc/config/bfin/bfin.md 2011-08-23 12:39:27.000000000 +0200 @@ -1463,7 +1463,7 @@ (define_insn "one_cmplsi2" (define_expand "clrsbsi2" [(set (match_dup 2) - (clrsb:HI (match_operand:SI 1 "register_operand" "d"))) + (truncate:HI (clrsb:SI (match_operand:SI 1 "register_operand" "d")))) (set (match_operand:SI 0 "register_operand") (zero_extend:SI (match_dup 2)))] "" @@ -1473,7 +1473,7 @@ (define_expand "clrsbsi2" (define_insn "signbitssi2" [(set (match_operand:HI 0 "register_operand" "=d") - (clrsb:HI (match_operand:SI 1 "register_operand" "d")))] + (truncate:HI (clrsb:SI (match_operand:SI 1 "register_operand" "d"))))] "" "%h0 = signbits %1%!" [(set_attr "type" "dsp32")]) --- gcc/testsuite/gcc.dg/pr50161.c.jj 2011-08-23 13:51:59.000000000 +0200 +++ gcc/testsuite/gcc.dg/pr50161.c 2011-08-23 13:31:14.000000000 +0200 @@ -0,0 +1,21 @@ +/* PR middle-end/50161 */ +/* { dg-do run } */ +/* { dg-options "-O2 -fno-tree-ter -funroll-loops" } */ + +extern void abort (void); + +int +main () +{ + unsigned i; + unsigned long a[16]; + + for (i = 0; i < 16; i++) + a[i] = ~0UL; + + for (i = 0; i < 16; i++) + if (__builtin_popcountl (a[i]) != sizeof (a[i]) * 8) + abort (); + + return 0; +} Jakub