I gave it another shot now by introducing a separate function as Richard suggested. It's probably not at the location he intended.
The way I read the discussion there hasn't been any consensus on how (or rather where) to properly tackle the problem. Any other ideas still? Regards Robin Found in PR112971 this patch adds folding support for bitwise operations of const duplicate zero/one vectors with stepped vectors. On riscv we have the situation that a folding would perpetually continue without simplifying because e.g. {0, 0, 0, ...} & {7, 6, 5, ...} would not be folded to {0, 0, 0, ...}. gcc/ChangeLog: PR middle-end/112971 * fold-const.cc (simplify_const_binop): New function for binop simplification of two constant vectors when element-wise handling is not necessary. (const_binop): Call new function. gcc/testsuite/ChangeLog: * gcc.target/riscv/rvv/autovec/pr112971.c: New test. --- gcc/fold-const.cc | 31 +++++++++++++++++++ .../gcc.target/riscv/rvv/autovec/pr112971.c | 18 +++++++++++ 2 files changed, 49 insertions(+) create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/pr112971.c diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc index 385e4a69ab3..2ef425aec0f 100644 --- a/gcc/fold-const.cc +++ b/gcc/fold-const.cc @@ -1343,6 +1343,29 @@ distributes_over_addition_p (tree_code op, int opno) } } +/* OP is the INDEXth operand to CODE (counting from zero) and OTHER_OP + is the other operand. Try to use the value of OP to simplify the + operation in one step, without having to process individual elements. */ +static tree +simplify_const_binop (tree_code code, tree op, tree other_op, + int index ATTRIBUTE_UNUSED) +{ + /* AND, IOR as well as XOR with a zerop can be simplified directly. */ + if (TREE_CODE (op) == VECTOR_CST && TREE_CODE (other_op) == VECTOR_CST) + { + if (integer_zerop (other_op)) + { + if (code == BIT_IOR_EXPR || code == BIT_XOR_EXPR) + return op; + else if (code == BIT_AND_EXPR) + return other_op; + } + } + + return NULL_TREE; +} + + /* Combine two constants ARG1 and ARG2 under operation CODE to produce a new constant. We assume ARG1 and ARG2 have the same data type, or at least are the same kind of constant and the same machine mode. Return zero if @@ -1646,6 +1669,14 @@ const_binop (enum tree_code code, tree arg1, tree arg2) return build_complex (type, real, imag); } + tree simplified; + if ((simplified = simplify_const_binop (code, arg1, arg2, 0))) + return simplified; + + if (commutative_tree_code (code) + && (simplified = simplify_const_binop (code, arg2, arg1, 1))) + return simplified; + if (TREE_CODE (arg1) == VECTOR_CST && TREE_CODE (arg2) == VECTOR_CST && known_eq (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg1)), diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr112971.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr112971.c new file mode 100644 index 00000000000..816ebd3c493 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr112971.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64gcv_zvl256b -mabi=lp64d -O3 -fno-vect-cost-model" } */ + +int a; +short b[9]; +char c, d; +void e() { + d = 0; + for (;; d++) { + if (b[d]) + break; + a = 8; + for (; a >= 0; a--) { + char *f = &c; + *f &= d == (a & d); + } + } +} -- 2.43.0