https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121306

--- Comment #11 from GCC Commits <cvs-commit at gcc dot gnu.org> ---
The trunk branch has been updated by Richard Sandiford <rsand...@gcc.gnu.org>:

https://gcc.gnu.org/g:5305f84c3be3de9397907dfaf151477579d91c77

commit r16-2789-g5305f84c3be3de9397907dfaf151477579d91c77
Author: Richard Sandiford <richard.sandif...@arm.com>
Date:   Tue Aug 5 14:42:34 2025 +0100

    i386: Extend recognition of high-reg rvalues [PR121306]

    The i386 high-register patterns used things like:

        (match_operator:SWI248 2 "extract_operator"
          [(match_operand 0 "int248_register_operand" "Q")
           (const_int 8)
           (const_int 8)])

    to match an extraction of a high register such as AH from AX/EAX/RAX.

    This construct is used in contexts where only the low 8 bits of the
    value matter.  This is either done explicitly using a (subreg:QI ... 0)
    or implicitly by assigning to an 8-bit zero_extract destination.

    extract_operator therefore matches both sign_extract and zero_extract,
    since the signedness of the extension beyond 8 bits is irrelevant.

    But the fact that only the low 8 bits of the value are significant
    means that a shift right by 8 is as good as an extraction.  Shifts
    right would already be used for things like:

      struct s {
        long a:8;
        long b:8;
        long c:48;
      };

      struct s f(struct s x, long y, long z) {
        x.b = (y & z) >> 8;
        return x;
      }

    but are used more after g:965564eafb721f8000013a3112f1bba8d8fae32b.

    This patch therefore replaces extract_operator with a new predicate
    called extract_high_operator that matches both extractions and shifts.
    The predicate checks the extraction field and shift amount itself,
    so that patterns only need to match the first operand.

    Splitters used match_op_dup to preserve the choice of extraction.
    But the fact that the extractions (and now shifts) are equivalent
    means that we can just as easily canonicalise on one of them.
    (In theory, canonicalisation would also promote CSE, although
    that's unlikely in practice.)  The patch goes for zero_extract,
    for consistency with destinations.

    gcc/
            PR target/121306
            * config/i386/predicates.md (extract_operator): Replace with...
            (extract_high_operator): ...this new predicate.
            * config/i386/i386.md (*cmpqi_ext<mode>_1, *cmpqi_ext<mode>_2)
            (*cmpqi_ext<mode>_3, *cmpqi_ext<mode>_4, *movstrictqi_ext<mode>_1)
            (*extzv<mode>, *insvqi_2, *extendqi<SWI24:mode>_ext_1)
            (*addqi_ext<mode>_1_slp, *addqi_ext<mode>_1_slp,
*addqi_ext<mode>_0)
            (*addqi_ext2<mode>_0, *addqi_ext<mode>_1, *<insn>qi_ext<mode>_2)
            (*subqi_ext<mode>_1_slp, *subqi_ext<mode>_2_slp,
*subqi_ext<mode>_0)
            (*subqi_ext2<mode>_0, *subqi_ext<mode>_1, *testqi_ext<mode>_1)
            (*testqi_ext<mode>_2, *<code>qi_ext<mode>_1_slp)
            (*<code>qi_ext<mode>_2_slp. *<code>qi_ext<mode>_0)
            (*<code>qi_ext2<mode>_0, *<code>qi_ext<mode>_1)
            (*<code>qi_ext<mode>_1_cc, *<code>qi_ext<mode>_1_cc)
            (*<code>qi_ext<mode>_2, *<code>qi_ext<mode>_3, *negqi_ext<mode>_1)
            (*one_cmplqi_ext<mode>_1, *ashlqi_ext<mode>_1,
*<insn>qi_ext<mode>_1)
            (define_peephole2): Replace uses of extract_operator with
            extract_high_operator, matching only the first operand.
            Use zero_extract rather than match_op_dup when splitting.

Reply via email to