"Roger Sayle" <[email protected]> writes:
> diff --git a/gcc/simplify-rtx.cc b/gcc/simplify-rtx.cc
> index 92a2a6e954a..32267ac061b 100644
> --- a/gcc/simplify-rtx.cc
> +++ b/gcc/simplify-rtx.cc
> @@ -5586,17 +5586,30 @@ simplify_ashift:
> return simplify_gen_binary (VEC_SELECT, mode, XEXP (trueop0, 0),
> gen_rtx_PARALLEL (VOIDmode, vec));
> }
> - /* (vec_concat:
> - (subreg_lowpart:N OP)
> - (vec_select:N OP P)) --> OP when P selects the high half
> - of the OP. */
> - if (GET_CODE (trueop0) == SUBREG
> - && subreg_lowpart_p (trueop0)
> - && GET_CODE (trueop1) == VEC_SELECT
> - && SUBREG_REG (trueop0) == XEXP (trueop1, 0)
> - && !side_effects_p (XEXP (trueop1, 0))
> - && vec_series_highpart_p (op1_mode, mode, XEXP (trueop1, 1)))
> - return XEXP (trueop1, 0);
> + /* (vec_concat:N
> + (subreg:N/2 OP 0)
> + (subreg:N/2 OP N/2)) --> OP
> + i.e. where concatenating the first and second halves of the
> + same object OP. */
> + if (known_eq (GET_MODE_SIZE (op0_mode),
> + GET_MODE_SIZE (op1_mode)))
I thought this was required for all VEC_CONCATs. Even if it isn't,
I think the GET_MODE_SIZE tests below are enough to ensure that
every byte of base0 is used exactly once.
So my preference would be to drop this check.
> + {
> + poly_uint64 offset = 0u;
> + rtx base0 = get_ref_base_and_offset (trueop0, &offset);
> + if (base0
> + && known_eq (offset, 0u)
> + && known_eq (GET_MODE_SIZE (GET_MODE (base0)),
> + GET_MODE_SIZE (mode)))
> + {
> + rtx base1 = get_ref_base_and_offset (trueop1, &offset);
> + if (base1
The null tests for base0 and base1 don't seem necessary. IMO it would
be a misfeature for get_ref_base_and_offset to return null. In the
worst case it can just return the parameter and set the offset to 0.
LGTM otherwise, but I think someone else should give the final ok.
Thanks for doing this.
Richard
> + && rtx_equal_p (base0, base1)
> + && known_eq (offset, GET_MODE_SIZE (op0_mode))
> + && !side_effects_p (trueop0)
> + && !side_effects_p (trueop1))
> + return gen_lowpart (mode, base0);
> + }
> + }
> }
> return 0;
>
> diff --git a/gcc/testsuite/gcc.target/i386/pr48609.c
> b/gcc/testsuite/gcc.target/i386/pr48609.c
> new file mode 100644
> index 00000000000..8af9d883761
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/pr48609.c
> @@ -0,0 +1,13 @@
> +/* PR target/48609 */
> +/* { dg-do compile { target { ! ia32 } } } */
> +/* { dg-options "-O2 -msse2" } */
> +typedef _Complex float SCtype;
> +extern SCtype bar;
> +void foo (SCtype x)
> +{
> + bar = x;
> +}
> +
> +/* { dg-final { scan-assembler-not "movdqa" } } */
> +/* { dg-final { scan-assembler-not "shufps" } } */
> +/* { dg-final { scan-assembler-not "unpcklps" } } */