]> gcc.gnu.org Git - gcc.git/commit
arm: Fix vcond_mask expander for MVE (PR target/100757)
authorChristophe Lyon <christophe.lyon@arm.com>
Wed, 20 Oct 2021 15:30:16 +0000 (15:30 +0000)
committerChristophe Lyon <christophe.lyon@foss.st.com>
Tue, 22 Feb 2022 15:55:07 +0000 (15:55 +0000)
commitdf0e57c2c032cea0f77f2e68231c035f282b26d6
tree21d8c9a9003ba83035baaea4f058760da0e64036
parent91224cf625dc90304bb515a0cc602beed48fe3da
arm: Fix vcond_mask expander for MVE (PR target/100757)

The problem in this PR is that we call VPSEL with a mask of vector
type instead of HImode. This happens because operand 3 in vcond_mask
is the pre-computed vector comparison and has vector type.

This patch fixes it by implementing TARGET_VECTORIZE_GET_MASK_MODE,
returning the appropriate VxBI mode when targeting MVE.  In turn, this
implies implementing vec_cmp<mode><MVE_vpred>,
vec_cmpu<mode><MVE_vpred> and vcond_mask_<mode><MVE_vpred>, and we can
move vec_cmp<mode><v_cmp_result>, vec_cmpu<mode><mode> and
vcond_mask_<mode><v_cmp_result> back to neon.md since they are not
used by MVE anymore.  The new *<MVE_vpred> patterns listed above are
implemented in mve.md since they are only valid for MVE. However this
may make maintenance/comparison more painful than having all of them
in vec-common.md.

In the process, we can get rid of the recently added vcond_mve
parameter of arm_expand_vector_compare.

Compared to neon.md's vcond_mask_<mode><v_cmp_result> before my "arm:
Auto-vectorization for MVE: vcmp" patch (r12-834), it keeps the VDQWH
iterator added in r12-835 (to have V4HF/V8HF support), as well as the
(!<Is_float_mode> || flag_unsafe_math_optimizations) condition which
was not present before r12-834 although SF modes were enabled by VDQW
(I think this was a bug).

Using TARGET_VECTORIZE_GET_MASK_MODE has the advantage that we no
longer need to generate vpsel with vectors of 0 and 1: the masks are
now merged via scalar 'ands' instructions operating on 16-bit masks
after converting the boolean vectors.

In addition, this patch fixes a problem in arm_expand_vcond() where
the result would be a vector of 0 or 1 instead of operand 1 or 2.

Since we want to skip gcc.dg/signbit-2.c for MVE, we also add a new
arm_mve effective target.

Reducing the number of iterations in pr100757-3.c from 32 to 8, we
generate the code below:

float a[32];
float fn1(int d) {
  float c = 4.0f;
  for (int b = 0; b < 8; b++)
    if (a[b] != 2.0f)
      c = 5.0f;
  return c;
}

fn1:
ldr     r3, .L3+48
vldr.64 d4, .L3              // q2=(2.0,2.0,2.0,2.0)
vldr.64 d5, .L3+8
vldrw.32        q0, [r3]     // q0=a(0..3)
adds    r3, r3, #16
vcmp.f32        eq, q0, q2   // cmp a(0..3) == (2.0,2.0,2.0,2.0)
vldrw.32        q1, [r3]     // q1=a(4..7)
vmrs     r3, P0
vcmp.f32        eq, q1, q2   // cmp a(4..7) == (2.0,2.0,2.0,2.0)
vmrs    r2, P0  @ movhi
ands    r3, r3, r2           // r3=select(a(0..3]) & select(a(4..7))
vldr.64 d4, .L3+16           // q2=(5.0,5.0,5.0,5.0)
vldr.64 d5, .L3+24
vmsr     P0, r3
vldr.64 d6, .L3+32           // q3=(4.0,4.0,4.0,4.0)
vldr.64 d7, .L3+40
vpsel q3, q3, q2             // q3=vcond_mask(4.0,5.0)
vmov.32 r2, q3[1]            // keep the scalar max
vmov.32 r0, q3[3]
vmov.32 r3, q3[2]
vmov.f32        s11, s12
vmov    s15, r2
vmov    s14, r3
vmaxnm.f32      s15, s11, s15
vmaxnm.f32      s15, s15, s14
vmov    s14, r0
vmaxnm.f32      s15, s15, s14
vmov    r0, s15
bx      lr
.L4:
.align  3
.L3:
.word   1073741824 // 2.0f
.word   1073741824
.word   1073741824
.word   1073741824
.word   1084227584 // 5.0f
.word   1084227584
.word   1084227584
.word   1084227584
.word   1082130432 // 4.0f
.word   1082130432
.word   1082130432
.word   1082130432

This patch adds tests that trigger an ICE without this fix.

The pr100757*.c testcases are derived from
gcc.c-torture/compile/20160205-1.c, forcing the use of MVE, and using
various types and return values different from 0 and 1 to avoid
commonalization with boolean masks.  In addition, since we should not
need these masks, the tests make sure they are not present.

Most of the work of this patch series was carried out while I was
working at STMicroelectronics as a Linaro assignee.

2022-02-22  Christophe Lyon  <christophe.lyon@arm.com>

PR target/100757
gcc/
* config/arm/arm-protos.h (arm_get_mask_mode): New prototype.
(arm_expand_vector_compare): Update prototype.
* config/arm/arm.cc (TARGET_VECTORIZE_GET_MASK_MODE): New.
(arm_vector_mode_supported_p): Add support for VxBI modes.
(arm_expand_vector_compare): Remove useless generation of vpsel.
(arm_expand_vcond): Fix select operands.
(arm_get_mask_mode): New.
* config/arm/mve.md (vec_cmp<mode><MVE_vpred>): New.
(vec_cmpu<mode><MVE_vpred>): New.
(vcond_mask_<mode><MVE_vpred>): New.
* config/arm/vec-common.md (vec_cmp<mode><v_cmp_result>)
(vec_cmpu<mode><mode, vcond_mask_<mode><v_cmp_result>): Move to ...
* config/arm/neon.md (vec_cmp<mode><v_cmp_result>)
(vec_cmpu<mode><mode, vcond_mask_<mode><v_cmp_result>): ... here
and disable for MVE.
* doc/sourcebuild.texi (arm_mve): Document new effective-target.

gcc/testsuite/
PR target/100757
* gcc.target/arm/simd/pr100757-2.c: New.
* gcc.target/arm/simd/pr100757-3.c: New.
* gcc.target/arm/simd/pr100757-4.c: New.
* gcc.target/arm/simd/pr100757.c: New.
* gcc.dg/signbit-2.c: Skip when targeting ARM/MVE.
* lib/target-supports.exp (check_effective_target_arm_mve): New.
12 files changed:
gcc/config/arm/arm-protos.h
gcc/config/arm/arm.cc
gcc/config/arm/mve.md
gcc/config/arm/neon.md
gcc/config/arm/vec-common.md
gcc/doc/sourcebuild.texi
gcc/testsuite/gcc.dg/signbit-2.c
gcc/testsuite/gcc.target/arm/simd/pr100757-2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arm/simd/pr100757-3.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arm/simd/pr100757-4.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arm/simd/pr100757.c [new file with mode: 0644]
gcc/testsuite/lib/target-supports.exp
This page took 0.071332 seconds and 6 git commands to generate.