i386: Apply LRA reload workaround to insns with high registers [PR82524]
commitdced5ae64703507a7159972316a1dde48e5f7470
authorUros Bizjak <ubizjak@gmail.com>
Wed, 8 Nov 2023 20:46:26 +0000 (8 21:46 +0100)
committerUros Bizjak <ubizjak@gmail.com>
Wed, 8 Nov 2023 20:51:31 +0000 (8 21:51 +0100)
treeb785ec3b0ca319e0497662dec74e51c2b2a14b0a
parent39d81b667373b0033f44702a4b532a4618dde9ff
i386: Apply LRA reload workaround to insns with high registers [PR82524]

LRA is not able to reload zero_extracted in-out operand with matched input
operand in the same way as strict_low_part in-out operand.  The patch
applies the strict_low_part workaround, where we allow LRA to generate
an instruction with non-matched input operand, which is split post reload
to the instruction that inserts non-matched input operand to an in-out
operand and the instruction that uses matched operand, also to
zero_extracted in-out operand case.

The generated code from the pr82524.c testcase improves from:

movl    %esi, %ecx
movl    %edi, %eax
movsbl  %ch, %esi
addl    %esi, %edx
movb    %dl, %ah

to:
movl    %edi, %eax
movl    %esi, %ecx
movb    %ch, %ah
addb    %dl, %ah

The compiler is now also able to handle non-commutative operations:

movl    %edi, %eax
movl    %esi, %ecx
movb    %ch, %ah
subb    %dl, %ah

and unary operations:

movl    %edi, %eax
movl    %esi, %edx
movb    %dh, %ah
negb    %ah

The patch also robustifies split condition of the splitters to ensure that
only alternatives with unmatched operands are split.

PR target/82524

gcc/ChangeLog:

* config/i386/i386.md (*add<mode>_1_slp):
Split insn only for unmatched operand 0.
(*sub<mode>_1_slp): Ditto.
(*<any_logic:code><mode>_1_slp): Merge pattern from "*and<mode>_1_slp"
and "*<any_logic:code><mode>_1_slp" using any_logic code iterator.
Split insn only for unmatched operand 0.
(*neg<mode>1_slp): Split insn only for unmatched operand 0.
(*one_cmpl<mode>_1_slp): Ditto.
(*ashl<mode>3_1_slp): Ditto.
(*<any_shiftrt:insn><mode>_1_slp): Ditto.
(*<any_rotate:insn><mode>_1_slp): Ditto.
(*addqi_ext<mode>_1): Redefine as define_insn_and_split.  Add
alternative 1 and split insn after reload for unmatched operand 0.
(*<plusminus:insn>qi_ext<mode>_2): Merge pattern from
"*addqi_ext<mode>_2" and "*subqi_ext<mode>_2" using plusminus code
iterator. Redefine as define_insn_and_split.  Add alternative 1
and split insn after reload for unmatched operand 0.
(*subqi_ext<mode>_1): Redefine as define_insn_and_split.  Add
alternative 1 and split insn after reload for unmatched operand 0.
(*<any_logic:code>qi_ext<mode>_0): Merge pattern from
"*andqi_ext<mode>_0" and and "*<any_logic:code>qi_ext<mode>_0" using
any_logic code iterator.
(*<any_logic:code>qi_ext<mode>_1): Merge pattern from
"*andqi_ext<mode>_1" and "*<any_logic:code>qi_ext<mode>_1" using
any_logic code iterator. Redefine as define_insn_and_split.  Add
alternative 1 and split insn after reload for unmatched operand 0.
(*<any_logic:code>qi_ext<mode>_1_cc): Merge pattern from
"*andqi_ext<mode>_1_cc" and "*xorqi_ext<mode>_1_cc" using any_logic
code iterator. Redefine as define_insn_and_split.  Add alternative 1
and split insn after reload for unmatched operand 0.
(*<any_logic:code>qi_ext<mode>_2): Merge pattern from
"*andqi_ext<mode>_2" and "*<any_or:code>qi_ext<mode>_2" using
any_logic code iterator. Redefine as define_insn_and_split.  Add
alternative 1 and split insn after reload for unmatched operand 0.
(*<any_logic:code>qi_ext<mode>_3): Redefine as define_insn_and_split.
Add alternative 1 and split insn after reload for unmatched operand 0.
(*negqi_ext<mode>_1): Rename from "*negqi_ext<mode>_2".  Add
alternative 1 and split insn after reload for unmatched operand 0.
(*one_cmplqi_ext<mode>_1): Ditto.
(*ashlqi_ext<mode>_1): Ditto.
(*<any_shiftrt:insn>qi_ext<mode>_1): Ditto.

gcc/testsuite/ChangeLog:

* gcc.target/i386/pr78904-1.c (test_sub): New test.
* gcc.target/i386/pr78904-1a.c (test_sub): Ditto.
* gcc.target/i386/pr78904-1b.c (test_sub): Ditto.
* gcc.target/i386/pr78904-2.c (test_sub): Ditto.
* gcc.target/i386/pr78904-2a.c (test_sub): Ditto.
* gcc.target/i386/pr78904-2b.c (test_sub): Ditto.
* gcc.target/i386/pr78952-4.c (test_sub): Ditto.
* gcc.target/i386/pr82524.c: New test.
* gcc.target/i386/pr82524-1.c: New test.
* gcc.target/i386/pr82524-2.c: New test.
* gcc.target/i386/pr82524-3.c: New test.
12 files changed:
gcc/config/i386/i386.md
gcc/testsuite/gcc.target/i386/pr78904-1.c
gcc/testsuite/gcc.target/i386/pr78904-1a.c
gcc/testsuite/gcc.target/i386/pr78904-1b.c
gcc/testsuite/gcc.target/i386/pr78904-2.c
gcc/testsuite/gcc.target/i386/pr78904-2a.c
gcc/testsuite/gcc.target/i386/pr78904-2b.c
gcc/testsuite/gcc.target/i386/pr78952-4.c
gcc/testsuite/gcc.target/i386/pr82524-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr82524-2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr82524-3.c [copied from gcc/testsuite/gcc.target/i386/pr78904-1b.c with 51% similarity]
gcc/testsuite/gcc.target/i386/pr82524.c [new file with mode: 0644]