This patch resolves PR target/110588 to catch another case in combine where the i386 backend should be generating a btl instruction. This adds another define_insn_and_split to recognize the RTL representation for this case.
I also noticed that two related define_insn_and_split weren't using the preferred string style for single statement preparation-statements, so I've reformatted these to be consistent in style with the new one. 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? 2023-07-13 Roger Sayle <ro...@nextmovesoftware.com> gcc/ChangeLog PR target/110588 * config/i386/i386.md (*bt<mode>_setcqi): Prefer string form preparation statement over braces for a single statement. (*bt<mode>_setncqi): Likewise. (*bt<mode>_setncqi_2): New define_insn_and_split. gcc/testsuite/ChangeLog PR target/110588 * gcc.target/i386/pr110588.c: New test case. Thanks again, Roger --
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index e47ced1..04eca049 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -16170,9 +16170,7 @@ (const_int 0))) (set (match_dup 0) (eq:QI (reg:CCC FLAGS_REG) (const_int 0)))] -{ - operands[2] = lowpart_subreg (SImode, operands[2], QImode); -}) + "operands[2] = lowpart_subreg (SImode, operands[2], QImode);") ;; Help combine recognize bt followed by setnc (define_insn_and_split "*bt<mode>_setncqi" @@ -16193,9 +16191,7 @@ (const_int 0))) (set (match_dup 0) (ne:QI (reg:CCC FLAGS_REG) (const_int 0)))] -{ - operands[2] = lowpart_subreg (SImode, operands[2], QImode); -}) + "operands[2] = lowpart_subreg (SImode, operands[2], QImode);") (define_insn_and_split "*bt<mode>_setnc<mode>" [(set (match_operand:SWI48 0 "register_operand") @@ -16219,6 +16215,27 @@ operands[2] = lowpart_subreg (SImode, operands[2], QImode); operands[3] = gen_reg_rtx (QImode); }) + +;; Help combine recognize bt followed by setnc (PR target/110588) +(define_insn_and_split "*bt<mode>_setncqi_2" + [(set (match_operand:QI 0 "register_operand") + (eq:QI + (zero_extract:SWI48 + (match_operand:SWI48 1 "register_operand") + (const_int 1) + (zero_extend:SI (match_operand:QI 2 "register_operand"))) + (const_int 0))) + (clobber (reg:CC FLAGS_REG))] + "TARGET_USE_BT && ix86_pre_reload_split ()" + "#" + "&& 1" + [(set (reg:CCC FLAGS_REG) + (compare:CCC + (zero_extract:SWI48 (match_dup 1) (const_int 1) (match_dup 2)) + (const_int 0))) + (set (match_dup 0) + (ne:QI (reg:CCC FLAGS_REG) (const_int 0)))] + "operands[2] = lowpart_subreg (SImode, operands[2], QImode);") ;; Store-flag instructions. diff --git a/gcc/testsuite/gcc.target/i386/pr110588.c b/gcc/testsuite/gcc.target/i386/pr110588.c new file mode 100644 index 0000000..4505c87 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr110588.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mtune=core2" } */ + +unsigned char foo (unsigned char x, int y) +{ + int _1 = (int) x; + int _2 = _1 >> y; + int _3 = _2 & 1; + unsigned char _8 = (unsigned char) _3; + unsigned char _6 = _8 ^ 1; + return _6; +} + +/* { dg-final { scan-assembler "btl" } } */ +/* { dg-final { scan-assembler "setnc" } } */ +/* { dg-final { scan-assembler-not "sarl" } } */ +/* { dg-final { scan-assembler-not "andl" } } */ +/* { dg-final { scan-assembler-not "xorl" } } */