On Wed, Sep 30, 2026 at 1:12 AM Roger Sayle <[email protected]> wrote:
>
>
> 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.
In cases like this, the target-independent infrastructure patch should
be reviewed and committed first, so this patch should be considered a
kind of RFC patch to illustrate what the middle-end will do with the
target.
Otherwise LGTM, with a few nits:
(define_code_iterator any_or_plus [plus ior xor])
+;; any_or_plus preferred prefix.
+(define_code_attr aop_pref_ior [(ior "") (xor "*") (plus "*")])
aop_pref_ior reads oddly, since it's really a name prefix for the
non-IOR variants. Something like aop_name_pfx, with a comment would
IMO be better:
;; Name prefix for any_or_plus insns: only the IOR form keeps a gen_* function.
(define_code_attr aop_name_pfx [(ior "") (xor "*") (plus "*")])
(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)
AI review flagged the line above as mixed \tSP\t indent. The
re-indentation is also inconsistent in a few other places. The nozext
patterns had their continuation lines realigned, while the *_2, _ndd_2
and nozext SI variants kept the old alignment against the moved
(ashift. AI of your choice is ideal for fixing these nits.
(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)))))
Ooh, a pre-existing bug in *x86_64_shrd_ndd_2. Here match_dup 2 refers
to the DImode register, but the count is operand 3. CCs added.
Uros.