RISC-V: Mask values before initializing bitmask vector [PR119114].

Message ID D8DJ6SAYODMC.1QKXQTAD7F1JC@gmail.com
State Committed
Commit b58a0af4e2e28b395a3cb4b7283f16f05c0cf3c8
Delegated to: Jeff Law
Headers
Series RISC-V: Mask values before initializing bitmask vector [PR119114]. |

Checks

Context Check Description
rivoscibot/toolchain-ci-rivos-apply-patch success Patch applied
rivoscibot/toolchain-ci-rivos-lint success Lint passed
rivoscibot/toolchain-ci-rivos-build--newlib-rv64gcv-lp64d-multilib success Build passed
rivoscibot/toolchain-ci-rivos-build--linux-rv64gc_zba_zbb_zbc_zbs-lp64d-multilib success Build passed
rivoscibot/toolchain-ci-rivos-build--linux-rv64gcv-lp64d-multilib success Build passed
rivoscibot/toolchain-ci-rivos-test success Testing passed

Commit Message

Robin Dapp March 11, 2025, 3:10 p.m. UTC
  Hi,

in the somewhat convoluted vector code of PR119114 we extracting
a <signed-boolean:1> mask value from a vector mask.  After some
middle-end simplifications we end up with a value of -2.  Its
lowest bit is correctly unset representing "false".
When initializing a bitmak vector from values we compare the full
value/register against zero instead of just the last bit.  This
causes erroneous mask values.

This patch masks the values by & 0x1 before comparing against 0.

Regtested on rv64gcv_zvl512b, let's see what the CI has to say.

Regards
 Robin

	PR target/119114

gcc/ChangeLog:

	* config/riscv/autovec.md: Apply & 0x1 mask when initializing
	bitmask vector.

gcc/testsuite/ChangeLog:

	* gcc.target/riscv/rvv/autovec/pr119114.c: New test.
---
 gcc/config/riscv/autovec.md                   | 14 ++++++-
 .../gcc.target/riscv/rvv/autovec/pr119114.c   | 37 +++++++++++++++++++
 2 files changed, 50 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/pr119114.c
  

Comments

Jeff Law March 15, 2025, 6:51 p.m. UTC | #1
On 3/11/25 9:10 AM, Robin Dapp wrote:
> Hi,
> 
> in the somewhat convoluted vector code of PR119114 we extracting
> a <signed-boolean:1> mask value from a vector mask.  After some
> middle-end simplifications we end up with a value of -2.  Its
> lowest bit is correctly unset representing "false".
> When initializing a bitmak vector from values we compare the full
> value/register against zero instead of just the last bit.  This
> causes erroneous mask values.
> 
> This patch masks the values by & 0x1 before comparing against 0.
> 
> Regtested on rv64gcv_zvl512b, let's see what the CI has to say.
> 
> Regards
> Robin
> 
>      PR target/119114
> 
> gcc/ChangeLog:
> 
>      * config/riscv/autovec.md: Apply & 0x1 mask when initializing
>      bitmask vector.
> 
> gcc/testsuite/ChangeLog:
> 
>      * gcc.target/riscv/rvv/autovec/pr119114.c: New test.
OK
jeff
  

Patch

diff --git a/gcc/config/riscv/autovec.md b/gcc/config/riscv/autovec.md
index 92e6942b523..c7f12f9e36f 100644
--- a/gcc/config/riscv/autovec.md
+++ b/gcc/config/riscv/autovec.md
@@ -405,16 +405,28 @@  (define_expand "vec_init<mode><vel>"
 
 ;; Provide a vec_init for mask registers by initializing
 ;; a QImode vector and comparing it against 0.
+;; As we need to ignore all but the lowest bit apply an AND mask
+;; before doing the comparison.
 (define_expand "vec_init<mode>qi"
   [(match_operand:VB 0 "register_operand")
    (match_operand 1 "")]
   "TARGET_VECTOR"
   {
+    /* Expand into a QImode vector.  */
     machine_mode qimode = riscv_vector::get_vector_mode
 	(QImode, GET_MODE_NUNITS (<MODE>mode)).require ();
     rtx tmp = gen_reg_rtx (qimode);
     riscv_vector::expand_vec_init (tmp, operands[1]);
-    riscv_vector::expand_vec_cmp (operands[0], NE, tmp, CONST0_RTX (qimode));
+
+    /* & 0x1.  */
+    insn_code icode = code_for_pred (AND, qimode);
+    rtx tmp2 = gen_reg_rtx (qimode);
+    rtx ones = gen_const_vec_duplicate (qimode, GEN_INT (1));
+    rtx ops[] = {tmp2, tmp, ones};
+    riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, ops);
+
+    /* Compare against zero.  */
+    riscv_vector::expand_vec_cmp (operands[0], NE, tmp2, CONST0_RTX (qimode));
     DONE;
   }
 )
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr119114.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr119114.c
new file mode 100644
index 00000000000..01025d62f1f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr119114.c
@@ -0,0 +1,37 @@ 
+/* { dg-do run } */
+/* { dg-require-effective-target riscv_v_ok } */
+/* { dg-require-effective-target rv64 } */
+/* { dg-add-options riscv_v } */
+/* { dg-options "-O3 -march=rv64gcv -mabi=lp64d -std=gnu99 -fwhole-program -mrvv-vector-bits=zvl" } */
+
+_Bool a;
+short b[18];
+long long al;
+_Bool e;
+char f = 010;
+short t[18];
+unsigned short w[8][18][18][18];
+
+void
+c (_Bool e, char f, short t[], unsigned short w[][18][18][18])
+{
+  for (int ae = 1; ae < f + 5; ae += 2)
+    {
+      a -= (_Bool) (t[ae - 1] & t[ae + 3]);
+      for (short af = 0; af < 18; af += 2)
+	for (_Bool ah = 0; ah < (w[e][1][af][0] > 0); ah = 5)
+	  b[af] |= 9;
+    }
+}
+
+int
+main ()
+{
+  for (int ad = 0; ad < 18; ad++)
+    t[ad] = 3;
+
+  c (e, f, t, w);
+  al = a;
+  if (al != 0)
+    __builtin_abort ();
+}