Commit e2f00837 by Jakub Jelinek Committed by Jakub Jelinek

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
parent e70e0b60
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> 2011-08-12 Michael Matz <matz@suse.de>
* cfgexpand.c (expand_one_register_var): Use get_pointer_alignment. * cfgexpand.c (expand_one_register_var): Use get_pointer_alignment.
......
;; Machine description for GNU compiler, ;; Machine description for GNU compiler,
;; for ATMEL AVR micro controllers. ;; for ATMEL AVR micro controllers.
;; Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007, 2008, ;; 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) ;; Contributed by Denis Chertykov (chertykov@gmail.com)
;; This file is part of GCC. ;; This file is part of GCC.
...@@ -4124,7 +4124,7 @@ ...@@ -4124,7 +4124,7 @@
[(set (reg:SI 22) [(set (reg:SI 22)
(match_operand:SI 1 "register_operand" "")) (match_operand:SI 1 "register_operand" ""))
(set (reg:HI 24) (set (reg:HI 24)
(parity:HI (reg:SI 22))) (truncate:HI (parity:SI (reg:SI 22))))
(set (match_dup 2) (set (match_dup 2)
(reg:HI 24)) (reg:HI 24))
(set (match_operand:SI 0 "register_operand" "") (set (match_operand:SI 0 "register_operand" "")
...@@ -4144,7 +4144,7 @@ ...@@ -4144,7 +4144,7 @@
(define_insn "*parityqihi2.libgcc" (define_insn "*parityqihi2.libgcc"
[(set (reg:HI 24) [(set (reg:HI 24)
(parity:HI (reg:QI 24)))] (zero_extend:HI (parity:QI (reg:QI 24))))]
"" ""
"%~call __parityqi2" "%~call __parityqi2"
[(set_attr "type" "xcall") [(set_attr "type" "xcall")
...@@ -4152,7 +4152,7 @@ ...@@ -4152,7 +4152,7 @@
(define_insn "*paritysihi2.libgcc" (define_insn "*paritysihi2.libgcc"
[(set (reg:HI 24) [(set (reg:HI 24)
(parity:HI (reg:SI 22)))] (truncate:HI (parity:SI (reg:SI 22))))]
"" ""
"%~call __paritysi2" "%~call __paritysi2"
[(set_attr "type" "xcall") [(set_attr "type" "xcall")
...@@ -4175,7 +4175,7 @@ ...@@ -4175,7 +4175,7 @@
[(set (reg:SI 22) [(set (reg:SI 22)
(match_operand:SI 1 "register_operand" "")) (match_operand:SI 1 "register_operand" ""))
(set (reg:HI 24) (set (reg:HI 24)
(popcount:HI (reg:SI 22))) (truncate:HI (popcount:SI (reg:SI 22))))
(set (match_dup 2) (set (match_dup 2)
(reg:HI 24)) (reg:HI 24))
(set (match_operand:SI 0 "register_operand" "") (set (match_operand:SI 0 "register_operand" "")
...@@ -4195,7 +4195,7 @@ ...@@ -4195,7 +4195,7 @@
(define_insn "*popcountsi2.libgcc" (define_insn "*popcountsi2.libgcc"
[(set (reg:HI 24) [(set (reg:HI 24)
(popcount:HI (reg:SI 22)))] (truncate:HI (popcount:SI (reg:SI 22))))]
"" ""
"%~call __popcountsi2" "%~call __popcountsi2"
[(set_attr "type" "xcall") [(set_attr "type" "xcall")
...@@ -4211,7 +4211,7 @@ ...@@ -4211,7 +4211,7 @@
(define_insn_and_split "*popcountqihi2.libgcc" (define_insn_and_split "*popcountqihi2.libgcc"
[(set (reg:HI 24) [(set (reg:HI 24)
(popcount:HI (reg:QI 24)))] (zero_extend:HI (popcount:QI (reg:QI 24))))]
"" ""
"#" "#"
"" ""
...@@ -4238,7 +4238,7 @@ ...@@ -4238,7 +4238,7 @@
[(set (reg:SI 22) [(set (reg:SI 22)
(match_operand:SI 1 "register_operand" "")) (match_operand:SI 1 "register_operand" ""))
(parallel [(set (reg:HI 24) (parallel [(set (reg:HI 24)
(clz:HI (reg:SI 22))) (truncate:HI (clz:SI (reg:SI 22))))
(clobber (reg:QI 26))]) (clobber (reg:QI 26))])
(set (match_dup 2) (set (match_dup 2)
(reg:HI 24)) (reg:HI 24))
...@@ -4260,7 +4260,7 @@ ...@@ -4260,7 +4260,7 @@
(define_insn "*clzsihi2.libgcc" (define_insn "*clzsihi2.libgcc"
[(set (reg:HI 24) [(set (reg:HI 24)
(clz:HI (reg:SI 22))) (truncate:HI (clz:SI (reg:SI 22))))
(clobber (reg:QI 26))] (clobber (reg:QI 26))]
"" ""
"%~call __clzsi2" "%~call __clzsi2"
...@@ -4284,7 +4284,7 @@ ...@@ -4284,7 +4284,7 @@
[(set (reg:SI 22) [(set (reg:SI 22)
(match_operand:SI 1 "register_operand" "")) (match_operand:SI 1 "register_operand" ""))
(parallel [(set (reg:HI 24) (parallel [(set (reg:HI 24)
(ctz:HI (reg:SI 22))) (truncate:HI (ctz:SI (reg:SI 22))))
(clobber (reg:QI 22)) (clobber (reg:QI 22))
(clobber (reg:QI 26))]) (clobber (reg:QI 26))])
(set (match_dup 2) (set (match_dup 2)
...@@ -4307,7 +4307,7 @@ ...@@ -4307,7 +4307,7 @@
(define_insn "*ctzsihi2.libgcc" (define_insn "*ctzsihi2.libgcc"
[(set (reg:HI 24) [(set (reg:HI 24)
(ctz:HI (reg:SI 22))) (truncate:HI (ctz:SI (reg:SI 22))))
(clobber (reg:QI 22)) (clobber (reg:QI 22))
(clobber (reg:QI 26))] (clobber (reg:QI 26))]
"" ""
...@@ -4332,7 +4332,7 @@ ...@@ -4332,7 +4332,7 @@
[(set (reg:SI 22) [(set (reg:SI 22)
(match_operand:SI 1 "register_operand" "")) (match_operand:SI 1 "register_operand" ""))
(parallel [(set (reg:HI 24) (parallel [(set (reg:HI 24)
(ffs:HI (reg:SI 22))) (truncate:HI (ffs:SI (reg:SI 22))))
(clobber (reg:QI 22)) (clobber (reg:QI 22))
(clobber (reg:QI 26))]) (clobber (reg:QI 26))])
(set (match_dup 2) (set (match_dup 2)
...@@ -4355,7 +4355,7 @@ ...@@ -4355,7 +4355,7 @@
(define_insn "*ffssihi2.libgcc" (define_insn "*ffssihi2.libgcc"
[(set (reg:HI 24) [(set (reg:HI 24)
(ffs:HI (reg:SI 22))) (truncate:HI (ffs:SI (reg:SI 22))))
(clobber (reg:QI 22)) (clobber (reg:QI 22))
(clobber (reg:QI 26))] (clobber (reg:QI 26))]
"" ""
......
;;- Machine description for Blackfin for GNU compiler ;;- 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. ;; Contributed by Analog Devices.
;; This file is part of GCC. ;; This file is part of GCC.
...@@ -1463,7 +1463,7 @@ ...@@ -1463,7 +1463,7 @@
(define_expand "clrsbsi2" (define_expand "clrsbsi2"
[(set (match_dup 2) [(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") (set (match_operand:SI 0 "register_operand")
(zero_extend:SI (match_dup 2)))] (zero_extend:SI (match_dup 2)))]
"" ""
...@@ -1473,7 +1473,7 @@ ...@@ -1473,7 +1473,7 @@
(define_insn "signbitssi2" (define_insn "signbitssi2"
[(set (match_operand:HI 0 "register_operand" "=d") [(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%!" "%h0 = signbits %1%!"
[(set_attr "type" "dsp32")]) [(set_attr "type" "dsp32")])
......
...@@ -2014,7 +2014,7 @@ ...@@ -2014,7 +2014,7 @@
(define_expand "ctzdi2" (define_expand "ctzdi2"
[(set (match_operand:DI 0 "register_operand" "") [(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" "TARGET_INSNS_64"
{ {
rtx tmpreg = gen_reg_rtx (DImode); rtx tmpreg = gen_reg_rtx (DImode);
......
@c Copyright (C) 1988, 1989, 1992, 1994, 1997, 1998, 1999, 2000, 2001, 2002, @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 Free Software Foundation, Inc.
@c This is part of the GCC manual. @c This is part of the GCC manual.
@c For copying conditions, see the file gcc.texi. @c For copying conditions, see the file gcc.texi.
...@@ -2408,9 +2408,8 @@ Most often @var{m} will be a floating point mode. ...@@ -2408,9 +2408,8 @@ Most often @var{m} will be a floating point mode.
@item (ffs:@var{m} @var{x}) @item (ffs:@var{m} @var{x})
Represents one plus the index of the least significant 1-bit in 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 @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}; zero if @var{x} is zero.) The mode of @var{x} must be @var{m}
depending on the target machine, various mode combinations may be or @code{VOIDmode}.
valid.
@findex clrsb @findex clrsb
@item (clrsb:@var{m} @var{x}) @item (clrsb:@var{m} @var{x})
...@@ -2418,7 +2417,7 @@ Represents the number of redundant leading sign bits in @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 represented as an integer of mode @var{m}, starting at the most
significant bit position. This is one less than the number of leading 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} 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 @findex clz
@item (clz:@var{m} @var{x}) @item (clz:@var{m} @var{x})
...@@ -2427,7 +2426,7 @@ integer of mode @var{m}, starting at the most significant bit position. ...@@ -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 If @var{x} is zero, the value is determined by
@code{CLZ_DEFINED_VALUE_AT_ZERO} (@pxref{Misc}). Note that this is one of @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 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 @findex ctz
@item (ctz:@var{m} @var{x}) @item (ctz:@var{m} @var{x})
...@@ -2436,23 +2435,24 @@ integer of mode @var{m}, starting at the least significant bit position. ...@@ -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 If @var{x} is zero, the value is determined by
@code{CTZ_DEFINED_VALUE_AT_ZERO} (@pxref{Misc}). Except for this case, @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 @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 @findex popcount
@item (popcount:@var{m} @var{x}) @item (popcount:@var{m} @var{x})
Represents the number of 1-bits in @var{x}, represented as an integer of 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 @findex parity
@item (parity:@var{m} @var{x}) @item (parity:@var{m} @var{x})
Represents the number of 1-bits modulo 2 in @var{x}, represented as an 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 integer of mode @var{m}. The mode of @var{x} must be @var{m} or
mode. @code{VOIDmode}.
@findex bswap @findex bswap
@item (bswap:@var{m} @var{x}) @item (bswap:@var{m} @var{x})
Represents the value @var{x} with the order of bytes reversed, carried out 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. 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 @end table
@node Comparisons @node Comparisons
......
...@@ -216,7 +216,32 @@ add_equal_note (rtx insns, rtx target, enum rtx_code code, rtx op0, rtx op1) ...@@ -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) 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 else
note = gen_rtx_fmt_ee (code, GET_MODE (target), copy_rtx (op0), copy_rtx (op1)); note = gen_rtx_fmt_ee (code, GET_MODE (target), copy_rtx (op0), copy_rtx (op1));
......
...@@ -1373,8 +1373,7 @@ simplify_const_unary_operation (enum rtx_code code, enum machine_mode mode, ...@@ -1373,8 +1373,7 @@ simplify_const_unary_operation (enum rtx_code code, enum machine_mode mode,
} }
if (CONST_INT_P (op) if (CONST_INT_P (op)
&& width <= HOST_BITS_PER_WIDE_INT && width <= HOST_BITS_PER_WIDE_INT && width > 0)
&& op_width <= HOST_BITS_PER_WIDE_INT && op_width > 0)
{ {
HOST_WIDE_INT arg0 = INTVAL (op); HOST_WIDE_INT arg0 = INTVAL (op);
HOST_WIDE_INT val; HOST_WIDE_INT val;
...@@ -1394,50 +1393,50 @@ simplify_const_unary_operation (enum rtx_code code, enum machine_mode mode, ...@@ -1394,50 +1393,50 @@ simplify_const_unary_operation (enum rtx_code code, enum machine_mode mode,
break; break;
case FFS: case FFS:
arg0 &= GET_MODE_MASK (op_mode); arg0 &= GET_MODE_MASK (mode);
val = ffs_hwi (arg0); val = ffs_hwi (arg0);
break; break;
case CLZ: case CLZ:
arg0 &= GET_MODE_MASK (op_mode); arg0 &= GET_MODE_MASK (mode);
if (arg0 == 0 && CLZ_DEFINED_VALUE_AT_ZERO (op_mode, val)) if (arg0 == 0 && CLZ_DEFINED_VALUE_AT_ZERO (mode, val))
; ;
else else
val = GET_MODE_PRECISION (op_mode) - floor_log2 (arg0) - 1; val = GET_MODE_PRECISION (mode) - floor_log2 (arg0) - 1;
break; break;
case CLRSB: case CLRSB:
arg0 &= GET_MODE_MASK (op_mode); arg0 &= GET_MODE_MASK (mode);
if (arg0 == 0) if (arg0 == 0)
val = GET_MODE_PRECISION (op_mode) - 1; val = GET_MODE_PRECISION (mode) - 1;
else if (arg0 >= 0) 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) else if (arg0 < 0)
val = GET_MODE_PRECISION (op_mode) - floor_log2 (~arg0) - 2; val = GET_MODE_PRECISION (mode) - floor_log2 (~arg0) - 2;
break; break;
case CTZ: case CTZ:
arg0 &= GET_MODE_MASK (op_mode); arg0 &= GET_MODE_MASK (mode);
if (arg0 == 0) if (arg0 == 0)
{ {
/* Even if the value at zero is undefined, we have to come /* Even if the value at zero is undefined, we have to come
up with some replacement. Seems good enough. */ up with some replacement. Seems good enough. */
if (! CTZ_DEFINED_VALUE_AT_ZERO (op_mode, val)) if (! CTZ_DEFINED_VALUE_AT_ZERO (mode, val))
val = GET_MODE_PRECISION (op_mode); val = GET_MODE_PRECISION (mode);
} }
else else
val = ctz_hwi (arg0); val = ctz_hwi (arg0);
break; break;
case POPCOUNT: case POPCOUNT:
arg0 &= GET_MODE_MASK (op_mode); arg0 &= GET_MODE_MASK (mode);
val = 0; val = 0;
while (arg0) while (arg0)
val++, arg0 &= arg0 - 1; val++, arg0 &= arg0 - 1;
break; break;
case PARITY: case PARITY:
arg0 &= GET_MODE_MASK (op_mode); arg0 &= GET_MODE_MASK (mode);
val = 0; val = 0;
while (arg0) while (arg0)
val++, arg0 &= arg0 - 1; val++, arg0 &= arg0 - 1;
......
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> 2011-08-23 Siddhesh Poyarekar <siddhesh.poyarekar@gmail.com>
PR c++/50055 PR c++/50055
......
/* 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;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment