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.
;; -------------------------------------------------------------------