https://gcc.gnu.org/g:5d13af1262083f3ec51b56c15bc60912400611fe
commit r16-6061-g5d13af1262083f3ec51b56c15bc60912400611fe Author: Tejas Belagod <[email protected]> Date: Tue Nov 11 16:35:23 2025 +0000 AArch64: Flip svbool_t equal conditionals in ternary operators. This patch flips == conditions: p == q ? s1 : s2; to p != q ? s2 : s1; where p and q are svbool_t expression types. This is an optimization to avoid generating an extra bit inverse to check for equality. gcc/ * config/aarch64/aarch64.cc (aarch64_instruction_selection): Flip svbool_t == to != to avoid extra bit-inverse. gcc/testsuite/ * g++.target/aarch64/sve/acle/general-c++/svbool_ternary.C: New test. Co-authored-by: Tamar Christina <[email protected]> Diff: --- gcc/config/aarch64/aarch64.cc | 65 ++++++++++++++++++++++ .../aarch64/sve/acle/general-c++/svbool_ternary.C | 13 +++++ 2 files changed, 78 insertions(+) diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc index f4bef646a92a..58914e3e6849 100644 --- a/gcc/config/aarch64/aarch64.cc +++ b/gcc/config/aarch64/aarch64.cc @@ -2207,6 +2207,68 @@ aarch64_preferred_else_value (unsigned, tree, unsigned int nops, tree *ops) return nops == 3 ? ops[2] : ops[0]; } +/* Implement TARGET_INSTRUCTION_SELECTION. The target hook is used to + change generic sequences to a form AArch64 has an easier time expanding + instructions for. It's not supposed to be used for generic rewriting that + all targets would benefit from. */ + +static bool +aarch64_instruction_selection (function * /* fun */, gimple_stmt_iterator *gsi) +{ + auto stmt = gsi_stmt (*gsi); + gassign *assign = dyn_cast<gassign *> (stmt); + + if (!assign) + return false; + + /* Convert + p == q ? s1 : s2; + to + p != q ? s2 : s1; + where p and q are svbool_t expr. Due to the absence of predicate + comparison instructions, we use bitwise xor for checking inequality. + Transforming == to != avoids an extra bitwise inversion to the xor. */ + if (gimple_assign_rhs_code (assign) != VEC_COND_EXPR) + return false; + + tree lhs = gimple_assign_lhs (assign); + tree rhs1 = gimple_assign_rhs1 (assign); + tree rhs2 = gimple_assign_rhs2 (assign); + tree rhs3 = gimple_assign_rhs3 (assign); + + if (TREE_CODE (rhs1) != SSA_NAME || !VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (rhs1))) + return false; + + gassign *da = dyn_cast<gassign *> (SSA_NAME_DEF_STMT (rhs1)); + + if (!da) + return false; + + if (gimple_assign_rhs_code (da) != EQ_EXPR) + return false; + + tree eqa = gimple_assign_rhs1 (da); + tree eqb = gimple_assign_rhs2 (da); + + if (!VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (eqa)) + || !VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (eqb))) + return false; + + tree ne_expr_var = create_tmp_var (TREE_TYPE (rhs1)); + gimple *ne_stmt = gimple_build_assign (ne_expr_var, NE_EXPR, eqa, eqb); + gsi_safe_insert_before (gsi, ne_stmt); + + gimple *g = gimple_build_call_internal (IFN_VCOND_MASK, 3, + ne_expr_var, rhs3, rhs2); + if (!g) + return false; + + gimple_set_lhs (g, lhs); + gsi_replace (gsi, g, false); + + return true; +} + /* Implement TARGET_HARD_REGNO_NREGS. */ static unsigned int @@ -33141,6 +33203,9 @@ aarch64_libgcc_floating_mode_supported_p #define TARGET_PREFERRED_ELSE_VALUE \ aarch64_preferred_else_value +#undef TARGET_INSTRUCTION_SELECTION +#define TARGET_INSTRUCTION_SELECTION aarch64_instruction_selection + #undef TARGET_INIT_LIBFUNCS #define TARGET_INIT_LIBFUNCS aarch64_init_libfuncs diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/svbool_ternary.C b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/svbool_ternary.C new file mode 100644 index 000000000000..38de1880d1c4 --- /dev/null +++ b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/svbool_ternary.C @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +#include <arm_sve.h> + +svbool_t g (svbool_t p, svbool_t q, svbool_t a, svbool_t b, + svbool_t c, svbool_t d) +{ + return (p == q) ? p : (a == b ? c : d); +} + +/* { dg-final { scan-tree-dump-not {VEC_COND_EXPR} "optimized" } } */ +/* { dg-final { scan-assembler-times {\teor\tp[0-9]+\.b} 2 } } */
