diff options
author | Jakub Jelinek <jakub@redhat.com> | 2011-08-23 17:51:45 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2011-08-23 17:51:45 +0200 |
commit | e2f008377225f76538d728cb16772e29091feb0f (patch) | |
tree | 62fb2f1d429ec029087fc74ce2fd3609e593cd39 | |
parent | e70e0b60724694c40064580368e5b93aae951842 (diff) | |
download | gcc-e2f008377225f76538d728cb16772e29091feb0f.zip gcc-e2f008377225f76538d728cb16772e29091feb0f.tar.gz gcc-e2f008377225f76538d728cb16772e29091feb0f.tar.bz2 |
re PR middle-end/50161 (wrong code with -fno-tree-ter and __builtin_popcountl)
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.
From-SVN: r177991
-rw-r--r-- | gcc/ChangeLog | 21 | ||||
-rw-r--r-- | gcc/config/avr/avr.md | 26 | ||||
-rw-r--r-- | gcc/config/bfin/bfin.md | 6 | ||||
-rw-r--r-- | gcc/config/c6x/c6x.md | 2 | ||||
-rw-r--r-- | gcc/doc/rtl.texi | 20 | ||||
-rw-r--r-- | gcc/optabs.c | 27 | ||||
-rw-r--r-- | gcc/simplify-rtx.c | 29 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/pr50161.c | 21 |
9 files changed, 114 insertions, 43 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3bb9318..6007136 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,24 @@ +2011-08-23 Jakub Jelinek <jakub@redhat.com> + + 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. + 2011-08-12 Michael Matz <matz@suse.de> * cfgexpand.c (expand_one_register_var): Use get_pointer_alignment. diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md index ad0febc..3541453 100644 --- a/gcc/config/avr/avr.md +++ b/gcc/config/avr/avr.md @@ -1,7 +1,7 @@ ;; Machine description for GNU compiler, ;; for ATMEL AVR micro controllers. ;; Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007, 2008, -;; 2009, 2010 Free Software Foundation, Inc. +;; 2009, 2010, 2011 Free Software Foundation, Inc. ;; Contributed by Denis Chertykov (chertykov@gmail.com) ;; This file is part of GCC. @@ -4124,7 +4124,7 @@ [(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 "*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 "*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 @@ [(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 "*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_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 @@ [(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 "*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 @@ [(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 "*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 @@ [(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 "*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))] "" diff --git a/gcc/config/bfin/bfin.md b/gcc/config/bfin/bfin.md index 8d8413d..9c8d4c2 100644 --- a/gcc/config/bfin/bfin.md +++ b/gcc/config/bfin/bfin.md @@ -1,5 +1,5 @@ ;;- Machine description for Blackfin for GNU compiler -;; Copyright 2005, 2006, 2007, 2008 Free Software Foundation, Inc. +;; Copyright 2005, 2006, 2007, 2008, 2011 Free Software Foundation, Inc. ;; Contributed by Analog Devices. ;; This file is part of GCC. @@ -1463,7 +1463,7 @@ (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_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")]) diff --git a/gcc/config/c6x/c6x.md b/gcc/config/c6x/c6x.md index e8e15b2..4554cd0 100644 --- a/gcc/config/c6x/c6x.md +++ b/gcc/config/c6x/c6x.md @@ -2014,7 +2014,7 @@ (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); diff --git a/gcc/doc/rtl.texi b/gcc/doc/rtl.texi index 0d60594..b5cb285 100644 --- a/gcc/doc/rtl.texi +++ b/gcc/doc/rtl.texi @@ -1,5 +1,5 @@ @c Copyright (C) 1988, 1989, 1992, 1994, 1997, 1998, 1999, 2000, 2001, 2002, -@c 2003, 2004, 2005, 2006, 2007, 2008, 2010 +@c 2003, 2004, 2005, 2006, 2007, 2008, 2010, 2011 @c Free Software Foundation, Inc. @c This is part of the GCC manual. @c For copying conditions, see the file gcc.texi. @@ -2408,9 +2408,8 @@ Most often @var{m} will be a floating point mode. @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 leading sign bits in @var{x}, 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 most significant bit position. 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 least significant bit position. 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 diff --git a/gcc/optabs.c b/gcc/optabs.c index a70119a..886b259 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -216,7 +216,32 @@ add_equal_note (rtx insns, rtx target, enum rtx_code code, rtx op0, rtx op1) } 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)); diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index eb328e5..ef5ea1a 100644 --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -1373,8 +1373,7 @@ simplify_const_unary_operation (enum rtx_code code, enum machine_mode mode, } 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_code code, enum machine_mode mode, 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; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index bac7961..5eb38de 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2011-08-23 Jakub Jelinek <jakub@redhat.com> + + PR middle-end/50161 + * gcc.dg/pr50161.c: New test. + 2011-08-23 Siddhesh Poyarekar <siddhesh.poyarekar@gmail.com> PR c++/50055 diff --git a/gcc/testsuite/gcc.dg/pr50161.c b/gcc/testsuite/gcc.dg/pr50161.c new file mode 100644 index 0000000..b76ff9a --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr50161.c @@ -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; +} |