From b58a0af4e2e28b395a3cb4b7283f16f05c0cf3c8 Mon Sep 17 00:00:00 2001 From: Robin Dapp Date: Tue, 11 Mar 2025 14:30:48 +0100 Subject: [PATCH] RISC-V: Mask values before initializing bitmask vector [PR119114]. In the somewhat convoluted vector code of PR119114 we extract a 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. 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 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 @@ ;; 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_initqi" [(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)).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 (); +}