"Robin Dapp" <[email protected]> writes:
>> Yeah, but that would require some way of detecting what
>> store_bit_field
>> is going to do. For the V2DF in the testcase, there is at least a
>> possibility that store_bit_field could use vec_set.
>>
>> Also, I still see the existing REGMODE_NATURAL_SIZE spills in
>> store/extract_bit_field as a half-way measure: better than ICEing,
>> but not what we want long-term. I don't think we should add spills
>> elsewhere in anticipation of the existing spills, at least not if
>> there is a simple alternative. It would just create more work
>> that needs to be undone later.
>
> OK, the attached is currently in the tester, waiting for aarch64:
>
> [PATCH] expmed: Use store_bit_field for unsplittable target. [PR127323]
>
> In extract_integral_bit_field we can get an unsplittable target like
> (reg:V2DF) and we try to store word-sized parts into it. After the
> regmode-natural-size changes, this will ICE. This patch goes through
> store_bit_field if we cannot use a subreg. For riscv, this will
> currently cause one spill per iteration but that can be mitigated later.
>
> gcc/ChangeLog:
>
> PR middle-end/127323
>
> * expmed.cc (extract_integral_bit_field): Use store_bit_field if
> operand_subword fails.
>
> gcc/testsuite/ChangeLog:
>
> * g++.target/riscv/rvv/autovec/pr127323.C: New test.
OK, thanks.
Richard
> ---
> gcc/expmed.cc | 6 ++-
> .../g++.target/riscv/rvv/autovec/pr127323.C | 39 +++++++++++++++++++
> 2 files changed, 43 insertions(+), 2 deletions(-)
> create mode 100644 gcc/testsuite/g++.target/riscv/rvv/autovec/pr127323.C
>
> diff --git a/gcc/expmed.cc b/gcc/expmed.cc
> index ca724e22e11..f28184ba635 100644
> --- a/gcc/expmed.cc
> +++ b/gcc/expmed.cc
> @@ -2126,14 +2126,16 @@ extract_integral_bit_field (rtx op0,
> opt_scalar_int_mode op0_mode,
> (unsignedp ? 1 : -1), target_part,
> mode, word_mode, reverse, fallback_p, NULL);
>
> - gcc_assert (target_part);
> if (!result_part)
> {
> delete_insns_since (last);
> return NULL;
> }
>
> - if (result_part != target_part)
> + if (!target_part)
> + store_bit_field (target, BITS_PER_WORD, i * BITS_PER_WORD,
> + 0, 0, word_mode, result_part, false, i == 0);
> + else if (result_part != target_part)
> emit_move_insn (target_part, result_part);
> }
>
> diff --git a/gcc/testsuite/g++.target/riscv/rvv/autovec/pr127323.C
> b/gcc/testsuite/g++.target/riscv/rvv/autovec/pr127323.C
> new file mode 100644
> index 00000000000..b26c0092991
> --- /dev/null
> +++ b/gcc/testsuite/g++.target/riscv/rvv/autovec/pr127323.C
> @@ -0,0 +1,39 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -mrvv-max-lmul=conv-dynamic -march=rv64gcv -mabi=lp64d
> -mtune=generic-ooo" } */
> +
> +typedef double VECTOR[3];
> +enum { X, Y, Z };
> +struct Bicubic_Patch_Struct {
> + VECTOR Control_Points[4][4];
> + VECTOR Bounding_Sphere_Center;
> + double Bounding_Sphere_Radius;
> +};
> +void Assign_Vector(VECTOR d, VECTOR s) {
> + d[X] = s[X];
> + d[Y] = s[Y];
> + d[Z] = s[Z];
> +}
> +typedef struct Bicubic_Patch_Struct BICUBIC_PATCH;
> +namespace std {
> +void find_average(int vector_count, VECTOR *vectors, VECTOR, double *radius)
> {
> + int i;
> + double r0, r1, yc, zc, y0;
> + for (i = 0; i < vector_count; i++) {
> + yc += vectors[i][Y];
> + zc += vectors[i][Z];
> + }
> + y0 = yc - zc;
> + r1 = y0;
> + if (r1)
> + *radius = r0;
> +}
> +void Precompute_Patch_Values(BICUBIC_PATCH *Shape) {
> + int i, j;
> + VECTOR Control_Points[6];
> + for (i = 0; i < 4; i++)
> + for (j = 0; j < 4; j++)
> + Assign_Vector(Control_Points[4 * i + j], Shape->Control_Points[i][j]);
> + find_average(6, Control_Points, Shape->Bounding_Sphere_Center,
> + &Shape->Bounding_Sphere_Radius);
> +}
> +} // namespace std