This is a follow-up to Tamar's target hook patch:
https://gcc.gnu.org/pipermail/gcc-patches/2025-November/700417.html
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_preferred_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]>
---
gcc/config/aarch64/aarch64.cc | 62 +++++++++++++++++++
.../sve/acle/general-c++/svbool_ternary.C | 12 ++++
2 files changed, 74 insertions(+)
create mode 100644
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/svbool_ternary.C
diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index 60608a19078..28ba2284209 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -2171,6 +2171,65 @@ aarch64_preferred_else_value (unsigned, tree, unsigned
int nops, tree *ops)
return nops == 3 ? ops[2] : ops[0];
}
+/* Implement TARGET_PREFERRED_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_preferred_instruction_selection (function * /* fun */,
+ gimple_stmt_iterator *gsi)
+{
+ auto stmt = gsi_stmt (*gsi);
+ gassign *assign = dyn_cast<gassign *> (stmt);
+
+ if (!assign)
+ return false;
+
+ tree_code code = gimple_assign_rhs_code (assign);
+
+ if (code != 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;
+
+ auto ds = SSA_NAME_DEF_STMT (rhs1);
+ gassign *da = dyn_cast<gassign *> (ds);
+
+ if (!da)
+ return false;
+
+ code = gimple_assign_rhs_code (da);
+
+ if (code != 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));
+ tree ne_expr = build2 (NE_EXPR, TREE_TYPE (rhs1), eqa, eqb);
+ gimple *ne_stmt = gimple_build_assign (ne_expr_var, ne_expr);
+ gsi_safe_insert_before (gsi, ne_stmt);
+
+ tree new_vce = build3 (VEC_COND_EXPR, TREE_TYPE (lhs),
+ ne_expr_var, rhs3, rhs2);
+ gimple *vce_stmt = gimple_build_assign (lhs, new_vce);
+ gsi_replace (gsi, vce_stmt, false);
+
+ return true;
+}
+
/* Implement TARGET_HARD_REGNO_NREGS. */
static unsigned int
@@ -32872,6 +32931,9 @@ aarch64_libgcc_floating_mode_supported_p
#undef TARGET_PREFERRED_ELSE_VALUE
#define TARGET_PREFERRED_ELSE_VALUE \
aarch64_preferred_else_value
+#undef TARGET_PREFERRED_INSTRUCTION_SELECTION
+#define TARGET_PREFERRED_INSTRUCTION_SELECTION \
+ aarch64_preferred_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 00000000000..91cb3244aaa
--- /dev/null
+++ b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/svbool_ternary.C
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#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-assembler-times {\teor\tp[0-9]+\.b} 2 } } */
--
2.34.1