public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Jakub Jelinek <jakub@redhat.com>
To: Bernd Schmidt <bernds@codesourcery.com>
Cc: Eric Botcazou <ebotcazou@adacore.com>,
	       Richard Sandiford <richard.sandiford@linaro.org>,
	       Richard Henderson <rth@redhat.com>,
	       GCC Patches <gcc-patches@gcc.gnu.org>
Subject: [PATCH] For FFS/CLZ/CTZ/CLRSB/POPCOUNT/PARITY/BSWAP require operand mode equal to operation mode (or VOIDmode) (PR middle-end/50161)
Date: Tue, 23 Aug 2011 13:43:00 -0000	[thread overview]
Message-ID: <20110823120605.GE2687@tyan-ft48-01.lab.bos.redhat.com> (raw)
In-Reply-To: <4E5379A6.1020905@codesourcery.com>

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  <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.

	* 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

  reply	other threads:[~2011-08-23 12:06 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-06-16 13:06 Add __builtin_clrsb, similar to clz/ctz Bernd Schmidt
2011-06-16 13:10 ` Georg-Johann Lay
2011-06-16 13:56 ` Laurent Desnogues
2011-06-16 13:59   ` Bernd Schmidt
2011-06-16 17:03 ` Richard Henderson
2011-06-20 20:32   ` Bernd Schmidt
2011-06-20 20:48     ` Richard Henderson
2011-06-21 16:39     ` [PATCH] Fix __bultin_clrsb* (PR middle-end/49489) Jakub Jelinek
2011-06-21 16:46       ` Bernd Schmidt
2011-06-23  6:23     ` Add __builtin_clrsb, similar to clz/ctz H.J. Lu
2011-07-12  3:50     ` Hans-Peter Nilsson
2011-08-23 10:07     ` Jakub Jelinek
2011-08-23 10:08       ` Bernd Schmidt
2011-08-23 10:19         ` Richard Guenther
2011-08-23 10:25         ` Jakub Jelinek
2011-08-23 10:34           ` Bernd Schmidt
2011-08-23 13:43             ` Jakub Jelinek [this message]
2011-08-23 14:54               ` [PATCH] For FFS/CLZ/CTZ/CLRSB/POPCOUNT/PARITY/BSWAP require operand mode equal to operation mode (or VOIDmode) (PR middle-end/50161) Georg-Johann Lay
2011-08-23 15:58               ` Jakub Jelinek
2011-08-23 16:16                 ` Bernd Schmidt
2011-08-23 10:45         ` Add __builtin_clrsb, similar to clz/ctz Richard Sandiford

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20110823120605.GE2687@tyan-ft48-01.lab.bos.redhat.com \
    --to=jakub@redhat.com \
    --cc=bernds@codesourcery.com \
    --cc=ebotcazou@adacore.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=richard.sandiford@linaro.org \
    --cc=rth@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).