public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Richard Sandiford <richard.sandiford@arm.com>
To: Dimitar Dimitrov <dimitar@dinux.eu>
Cc: gcc-patches@gcc.gnu.org, rguenther@suse.de
Subject: Re: [committed] pru: Fix CLZ expansion for QI and HI modes
Date: Tue, 24 Jan 2023 09:32:19 +0000	[thread overview]
Message-ID: <mpth6wgnuqk.fsf@arm.com> (raw)
In-Reply-To: <20230122195040.746214-1-dimitar@dinux.eu> (Dimitar Dimitrov's message of "Sun, 22 Jan 2023 21:50:40 +0200")

Dimitar Dimitrov <dimitar@dinux.eu> writes:
> The recent gcc.dg/tree-ssa/clz-char.c test case failed for PRU target,
> exposing a wrong code generation bug in the PRU backend.  The "clz"
> pattern did not produce correct output for QI and HI input operand
> modes.  SI mode is ok.
>
> The "clz" pattern is expanded to an LMBD instruction to get the
> left-most bit position having value "1".  In turn, to get the correct
> "clz" value, that bit position must be subtracted from the MSB bit
> position of the input operand.  The old behaviour of hard-coding 31
> for MSB bit position is wrong.
>
> The LMBD instruction returns 32 if input operand is zero, irrespective
> of its register mode.  This maps nicely for SI mode, where the "clz"
> pattern outputs -1.  It also leads to peculiar (but valid!) output
> values from the "clz" pattern for QI and HI zero-valued inputs.
>
> Pushed to trunk. This patch is confined to the PRU backend only,
> and is fixing a wrong code generation.  Hence I deem it suitable
> for stage 4.
>
> Is it ok to push a backport to gcc-11 and gcc-12 branches?

Since it's a backend-specific patch, I think that's your call.

Thanks,
Richard

> gcc/ChangeLog:
>
> 	* config/pru/pru.h (CLZ_DEFINED_VALUE_AT_ZERO): Fix value for QI
> 	and HI input modes.
> 	* config/pru/pru.md (clz): Fix generated code for QI and HI
> 	input modes.
>
> gcc/testsuite/ChangeLog:
>
> 	* gcc.target/pru/clz-hi-2.c: New test.
> 	* gcc.target/pru/clz-hi.c: New test.
>
> Signed-off-by: Dimitar Dimitrov <dimitar@dinux.eu>
> ---
>  gcc/config/pru/pru.h                    |  5 ++--
>  gcc/config/pru/pru.md                   | 15 ++++++++---
>  gcc/testsuite/gcc.target/pru/clz-hi-2.c | 24 +++++++++++++++++
>  gcc/testsuite/gcc.target/pru/clz-hi.c   | 35 +++++++++++++++++++++++++
>  4 files changed, 74 insertions(+), 5 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.target/pru/clz-hi-2.c
>  create mode 100644 gcc/testsuite/gcc.target/pru/clz-hi.c
>
> diff --git a/gcc/config/pru/pru.h b/gcc/config/pru/pru.h
> index 3658036cccb..1b5e874bc06 100644
> --- a/gcc/config/pru/pru.h
> +++ b/gcc/config/pru/pru.h
> @@ -566,8 +566,9 @@ do {									\
>  
>  #define CASE_VECTOR_MODE Pmode
>  
> -/* See definition of clz pattern for rationale of value -1.  */
> -#define CLZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) ((VALUE) = -1, 2)
> +/* See definition of clz pattern for rationale of the value.  */
> +#define CLZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE)	\
> +	((VALUE) = GET_MODE_BITSIZE (MODE) - 1 - 32, 2)
>  
>  /* Jumps are cheap on PRU.  */
>  #define LOGICAL_OP_NON_SHORT_CIRCUIT		0
> diff --git a/gcc/config/pru/pru.md b/gcc/config/pru/pru.md
> index dfe08071e04..aa8e42a3587 100644
> --- a/gcc/config/pru/pru.md
> +++ b/gcc/config/pru/pru.md
> @@ -1723,8 +1723,16 @@ (define_insn "pru_halt"
>    [(set_attr "type" "control")])
>  
>  ;; Count Leading Zeros implemented using LMBD.
> -;; LMBD returns 32 if bit value is not present, and we subtract 31 to get CLZ.
> -;; Hence we get a defined value -1 for CLZ_DEFINED_VALUE_AT_ZERO.
> +;;
> +;; LMBD returns 32 if bit value is not present, for any kind of input MODE.
> +;; The LMBD's search result for a "1" bit is subtracted from the
> +;; mode bit size minus one, in order to get CLZ.
> +;;
> +;; Hence for SImode we get a defined value -1 for CLZ_DEFINED_VALUE_AT_ZERO.
> +;;
> +;; The QImode and HImode defined values for zero inputs end up to be
> +;; non-standard (-25 and -17).  But this is considered acceptable in
> +;; order to keep the CLZ expansion to only two instructions.
>  (define_expand "clz<mode>2"
>    [(set (match_operand:QISI 0 "register_operand")
>  	(clz:QISI (match_operand:QISI 1 "register_operand")))]
> @@ -1735,7 +1743,8 @@ (define_expand "clz<mode>2"
>    rtx tmpval = gen_reg_rtx (<MODE>mode);
>  
>    emit_insn (gen_pru_lmbd (<MODE>mode, tmpval, src, const1_rtx));
> -  emit_insn (gen_sub3_insn (dst, GEN_INT (31), tmpval));
> +  int msb_bitn = GET_MODE_BITSIZE (<MODE>mode) - 1;
> +  emit_insn (gen_sub3_insn (dst, GEN_INT (msb_bitn), tmpval));
>    DONE;
>  })
>  
> diff --git a/gcc/testsuite/gcc.target/pru/clz-hi-2.c b/gcc/testsuite/gcc.target/pru/clz-hi-2.c
> new file mode 100644
> index 00000000000..af877c7021e
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/pru/clz-hi-2.c
> @@ -0,0 +1,24 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -fno-tree-ch" } */
> +
> +/* This test case is based on gcc.dg/tree-ssa/clz-char.c. */
> +
> +#define PREC (sizeof(short) * 8)
> +
> +int
> +__attribute__ ((noinline, noclone))
> +foo (unsigned short b) {
> +    int c = 0;
> +
> +    if (b == 0)
> +      return PREC;
> +
> +    while (!(b & (1 << (PREC - 1)))) {
> +	b <<= 1;
> +	c++;
> +    }
> +
> +    return c;
> +}
> +
> +/* { dg-final { scan-assembler "lmbd\\tr\[012\]\[0-9\]?.w\[0-2\], r\[012\]\[0-9\]?.w\[0-2\], 1" } } */
> diff --git a/gcc/testsuite/gcc.target/pru/clz-hi.c b/gcc/testsuite/gcc.target/pru/clz-hi.c
> new file mode 100644
> index 00000000000..9350913b6d5
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/pru/clz-hi.c
> @@ -0,0 +1,35 @@
> +/* { dg-do run } */
> +/* { dg-options "-O2 -fno-tree-ch -fdump-tree-optimized" } */
> +
> +/* This test case is based on gcc.dg/tree-ssa/clz-char.c. */
> +
> +#define PREC (sizeof(short) * 8)
> +
> +int
> +__attribute__ ((noinline, noclone))
> +foo (unsigned short b) {
> +    int c = 0;
> +
> +    if (b == 0)
> +      return PREC;
> +
> +    while (!(b & (1 << (PREC - 1)))) {
> +	b <<= 1;
> +	c++;
> +    }
> +
> +    return c;
> +}
> +
> +int main()
> +{
> +  if (foo(0) != PREC)
> +    __builtin_abort ();
> +  if (foo(1 << (PREC - 1)) != 0)
> +    __builtin_abort ();
> +  if (foo(35) != PREC - 6)
> +    __builtin_abort ();
> +  return 0;
> +}
> +
> +/* { dg-final { scan-tree-dump-times "__builtin_clz|\\.CLZ" 1 "optimized" } } */

      reply	other threads:[~2023-01-24  9:32 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-01-22 19:50 Dimitar Dimitrov
2023-01-24  9:32 ` Richard Sandiford [this message]

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=mpth6wgnuqk.fsf@arm.com \
    --to=richard.sandiford@arm.com \
    --cc=dimitar@dinux.eu \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=rguenther@suse.de \
    /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).