On Wed, 28 Dec 2022 at 19:18, Raphael Moreira Zinsly <
rzin...@ventanamicro.com> wrote:

> The Zbb min/max pattern was not matching 32-bit sources when
> compiling for 64-bit.
> This patch separates the pattern into SImode and DImode, and
> use a define_expand to handle SImode on 64-bit.
> zbb-min-max-02.c generates different code as a result of the new
> expander.  The resulting code is as efficient as the old code.
> Furthermore, the special sh1add pattern that appeared in
> zbb-min-max-02.c is tested by the zba-shNadd-* tests.
>
>         gcc/ChangeLog:
>
>                 * config/riscv/bitmanip.md
>                 (<bitmanip_optab><mode>3): Divide pattern into
>                 <bitmanip_optab>si3_insn and <bitmanip_optab>di3.
>                 (<bitmanip_optab>si3): Handle SImode sources on
>                 TARGET_64BIT.
>
>         gcc/testsuite:
>
>                 * gcc.target/riscv/zbb-abs.c: New test.
>                 * gcc.target/riscv/zbb-min-max-02.c: Addapt the
>                 expected output.
> ---
>  gcc/config/riscv/bitmanip.md                  | 38 ++++++++++++++++---
>  gcc/testsuite/gcc.target/riscv/zbb-abs.c      | 18 +++++++++
>  .../gcc.target/riscv/zbb-min-max-02.c         |  2 +-
>  3 files changed, 52 insertions(+), 6 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.target/riscv/zbb-abs.c
>
> diff --git a/gcc/config/riscv/bitmanip.md b/gcc/config/riscv/bitmanip.md
> index d17133d58c1..abf08a29e89 100644
> --- a/gcc/config/riscv/bitmanip.md
> +++ b/gcc/config/riscv/bitmanip.md
> @@ -360,14 +360,42 @@
>    DONE;
>  })
>
> -(define_insn "<bitmanip_optab><mode>3"
> -  [(set (match_operand:X 0 "register_operand" "=r")
> -        (bitmanip_minmax:X (match_operand:X 1 "register_operand" "r")
> -                          (match_operand:X 2 "register_operand" "r")))]
> -  "TARGET_ZBB"
> +(define_insn "<bitmanip_optab>si3_insn"
> +  [(set (match_operand:SI 0 "register_operand" "=r")
> +        (bitmanip_minmax:SI (match_operand:SI 1 "register_operand" "r")
> +                            (match_operand:SI 2 "register_operand" "r")))]
> +  "!TARGET_64BIT && TARGET_ZBB"
>    "<bitmanip_insn>\t%0,%1,%2"
>    [(set_attr "type" "bitmanip")])
>
> +(define_insn "<bitmanip_optab>di3"
> +  [(set (match_operand:DI 0 "register_operand" "=r")
> +        (bitmanip_minmax:DI (match_operand:DI 1 "register_operand" "r")
> +                            (match_operand:DI 2 "register_operand" "r")))]
> +  "TARGET_64BIT && TARGET_ZBB"
> +  "<bitmanip_insn>\t%0,%1,%2"
> +  [(set_attr "type" "bitmanip")])
> +
> +(define_expand "<bitmanip_optab>si3"
> +  [(set (match_operand:SI 0 "register_operand" "=r")
> +        (bitmanip_minmax:SI (match_operand:SI 1 "register_operand" "r")
> +                            (match_operand:SI 2 "register_operand" "r")))]
> +  "TARGET_ZBB"
> +  "
> +{
> +  if (TARGET_64BIT)
> +    {
> +      rtx op1_x = gen_reg_rtx (DImode);
> +      emit_move_insn (op1_x, gen_rtx_SIGN_EXTEND (DImode, operands[1]));
> +      rtx op2_x = gen_reg_rtx (DImode);
> +      emit_move_insn (op2_x, gen_rtx_SIGN_EXTEND (DImode, operands[2]));
> +      rtx dst_x = gen_reg_rtx (DImode);
> +      emit_insn (gen_<bitmanip_optab>di3 (dst_x, op1_x, op2_x));
> +      emit_move_insn (operands[0], gen_lowpart (SImode, dst_x));
> +      DONE;
> +    }
> +}")
>

We have two issues around min/max here:
1. That it doesn't apply to the SImode abs case (which is due to
expand_abs_nojump() blindly testing for the current mode in smax_optab).
2. That we have to reduce the number of extensions to the least amount.

The above addresses expand_abs_nojump(), but makes the general solution
harder as the middle-end needs to know there is no native SImode min/max
available.
We still plan (proof-of-concept works, but a final patch will likely not be
ready before very late in January) to submit a patch to improve the
expansion of MIN_EXPR/MAX_EXPR that utilizes the type-precision and
value-ranges to not even create the sign-extensions in the first place.  If
we do the above, the middle-end will blindly emit this sequence with the 2
sign-extensions — which may or may not be eliminated later by combining
with a w-form.
I'll also add an enhancement to expand_abs_nojump() to our list of changes
for the min/max enhancement during the lowering.

Note that, if we decide to go ahead with using this as a temporary solution
until our change is ready, you'll also need to add a cost for the SImode
max.

Philipp.


> +
>  ;; Optimize the common case of a SImode min/max against a constant
>  ;; that is safe both for sign- and zero-extension.
>  (define_insn_and_split "*minmax"
> diff --git a/gcc/testsuite/gcc.target/riscv/zbb-abs.c
> b/gcc/testsuite/gcc.target/riscv/zbb-abs.c
> new file mode 100644
> index 00000000000..6ef7efdbd49
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/zbb-abs.c
> @@ -0,0 +1,18 @@
> +/* { dg-do compile } */
> +/* { dg-options "-march=rv64gc_zbb" } */
> +/* { dg-skip-if "" { *-*-* } { "-O0" } } */
> +
> +#define ABS(x) (((x) >= 0) ? (x) : -(x))
> +
> +int
> +foo (int x)
> +{
> +  return ABS(x);
> +}
> +
> +/* { dg-final { scan-assembler-times "neg" 1 } } */
> +/* { dg-final { scan-assembler-times "max" 1 } } */
> +/* { dg-final { scan-assembler-not "sraiw" } } */
> +/* { dg-final { scan-assembler-not "xor" } } */
> +/* { dg-final { scan-assembler-not "subw" } } */
> +
> diff --git a/gcc/testsuite/gcc.target/riscv/zbb-min-max-02.c
> b/gcc/testsuite/gcc.target/riscv/zbb-min-max-02.c
> index b462859f10f..b9db655d55d 100644
> --- a/gcc/testsuite/gcc.target/riscv/zbb-min-max-02.c
> +++ b/gcc/testsuite/gcc.target/riscv/zbb-min-max-02.c
> @@ -9,6 +9,6 @@ int f(unsigned int* a)
>  }
>
>  /* { dg-final { scan-assembler-times "minu" 1 } } */
> -/* { dg-final { scan-assembler-times "sext.w" 1 } } */
> +/* { dg-final { scan-assembler-times "sext.w|addw" 1 } } */
>  /* { dg-final { scan-assembler-not "zext.w" } } */
>
> --
> 2.38.1
>
>

Reply via email to