re PR middle-end/50161 (wrong code with -fno-tree-ter and __builtin_popcountl)
authorJakub Jelinek <jakub@redhat.com>
Tue, 23 Aug 2011 15:51:45 +0000 (17:51 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Tue, 23 Aug 2011 15:51:45 +0000 (17:51 +0200)
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

gcc/ChangeLog
gcc/config/avr/avr.md
gcc/config/bfin/bfin.md
gcc/config/c6x/c6x.md
gcc/doc/rtl.texi
gcc/optabs.c
gcc/simplify-rtx.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/pr50161.c [new file with mode: 0644]

index 3bb93182699133df6cc0df9ffe71625b879fccad..6007136d81e4c2f1a16aaaf7f615f6da759f6f65 100644 (file)
@@ -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.
index ad0febc333e7405cc3ecca6e7c110efb64940e8c..35414539ea2079dbd29787d8b84c0388db8f671e 100644 (file)
@@ -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.
   [(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" "")
 
 (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")
 
 (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")
   [(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" "")
 
 (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")
 
 (define_insn_and_split "*popcountqihi2.libgcc"
   [(set (reg:HI 24)
-        (popcount:HI (reg:QI 24)))]
+       (zero_extend:HI (popcount:QI (reg:QI 24))))]
   ""
   "#"
   ""
   [(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))
 
 (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"
   [(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)
 
 (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))]
   ""
   [(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)
 
 (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))]
   ""
index 8d8413de3046c6a89493ef686e1d9f37b5a1501c..9c8d4c26d3e88b743db11d29999ea90ea77bc9d2 100644 (file)
@@ -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.
 
 (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)))]
   ""
 
 (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")])
index e8e15b2ec56328e5f18da5cf2a078cee2caa4057..4554cd081303e891e747071d9999045700ac9535 100644 (file)
 
 (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);
index 0d60594e38eeeba9959fef89f915d2a27e35a4b1..b5cb285110d7949f1d79580d3dc300641ff0c16a 100644 (file)
@@ -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
index a70119abfdcc61f0b4905b65579c61eebeef88fe..886b259ce3472c94e0f9efb4ef2386eefcceb135 100644 (file)
@@ -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));
 
index eb328e521d4b23ea0f0a966fdd89ddf85610441d..ef5ea1aac33f45850aa0e6e9c77a9b26d3f0ed85 100644 (file)
@@ -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;
index bac79615945f8918d7870601076d0dc5885326bc..5eb38dec77a8a9f743ce1024b3afaf31ce2c0171 100644 (file)
@@ -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 (file)
index 0000000..b76ff9a
--- /dev/null
@@ -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;
+}