This patch tweaks i386.md to ensure that it is AOP-safe, i.e. can recognize
shld and shrd instructions when expressed in RTL using either PLUS, IOR or
XOR.  This is a pre-requisite to fixing PR tree-optimization/108477.

This patch has been tested on x86_64-pc-linux-gnu with make bootstrap
and make -k check, both with and without --target_board=unix{-m32}
with no new failures.  Ok for mainline?

To double check the approach used, I've also bootstrap and regression
tested a variant using aop_pref_plus that prefers PLUS in the gen_insn
functions, also with no new failures.


2026-09-30  Roger Sayle  <[email protected]>

gcc/ChangeLog
        * config/i386/i386.md (aop_pref_ior): New code attribute to
        produce "*" for XOR/PLUS.
        (x86_64_shld<nf_name>): Use any_or_plus and aop_pref_ior.
        (x86_64_shld_ndd<nf_name>): Likewise.
        (x86_64_shld_1<nf_name>): Likewise.
        (x86_64_shld_ndd_1<nf_name>): Likewise.
        (*x86_64_shld_shrd_1_nozext_nf): Use any_or_plus.
        (*x86_64_shld_shrd_1_nozext): Likewise.
        (*x86_64_shld_2): Likewise.
        (*x86_64_shld_ndd_2): Likewise.
        (x86_shld<nf_name>): Use any_or_plus and aop_pref_ior.
        (x86_shld_1<nf_name>): Likewise.
        (x86_shld_ndd_1<nf_name>): Likewise.
        (*x86_shld_shrd_1_nozext_nf): Use any_or_plus.
        (*x86_shld_shrd_1_nozext): Likewise.
        (*x86_shld_2): Likewise.
        (*x86_shld_ndd_2): Likewise.
        (x86_64_shrd<nf_name>): Use any_or_plus and aop_pref_ior.
        (x86_64_shrd_ndd<nf_name>): Likewise.
        (x86_64_shrd_1<nf_name>): Likewise.
        (x86_64_shrd_ndd_1<nf_name>): Likewise.
        (*x86_64_shrd_shld_1_nozext_nf): Use any_or_plus.
        (*x86_64_shrd_shld_1_nozext): Likewise.
        (*x86_64_shrd_2): Likewise.
        (*x86_64_shrd_ndd_2): Likewise.
        (x86_shrd<nf_name>): Use any_or_plus and aop_pref_ior.
        (x86_shrd_ndd<nf_name>): Likewise.
        (x86_shrd_1<nf_name>): Likewise.
        (x86_shrd_ndd_1<nf_name>): Likewise.
        (*x86_shrd_shld_1_nozext_nf): Use any_or_plus.
        (*x86_shrd_shld_1_nozext): Likewise.
        (*x86_shrd_2): Likewise.
        (*x86_shrd_ndd_2): Likewise.


Thanks in advance,
Roger
--

diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 9888644ed91..a02a0b9fdaa 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -3761,6 +3761,8 @@
    (set_attr "mode" "QI")])
 
 (define_code_iterator any_or_plus [plus ior xor])
+;; any_or_plus preferred prefix.
+(define_code_attr aop_pref_ior [(ior "") (xor "*") (plus "*")])
 
 (define_insn_and_split "*insvti_highpart_1"
   [(set (match_operand:TI 0 "nonimmediate_operand" "=ro,r,r,&r")
@@ -16372,9 +16374,10 @@
              (symbol_ref "TARGET_ENABLE_NDD_MEM")]
           (symbol_ref "true")))])
 
-(define_insn "x86_64_shld<nf_name>"
+(define_insn "<aop_pref_ior>x86_64_shld<nf_name>"
   [(set (match_operand:DI 0 "nonimmediate_operand" "+r*m")
-        (ior:DI (ashift:DI (match_dup 0)
+        (any_or_plus:DI
+               (ashift:DI (match_dup 0)
                  (and:QI (match_operand:QI 2 "nonmemory_operand" "Jc")
                          (const_int 63)))
                (subreg:DI
@@ -16393,9 +16396,10 @@
    (set_attr "amdfam10_decode" "vector")
    (set_attr "bdver1_decode" "vector")])
 
-(define_insn "x86_64_shld_ndd<nf_name>"
+(define_insn "<aop_pref_ior>x86_64_shld_ndd<nf_name>"
   [(set (match_operand:DI 0 "register_operand" "=r,r")
-        (ior:DI (ashift:DI (match_operand:DI 1 "nonimmediate_operand" "r,m")
+        (any_or_plus:DI
+               (ashift:DI (match_operand:DI 1 "nonimmediate_operand" "r,m")
                  (and:QI (match_operand:QI 3 "nonmemory_operand" "Jc,Jc")
                          (const_int 63)))
                (subreg:DI
@@ -16414,9 +16418,10 @@
    (set_attr "has_nf" "1")
    (set_attr "mode" "DI")])
 
-(define_insn "x86_64_shld_1<nf_name>"
+(define_insn "<aop_pref_ior>x86_64_shld_1<nf_name>"
   [(set (match_operand:DI 0 "nonimmediate_operand" "+r*m")
-        (ior:DI (ashift:DI (match_dup 0)
+        (any_or_plus:DI
+               (ashift:DI (match_dup 0)
                           (match_operand:QI 2 "const_0_to_63_operand"))
                (subreg:DI
                  (lshiftrt:TI
@@ -16436,9 +16441,10 @@
    (set_attr "amdfam10_decode" "vector")
    (set_attr "bdver1_decode" "vector")])
 
-(define_insn "x86_64_shld_ndd_1<nf_name>"
+(define_insn "<aop_pref_ior>x86_64_shld_ndd_1<nf_name>"
   [(set (match_operand:DI 0 "register_operand" "=r,r")
-        (ior:DI (ashift:DI (match_operand:DI 1 "nonimmediate_operand" "r,m")
+        (any_or_plus:DI
+               (ashift:DI (match_operand:DI 1 "nonimmediate_operand" "r,m")
                           (match_operand:QI 3 "const_0_to_63_operand"))
                (subreg:DI
                  (lshiftrt:TI
@@ -16460,8 +16466,9 @@
 
 (define_insn_and_split "*x86_64_shld_shrd_1_nozext_nf"
   [(set (match_operand:DI 0 "nonimmediate_operand")
-       (ior:DI (ashift:DI (match_operand:DI 4 "nonimmediate_operand")
-                            (match_operand:QI 2 "const_0_to_63_operand"))
+       (any_or_plus:DI
+               (ashift:DI (match_operand:DI 4 "nonimmediate_operand")
+                          (match_operand:QI 2 "const_0_to_63_operand"))
                (lshiftrt:DI
                  (match_operand:DI 1 "nonimmediate_operand")
                  (match_operand:QI 3 "const_0_to_63_operand"))))]
@@ -16515,8 +16522,9 @@
 
 (define_insn_and_split "*x86_64_shld_shrd_1_nozext"
   [(set (match_operand:DI 0 "nonimmediate_operand")
-       (ior:DI (ashift:DI (match_operand:DI 4 "nonimmediate_operand")
-                            (match_operand:QI 2 "const_0_to_63_operand"))
+       (any_or_plus:DI
+               (ashift:DI (match_operand:DI 4 "nonimmediate_operand")
+                          (match_operand:QI 2 "const_0_to_63_operand"))
                (lshiftrt:DI
                  (match_operand:DI 1 "nonimmediate_operand")
                  (match_operand:QI 3 "const_0_to_63_operand"))))
@@ -16569,7 +16577,8 @@
 
 (define_insn_and_split "*x86_64_shld_2"
   [(set (match_operand:DI 0 "nonimmediate_operand")
-       (ior:DI (ashift:DI (match_dup 0)
+       (any_or_plus:DI
+               (ashift:DI (match_dup 0)
                           (match_operand:QI 2 "nonmemory_operand"))
                (lshiftrt:DI (match_operand:DI 1 "register_operand")
                             (minus:QI (const_int 64) (match_dup 2)))))
@@ -16590,7 +16599,8 @@
 
 (define_insn_and_split "*x86_64_shld_ndd_2"
   [(set (match_operand:DI 0 "register_operand")
-       (ior:DI (ashift:DI (match_operand:DI 1 "nonimmediate_operand")
+       (any_or_plus:DI
+               (ashift:DI (match_operand:DI 1 "nonimmediate_operand")
                           (match_operand:QI 3 "nonmemory_operand"))
                (lshiftrt:DI (match_operand:DI 2 "register_operand")
                             (minus:QI (const_int 64) (match_dup 3)))))
@@ -16610,9 +16620,10 @@
                                                   (const_int 63)))) 0)))
              (clobber (reg:CC FLAGS_REG))])])
 
-(define_insn "x86_shld<nf_name>"
+(define_insn "<aop_pref_ior>x86_shld<nf_name>"
   [(set (match_operand:SI 0 "nonimmediate_operand" "+r*m")
-        (ior:SI (ashift:SI (match_dup 0)
+        (any_or_plus:SI
+               (ashift:SI (match_dup 0)
                  (and:QI (match_operand:QI 2 "nonmemory_operand" "Ic")
                          (const_int 31)))
                (subreg:SI
@@ -16632,9 +16643,10 @@
    (set_attr "amdfam10_decode" "vector")
    (set_attr "bdver1_decode" "vector")])
 
-(define_insn "x86_shld_ndd<nf_name>"
+(define_insn "<aop_pref_ior>x86_shld_ndd<nf_name>"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r")
-        (ior:SI (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "r,m")
+        (any_or_plus:SI
+               (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "r,m")
                  (and:QI (match_operand:QI 3 "nonmemory_operand" "Ic,Ic")
                          (const_int 31)))
                (subreg:SI
@@ -16654,9 +16666,10 @@
    (set_attr "mode" "SI")])
 
 
-(define_insn "x86_shld_1<nf_name>"
+(define_insn "<aop_pref_ior>x86_shld_1<nf_name>"
   [(set (match_operand:SI 0 "nonimmediate_operand" "+r*m")
-        (ior:SI (ashift:SI (match_dup 0)
+        (any_or_plus:SI
+               (ashift:SI (match_dup 0)
                           (match_operand:QI 2 "const_0_to_31_operand"))
                (subreg:SI
                  (lshiftrt:DI
@@ -16676,9 +16689,10 @@
    (set_attr "amdfam10_decode" "vector")
    (set_attr "bdver1_decode" "vector")])
 
-(define_insn "x86_shld_ndd_1<nf_name>"
+(define_insn "<aop_pref_ior>x86_shld_ndd_1<nf_name>"
   [(set (match_operand:SI 0 "register_operand" "=r,r")
-        (ior:SI (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "r,m")
+        (any_or_plus:SI
+               (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "r,m")
                           (match_operand:QI 3 "const_0_to_31_operand"))
                (subreg:SI
                  (lshiftrt:DI
@@ -16700,8 +16714,9 @@
 
 (define_insn_and_split "*x86_shld_shrd_1_nozext_nf"
   [(set (match_operand:SI 0 "nonimmediate_operand")
-       (ior:SI (ashift:SI (match_operand:SI 4 "nonimmediate_operand")
-                            (match_operand:QI 2 "const_0_to_31_operand"))
+       (any_or_plus:SI
+              (ashift:SI (match_operand:SI 4 "nonimmediate_operand")
+                         (match_operand:QI 2 "const_0_to_31_operand"))
               (lshiftrt:SI
                   (match_operand:SI 1 "nonimmediate_operand")
                   (match_operand:QI 3 "const_0_to_31_operand"))))]
@@ -16755,7 +16770,8 @@
 
 (define_insn_and_split "*x86_shld_shrd_1_nozext"
   [(set (match_operand:SI 0 "nonimmediate_operand")
-       (ior:SI (ashift:SI (match_operand:SI 4 "nonimmediate_operand")
+       (any_or_plus:SI
+              (ashift:SI (match_operand:SI 4 "nonimmediate_operand")
                             (match_operand:QI 2 "const_0_to_31_operand"))
               (lshiftrt:SI
                   (match_operand:SI 1 "nonimmediate_operand")
@@ -16808,7 +16824,8 @@
 
 (define_insn_and_split "*x86_shld_2"
   [(set (match_operand:SI 0 "nonimmediate_operand")
-       (ior:SI (ashift:SI (match_dup 0)
+       (any_or_plus:SI
+               (ashift:SI (match_dup 0)
                           (match_operand:QI 2 "nonmemory_operand"))
                (lshiftrt:SI (match_operand:SI 1 "register_operand")
                             (minus:QI (const_int 32) (match_dup 2)))))
@@ -16829,7 +16846,8 @@
 
 (define_insn_and_split "*x86_shld_ndd_2"
   [(set (match_operand:SI 0 "register_operand")
-       (ior:SI (ashift:SI (match_operand:SI 1 "nonimmediate_operand")
+       (any_or_plus:SI
+               (ashift:SI (match_operand:SI 1 "nonimmediate_operand")
                           (match_operand:QI 3 "nonmemory_operand"))
                (lshiftrt:SI (match_operand:SI 2 "register_operand")
                             (minus:QI (const_int 32) (match_dup 3)))))
@@ -17728,9 +17746,10 @@
 }
   [(set_attr "has_nf" "1")])
 
-(define_insn "x86_64_shrd<nf_name>"
+(define_insn "<aop_pref_ior>x86_64_shrd<nf_name>"
   [(set (match_operand:DI 0 "nonimmediate_operand" "+r*m")
-        (ior:DI (lshiftrt:DI (match_dup 0)
+        (any_or_plus:DI
+               (lshiftrt:DI (match_dup 0)
                  (and:QI (match_operand:QI 2 "nonmemory_operand" "Jc")
                          (const_int 63)))
                (subreg:DI
@@ -17749,9 +17768,10 @@
    (set_attr "amdfam10_decode" "vector")
    (set_attr "bdver1_decode" "vector")])
 
-(define_insn "x86_64_shrd_ndd<nf_name>"
+(define_insn "<aop_pref_ior>x86_64_shrd_ndd<nf_name>"
   [(set (match_operand:DI 0 "register_operand" "=r,r")
-        (ior:DI (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "r,m")
+        (any_or_plus:DI
+               (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "r,m")
                  (and:QI (match_operand:QI 3 "nonmemory_operand" "Jc,Jc")
                          (const_int 63)))
                (subreg:DI
@@ -17770,9 +17790,10 @@
    (set_attr "has_nf" "1")
    (set_attr "mode" "DI")])
 
-(define_insn "x86_64_shrd_1<nf_name>"
+(define_insn "<aop_pref_ior>x86_64_shrd_1<nf_name>"
   [(set (match_operand:DI 0 "nonimmediate_operand" "+r*m")
-        (ior:DI (lshiftrt:DI (match_dup 0)
+        (any_or_plus:DI
+               (lshiftrt:DI (match_dup 0)
                             (match_operand:QI 2 "const_0_to_63_operand"))
                (subreg:DI
                  (ashift:TI
@@ -17792,9 +17813,10 @@
    (set_attr "amdfam10_decode" "vector")
    (set_attr "bdver1_decode" "vector")])
 
-(define_insn "x86_64_shrd_ndd_1<nf_name>"
+(define_insn "<aop_pref_ior>x86_64_shrd_ndd_1<nf_name>"
   [(set (match_operand:DI 0 "register_operand" "=r,r")
-        (ior:DI (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "r,m")
+        (any_or_plus:DI
+               (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "r,m")
                             (match_operand:QI 3 "const_0_to_63_operand"))
                (subreg:DI
                  (ashift:TI
@@ -17816,7 +17838,8 @@
 
 (define_insn_and_split "*x86_64_shrd_shld_1_nozext_nf"
   [(set (match_operand:DI 0 "nonimmediate_operand")
-       (ior:DI (lshiftrt:DI (match_operand:DI 4 "nonimmediate_operand")
+       (any_or_plus:DI
+               (lshiftrt:DI (match_operand:DI 4 "nonimmediate_operand")
                             (match_operand:QI 2 "const_0_to_63_operand"))
                (ashift:DI
                  (match_operand:DI 1 "nonimmediate_operand")
@@ -17871,7 +17894,8 @@
 
 (define_insn_and_split "*x86_64_shrd_shld_1_nozext"
   [(set (match_operand:DI 0 "nonimmediate_operand")
-       (ior:DI (lshiftrt:DI (match_operand:DI 4 "nonimmediate_operand")
+       (any_or_plus:DI
+               (lshiftrt:DI (match_operand:DI 4 "nonimmediate_operand")
                             (match_operand:QI 2 "const_0_to_63_operand"))
                (ashift:DI
                  (match_operand:DI 1 "nonimmediate_operand")
@@ -17925,7 +17949,8 @@
 
 (define_insn_and_split "*x86_64_shrd_2"
   [(set (match_operand:DI 0 "nonimmediate_operand")
-       (ior:DI (lshiftrt:DI (match_dup 0)
+       (any_or_plus:DI
+               (lshiftrt:DI (match_dup 0)
                             (match_operand:QI 2 "nonmemory_operand"))
                (ashift:DI (match_operand:DI 1 "register_operand")
                           (minus:QI (const_int 64) (match_dup 2)))))
@@ -17946,7 +17971,8 @@
 
 (define_insn_and_split "*x86_64_shrd_ndd_2"
   [(set (match_operand:DI 0 "register_operand")
-       (ior:DI (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand")
+       (any_or_plus:DI
+               (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand")
                             (match_operand:QI 3 "nonmemory_operand"))
                (ashift:DI (match_operand:DI 2 "register_operand")
                           (minus:QI (const_int 64) (match_dup 2)))))
@@ -17966,9 +17992,10 @@
                                                   (const_int 63)))) 0)))
              (clobber (reg:CC FLAGS_REG))])])
 
-(define_insn "x86_shrd<nf_name>"
+(define_insn "<aop_pref_ior>x86_shrd<nf_name>"
   [(set (match_operand:SI 0 "nonimmediate_operand" "+r*m")
-        (ior:SI (lshiftrt:SI (match_dup 0)
+        (any_or_plus:SI
+               (lshiftrt:SI (match_dup 0)
                  (and:QI (match_operand:QI 2 "nonmemory_operand" "Ic")
                          (const_int 31)))
                (subreg:SI
@@ -17988,9 +18015,10 @@
    (set_attr "amdfam10_decode" "vector")
    (set_attr "bdver1_decode" "vector")])
 
-(define_insn "x86_shrd_ndd<nf_name>"
+(define_insn "<aop_pref_ior>x86_shrd_ndd<nf_name>"
   [(set (match_operand:SI 0 "register_operand" "=r,r")
-        (ior:SI (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "r,m")
+        (any_or_plus:SI
+               (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "r,m")
                  (and:QI (match_operand:QI 3 "nonmemory_operand" "Ic,Ic")
                          (const_int 31)))
                (subreg:SI
@@ -18009,9 +18037,10 @@
    (set_attr "has_nf" "1")
    (set_attr "mode" "SI")])
 
-(define_insn "x86_shrd_1<nf_name>"
+(define_insn "<aop_pref_ior>x86_shrd_1<nf_name>"
   [(set (match_operand:SI 0 "nonimmediate_operand" "+r*m")
-        (ior:SI (lshiftrt:SI (match_dup 0)
+        (any_or_plus:SI
+               (lshiftrt:SI (match_dup 0)
                             (match_operand:QI 2 "const_0_to_31_operand"))
                (subreg:SI
                  (ashift:DI
@@ -18031,9 +18060,10 @@
    (set_attr "amdfam10_decode" "vector")
    (set_attr "bdver1_decode" "vector")])
 
-(define_insn "x86_shrd_ndd_1<nf_name>"
+(define_insn "<aop_pref_ior>x86_shrd_ndd_1<nf_name>"
   [(set (match_operand:SI 0 "register_operand" "=r,r")
-        (ior:SI (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "r,m")
+        (any_or_plus:SI
+               (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "r,m")
                             (match_operand:QI 3 "const_0_to_31_operand"))
                (subreg:SI
                  (ashift:DI
@@ -18055,8 +18085,9 @@
 
 (define_insn_and_split "*x86_shrd_shld_1_nozext_nf"
   [(set (match_operand:SI 0 "nonimmediate_operand")
-       (ior:SI (lshiftrt:SI (match_operand:SI 4 "nonimmediate_operand")
-                            (match_operand:QI 2 "const_0_to_31_operand"))
+       (any_or_plus:SI
+              (lshiftrt:SI (match_operand:SI 4 "nonimmediate_operand")
+                           (match_operand:QI 2 "const_0_to_31_operand"))
               (ashift:SI
                   (match_operand:SI 1 "nonimmediate_operand")
                   (match_operand:QI 3 "const_0_to_31_operand"))))]
@@ -18110,8 +18141,9 @@
 
 (define_insn_and_split "*x86_shrd_shld_1_nozext"
   [(set (match_operand:SI 0 "nonimmediate_operand")
-       (ior:SI (lshiftrt:SI (match_operand:SI 4 "nonimmediate_operand")
-                            (match_operand:QI 2 "const_0_to_31_operand"))
+       (any_or_plus:SI
+              (lshiftrt:SI (match_operand:SI 4 "nonimmediate_operand")
+                           (match_operand:QI 2 "const_0_to_31_operand"))
               (ashift:SI
                   (match_operand:SI 1 "nonimmediate_operand")
                   (match_operand:QI 3 "const_0_to_31_operand"))))
@@ -18163,7 +18195,8 @@
 
 (define_insn_and_split "*x86_shrd_2"
   [(set (match_operand:SI 0 "nonimmediate_operand")
-       (ior:SI (lshiftrt:SI (match_dup 0)
+       (any_or_plus:SI
+               (lshiftrt:SI (match_dup 0)
                             (match_operand:QI 2 "nonmemory_operand"))
                (ashift:SI (match_operand:SI 1 "register_operand")
                           (minus:QI (const_int 32) (match_dup 2)))))
@@ -18184,7 +18217,8 @@
 
 (define_insn_and_split "*x86_shrd_ndd_2"
   [(set (match_operand:SI 0 "register_operand")
-       (ior:SI (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand")
+       (any_or_plus:SI
+               (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand")
                           (match_operand:QI 3 "nonmemory_operand"))
                (ashift:SI (match_operand:SI 2 "register_operand")
                           (minus:QI (const_int 32) (match_dup 3)))))

Reply via email to