This patch tweaks aarch64.md to ensure it is AOP-safe, i.e. can recognize
bfi, bfxil and rev16 instructions when expressed in RTL using either PLUS,
IOR or XOR.  My already approved patch for PR tree-optimization/108477
will cause 8 testsuite regressions on aarch64, and this patch addresses
the machine description issues and resolves/prevents 2 of those 8 FAILs.

Firstly, many thanks to Kyrill Tkachov for reviewing/approving the
previous aarch64 fix for AOP issues (around movk).
https://gcc.gnu.org/pipermail/gcc-patches/2026-September/729755.html

For PR 108477, the middle-end will even more aggressively select between
PLUS and IOR, by making use of get_nonzero_bits during expand.
https://gcc.gnu.org/pipermail/gcc-patches/2026-September/733041.html

Alas on aarch64 this causes the following code quality (not correctness)
regressions in the testsuite:

FAIL: gcc.target/aarch64/combine_bfi_1.c scan-assembler-times \\tbfi\\t 5
FAIL: gcc.target/aarch64/combine_bfi_2.c scan-assembler-times \\tbfi\\t 2
FAIL: gcc.target/aarch64/combine_bfxil.c scan-assembler-times bfxil\\t 3
FAIL: gcc.target/aarch64/combine_bfxil.c scan-assembler-times bfi\\t 15
FAIL: gcc.target/aarch64/fcvt_int_float_double3.c scan-assembler
\\tscvtf\\td0,
w[0-9]*
FAIL: gcc.target/aarch64/movk_2.c check-function-bodies f2
FAIL: gcc.target/aarch64/pr100028.c scan-assembler-times \\tbfxil\\t 2
FAIL: gcc.target/aarch64/rev16_2.c scan-assembler-times rev16\\tx[0-9]+ 2

I'd initially hoped this patch would be sufficient to avoid these
regressions, but alas providing AOP-safe patterns only allows combine
to "recognize" these instructions, but (for the first six above)
aarch64_rtx_costs also needs to provide accurate estimates for them to
be used.  It turns out the cost infrastructure is (partially) shared
with the arm backend (via aarch-common), and my patch to the upstream
config/arm/aarch-common.cc is still awaiting review.
https://gcc.gnu.org/pipermail/gcc-patches/2026-September/732926.html

Hopefully, this (partially finished) fix is acceptable, to silence
some of the upcoming regressions, and explain what's happening and
why.


This patch has been tested on aarch64-apple-darwin24.3.0 (using
iains' fork) with make bootstrap and make -k check with no new
failures.  Ok for mainline?

Note: the i386 maintainers (Uros) preferred to name the new code
attribute "aop_name_pfx" instead of "aop_pref_ior" used below.
I'm happy to make a similar change if aarch64 folks also prefer
that spelling.


2026-10-04  Roger Sayle  <[email protected]>

gcc/ChangeLog
        * config/gcc/aarch64.cc (aarch64_extr_rtx_p): Allow extr
        pattern to be represented as either IOR, XOR or PLUS.
        * config/aarch64/aarch64.md (*aarch64_bfxil<mode>_extr):
        Use any_or_plus iterator.
        (*aarch64_bfxilsi_extrdi): Likewise.
        (*aarch64_bfxil<mode>): Likewise.
        (*aarch64_bfxilsi_uxtw): Likewise.
        (aarch64_rev16<mode>2_alt1): Use any_or_plus iterator and
        new aop_pref_ior attribute so that the gen function uses IOR.
        (*aarch64_rev16<mode>2_alt2): Use any_or_plus iterator.
        (*aarch64_rev16si2_alt3): Add "*" prefix to skip gen function.
        * config/aarch64/iterators.md (aop_pref_ior): New code attribute to
        produce "*" for XOR/PLUS.


Thanks in advance (and sorry for any inconvenience).
Roger
--

diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index bbbbe879f5b..7c6fb7f3c50 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -15600,7 +15600,9 @@ aarch64_extr_rtx_p (rtx x, rtx *res_op0, rtx *res_op1)
   *res_op0 = NULL_RTX;
   *res_op1 = NULL_RTX;
 
-  if (GET_CODE (x) != IOR)
+  if (GET_CODE (x) != IOR
+      && GET_CODE (x) != XOR
+      && GET_CODE (x) != PLUS)
     return false;
 
   op0 = XEXP (x, 0);
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index ada51c806b3..c55141d39c8 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -6921,12 +6921,13 @@
 
 (define_insn "*aarch64_bfxil<mode>_extr"
   [(set (match_operand:GPI 0 "register_operand" "=r")
-        (ior:GPI (and:GPI (match_operand:GPI 1 "register_operand" "0")
-                         (match_operand:GPI 2 "const_int_operand" "n"))
-                (zero_extract:GPI
-                  (match_operand:GPI 3 "register_operand" "r")
-                  (match_operand:GPI 4 "aarch64_simd_shift_imm_<mode>" "n")
-                  (match_operand:GPI 5 "aarch64_simd_shift_imm_<mode>" "n"))))]
+        (any_or_plus:GPI
+         (and:GPI (match_operand:GPI 1 "register_operand" "0")
+                  (match_operand:GPI 2 "const_int_operand" "n"))
+         (zero_extract:GPI
+           (match_operand:GPI 3 "register_operand" "r")
+           (match_operand:GPI 4 "aarch64_simd_shift_imm_<mode>" "n")
+           (match_operand:GPI 5 "aarch64_simd_shift_imm_<mode>" "n"))))]
   "UINTVAL (operands[2]) == HOST_WIDE_INT_M1U << INTVAL (operands[4])
    && INTVAL (operands[4])
    && (UINTVAL (operands[4]) + UINTVAL (operands[5])
@@ -6937,13 +6938,14 @@
 
 (define_insn "*aarch64_bfxilsi_extrdi"
   [(set (match_operand:SI 0 "register_operand" "=r")
-        (ior:SI (and:SI (match_operand:SI 1 "register_operand" "0")
-                       (match_operand:SI 2 "const_int_operand" "n"))
-               (match_operator:SI 6 "subreg_lowpart_operator"
-                 [(zero_extract:DI
-                    (match_operand:DI 3 "register_operand" "r")
-                    (match_operand:SI 4 "aarch64_simd_shift_imm_si" "n")
-                    (match_operand:SI 5 "aarch64_simd_shift_imm_si" "n"))])))]
+        (any_or_plus:SI
+         (and:SI (match_operand:SI 1 "register_operand" "0")
+                 (match_operand:SI 2 "const_int_operand" "n"))
+         (match_operator:SI 6 "subreg_lowpart_operator"
+           [(zero_extract:DI
+              (match_operand:DI 3 "register_operand" "r")
+              (match_operand:SI 4 "aarch64_simd_shift_imm_si" "n")
+              (match_operand:SI 5 "aarch64_simd_shift_imm_si" "n"))])))]
   "UINTVAL (operands[2]) == HOST_WIDE_INT_M1U << INTVAL (operands[4])
    && INTVAL (operands[4])
    && UINTVAL (operands[4]) + UINTVAL (operands[5]) <= 32"
@@ -7057,10 +7059,11 @@
 
 (define_insn "*aarch64_bfxil<mode>"
   [(set (match_operand:GPI 0 "register_operand" "=r,r")
-    (ior:GPI (and:GPI (match_operand:GPI 1 "register_operand" "r,0")
-                   (match_operand:GPI 3 "const_int_operand" "n, Ulc"))
-           (and:GPI (match_operand:GPI 2 "register_operand" "0,r")
-                   (match_operand:GPI 4 "const_int_operand" "Ulc, n"))))]
+    (any_or_plus:GPI
+      (and:GPI (match_operand:GPI 1 "register_operand" "r,0")
+              (match_operand:GPI 3 "const_int_operand" "n, Ulc"))
+      (and:GPI (match_operand:GPI 2 "register_operand" "0,r")
+              (match_operand:GPI 4 "const_int_operand" "Ulc, n"))))]
   "(INTVAL (operands[3]) == ~INTVAL (operands[4]))
   && (aarch64_high_bits_all_ones_p (INTVAL (operands[3]))
     || aarch64_high_bits_all_ones_p (INTVAL (operands[4])))"
@@ -7083,8 +7086,8 @@
 ; Zero-extended version of above (aarch64_bfxil)
 (define_insn "*aarch64_bfxilsi_uxtw"
   [(set (match_operand:DI 0 "register_operand" "=r,r")
-       (zero_extend:DI (ior:SI (and:SI (match_operand:SI 1 "register_operand"
-                                       "r,0")
+       (zero_extend:DI (any_or_plus:SI
+           (and:SI (match_operand:SI 1 "register_operand" "r,0")
                    (match_operand:SI 3 "const_int_operand" "n, Ulc"))
            (and:SI (match_operand:SI 2 "register_operand" "0,r")
                    (match_operand:SI 4 "const_int_operand" "Ulc, n")))))]
@@ -7111,14 +7114,15 @@
 ;; operations within an IOR/AND RTX, therefore we have two patterns matching
 ;; each valid permutation.
 
-(define_insn "aarch64_rev16<mode>2_alt1"
+(define_insn "<aop_pref_ior>aarch64_rev16<mode>2_alt1"
   [(set (match_operand:GPI 0 "register_operand" "=r")
-        (ior:GPI (and:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" 
"r")
-                                      (const_int 8))
-                          (match_operand:GPI 3 "const_int_operand" "n"))
-                 (and:GPI (lshiftrt:GPI (match_dup 1)
-                                        (const_int 8))
-                          (match_operand:GPI 2 "const_int_operand" "n"))))]
+       (any_or_plus:GPI
+         (and:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
+                              (const_int 8))
+                  (match_operand:GPI 3 "const_int_operand" "n"))
+         (and:GPI (lshiftrt:GPI (match_dup 1)
+                                (const_int 8))
+                  (match_operand:GPI 2 "const_int_operand" "n"))))]
   "aarch_rev16_shleft_mask_imm_p (operands[3], <MODE>mode)
    && aarch_rev16_shright_mask_imm_p (operands[2], <MODE>mode)"
   "rev16\\t%<w>0, %<w>1"
@@ -7127,12 +7131,13 @@
 
 (define_insn "*aarch64_rev16<mode>2_alt2"
   [(set (match_operand:GPI 0 "register_operand" "=r")
-        (ior:GPI (and:GPI (lshiftrt:GPI (match_operand:GPI 1 
"register_operand" "r")
-                                        (const_int 8))
-                          (match_operand:GPI 2 "const_int_operand" "n"))
-                 (and:GPI (ashift:GPI (match_dup 1)
-                                      (const_int 8))
-                          (match_operand:GPI 3 "const_int_operand" "n"))))]
+       (any_or_plus:GPI
+         (and:GPI (lshiftrt:GPI (match_operand:GPI 1 "register_operand" "r")
+                                (const_int 8))
+                  (match_operand:GPI 2 "const_int_operand" "n"))
+         (and:GPI (ashift:GPI (match_dup 1)
+                              (const_int 8))
+                  (match_operand:GPI 3 "const_int_operand" "n"))))]
   "aarch_rev16_shleft_mask_imm_p (operands[3], <MODE>mode)
    && aarch_rev16_shright_mask_imm_p (operands[2], <MODE>mode)"
   "rev16\\t%<w>0, %<w>1"
@@ -7140,7 +7145,7 @@
 )
 
 ;; Similar pattern to match (rotate (bswap) 16)
-(define_insn "aarch64_rev16si2_alt3"
+(define_insn "*aarch64_rev16si2_alt3"
   [(set (match_operand:SI 0 "register_operand" "=r")
         (rotate:SI (bswap:SI (match_operand:SI 1 "register_operand" "r"))
                    (const_int 16)))]
diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md
index a56edb8ebf4..26ee21e94a4 100644
--- a/gcc/config/aarch64/iterators.md
+++ b/gcc/config/aarch64/iterators.md
@@ -3667,6 +3667,9 @@
                            (pre_inc "preinc")
                            (pre_dec "predec")])
 
+;; Prefer IOR form when expanding any_or_plus
+(define_code_attr aop_pref_ior [(ior "") (xor "*") (plus "*")])
+
 ;; -------------------------------------------------------------------
 ;; Int Iterators.
 ;; -------------------------------------------------------------------

Reply via email to