On 27/07/2026 10:17, Richard Earnshaw wrote:
On 26/07/2026 15:18, Shivam Gupta wrote:
At -O1, a complemented XOR whose result is masked to bit zero is
currently emitted as:

    eor     w0, w0, w1
    ubfx    x0, x0, 0, 1
    eor     w0, w0, 1

Recognize (and (not (xor ...)) 1) and split it into a complemented
XOR followed by an AND, allowing the complemented XOR to use EON:

    eon     w0, w0, w1
    and     w0, w0, 1

Tested on aarch64-unknown-linux-gnu with no regressions.

Thanks for the patch, some suggestions/comments below.


gcc/ChangeLog:

    * config/aarch64/aarch64.md (*aarch64_xor_not_and_one): New
    define_insn_and_split.

gcc/testsuite/ChangeLog:

    * gcc.target/aarch64/xor-not-and-one.c: New test.

Signed-off-by: Shivam Gupta <[email protected]>
---
  gcc/config/aarch64/aarch64.md                 | 14 +++++++++++
  .../gcc.target/aarch64/xor-not-and-one.c      | 23 +++++++++++++++++++
  2 files changed, 37 insertions(+)
  create mode 100644 gcc/testsuite/gcc.target/aarch64/xor-not-and-one.c

diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/ aarch64.md
index b2185c63819..1a61d7f85ca 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -5263,6 +5263,20 @@
  ;; Logical operations
  ;; -------------------------------------------------------------------
+(define_insn_and_split "*aarch64_xor_not_and_one<mode>"

Combine can handle 3->2 patterns without the need for intermediate insn patterns, so I think this should just be a define_split (with a suitable scratch clobber operand to hold the intermediate result).

+  [(set (match_operand:GPI 0 "register_operand" "=r")
+    (and:GPI
+      (not:GPI
+        (xor:GPI (match_operand:GPI 1 "register_operand" "r")
+             (match_operand:GPI 2 "register_operand" "r")))
+      (const_int 1)))]
The shape of this pattern is generic (eon + and), so there's no need to restrict this to a literal 1.  In fact, there's no real need for the split pattern to restrict it to a constant, and operand that is valid for AND should be OK here.

R.


Actually, I've just noticed that you said this was at -O1. If I compile with -O2 (which is what we generally recommend for general use), we already generate the eon/and sequence, so I don't think we need anything more in this case; the problem is just that your optimization level is too low.

The issue with having patterns that need later splitting is that it can cause combinatorial explosion problems in the machine description - we have to start adding yet more patterns to recognize multiple combinations.

The compilers heuristics are usually very good at handling this complexity by splitting things as soon as possible. So we try to stick closely to the 1 insn, 1 instruction rule and only add 1->2+ when there is something very critical that can't be handled by other optimizations.

R.

Reply via email to