https://gcc.gnu.org/g:0983945b7c1cdc575fefe9c61609e27f18b1ba3f
commit r16-5029-g0983945b7c1cdc575fefe9c61609e27f18b1ba3f Author: Uros Bizjak <[email protected]> Date: Tue Nov 4 10:18:03 2025 +0100 i386: TEST insn should be merged with ADC/SBB insn [PR122390] The attached testcase is currently compiled to: f1: cmpl %esi, %edi adcl %esi, %edi testl %edi, %edi js .L4 ... TEST insn should be merged with ADC/SBB insn. The patch provides missing combined insn patterns. PR target/122390 gcc/ChangeLog: * config/i386/i386.md (*add<mode>3_carry_2): New insn pattern. (*add<mode>3_carry_0_cc): Ditto. (*add<mode>3_carry_0r_cc): Ditto. (*sub<mode>3_carry_2): Ditto. (*sub<mode>3_carry_0_cc): Ditto. (*sub<mode>3_carry_0r_cc): Ditt. gcc/testsuite/ChangeLog: * gcc.target/i386/pr122390.c: New test. * gcc.target/i386/pr122390-1.c: New test. Diff: --- gcc/config/i386/i386.md | 138 +++++++++++++++++++++++++++++ gcc/testsuite/gcc.target/i386/pr122390-1.c | 26 ++++++ gcc/testsuite/gcc.target/i386/pr122390.c | 44 +++++++++ 3 files changed, 208 insertions(+) diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 4a2232e40239..3ea2439526be 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -8860,6 +8860,35 @@ (match_dup 0))) (clobber (reg:CC FLAGS_REG))])]) +(define_insn "*add<mode>3_carry_2" + [(set (reg FLAGS_REG) + (compare + (plus:SWI + (plus:SWI + (match_operator:SWI 4 "ix86_carry_flag_operator" + [(match_operand 3 "flags_reg_operand") (const_int 0)]) + (match_operand:SWI 1 "nonimmediate_operand" "%0,0,rm,r")) + (match_operand:SWI 2 "<general_operand>" "<r><i>,<m>,r<i>,<m>")) + (const_int 0))) + (set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,<r>,r,r") + (plus:SWI + (plus:SWI + (match_op_dup 4 [(match_dup 3) (const_int 0)]) + (match_dup 1)) + (match_dup 2)))] + "ix86_match_ccmode (insn, CCGOCmode) + && ix86_binary_operator_ok (PLUS, <MODE>mode, operands, TARGET_APX_NDD)" + "@ + adc{<imodesuffix>}\t{%2, %0|%0, %2} + adc{<imodesuffix>}\t{%2, %0|%0, %2} + adc{<imodesuffix>}\t{%2, %1, %0|%0, %1, %2} + adc{<imodesuffix>}\t{%2, %1, %0|%0, %1, %2}" + [(set_attr "isa" "*,*,apx_ndd,apx_ndd") + (set_attr "type" "alu") + (set_attr "use_carry" "1") + (set_attr "pent_pair" "pu") + (set_attr "mode" "<MODE>")]) + (define_insn "*add<mode>3_carry_0" [(set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m") (plus:SWI @@ -8874,6 +8903,26 @@ (set_attr "pent_pair" "pu") (set_attr "mode" "<MODE>")]) +(define_insn "*add<mode>3_carry_0_cc" + [(set (reg FLAGS_REG) + (compare + (plus:SWI + (match_operator:SWI 2 "ix86_carry_flag_operator" + [(match_operand 3 "flags_reg_operand") (const_int 0)]) + (match_operand:SWI 1 "nonimmediate_operand" "0")) + (const_int 0))) + (set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m") + (plus:SWI + (match_op_dup 2 [(match_dup 3) (const_int 0)]) + (match_dup 1)))] + "ix86_match_ccmode (insn, CCGOCmode) + && (!MEM_P (operands[0]) || rtx_equal_p (operands[0], operands[1]))" + "adc{<imodesuffix>}\t{$0, %0|%0, 0}" + [(set_attr "type" "alu") + (set_attr "use_carry" "1") + (set_attr "pent_pair" "pu") + (set_attr "mode" "<MODE>")]) + (define_insn "*add<mode>3_carry_0r" [(set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m") (plus:SWI @@ -8888,6 +8937,26 @@ (set_attr "pent_pair" "pu") (set_attr "mode" "<MODE>")]) +(define_insn "*add<mode>3_carry_0r_cc" + [(set (reg FLAGS_REG) + (compare + (plus:SWI + (match_operator:SWI 2 "ix86_carry_flag_unset_operator" + [(match_operand 3 "flags_reg_operand") (const_int 0)]) + (match_operand:SWI 1 "nonimmediate_operand" "0")) + (const_int 0))) + (set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m") + (plus:SWI + (match_op_dup 2 [(match_dup 3) (const_int 0)]) + (match_dup 1)))] + "ix86_match_ccmode (insn, CCGOCmode) + && (!MEM_P (operands[0]) || rtx_equal_p (operands[0], operands[1]))" + "sbb{<imodesuffix>}\t{$-1, %0|%0, -1}" + [(set_attr "type" "alu") + (set_attr "use_carry" "1") + (set_attr "pent_pair" "pu") + (set_attr "mode" "<MODE>")]) + (define_insn "*addqi3_carry_zext<mode>" [(set (match_operand:SWI248x 0 "register_operand" "=r,r") (zero_extend:SWI248x @@ -9456,6 +9525,35 @@ (match_dup 0))) (clobber (reg:CC FLAGS_REG))])]) +(define_insn "*sub<mode>3_carry_2" + [(set (reg FLAGS_REG) + (compare + (minus:SWI + (minus:SWI + (match_operand:SWI 1 "nonimmediate_operand" "0,0,rm,r") + (match_operator:SWI 4 "ix86_carry_flag_operator" + [(match_operand 3 "flags_reg_operand") (const_int 0)])) + (match_operand:SWI 2 "<general_operand>" "<r><i>,<m>,r<i>,<m>")) + (const_int 0))) + (set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,<r>,r,r") + (minus:SWI + (minus:SWI + (match_dup 1) + (match_op_dup 4 [(match_dup 3) (const_int 0)])) + (match_dup 2)))] + "ix86_match_ccmode (insn, CCGOCmode) + && ix86_binary_operator_ok (MINUS, <MODE>mode, operands, TARGET_APX_NDD)" + "@ + sbb{<imodesuffix>}\t{%2, %0|%0, %2} + sbb{<imodesuffix>}\t{%2, %0|%0, %2} + sbb{<imodesuffix>}\t{%2, %1, %0|%0, %1, %2} + sbb{<imodesuffix>}\t{%2, %1, %0|%0, %1, %2}" + [(set_attr "isa" "*,*,apx_ndd,apx_ndd") + (set_attr "type" "alu") + (set_attr "use_carry" "1") + (set_attr "pent_pair" "pu") + (set_attr "mode" "<MODE>")]) + (define_insn "*sub<mode>3_carry_0" [(set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m") (minus:SWI @@ -9470,6 +9568,26 @@ (set_attr "pent_pair" "pu") (set_attr "mode" "<MODE>")]) +(define_insn "*sub<mode>3_carry_0_cc" + [(set (reg FLAGS_REG) + (compare + (minus:SWI + (match_operand:SWI 1 "nonimmediate_operand" "0") + (match_operator:SWI 2 "ix86_carry_flag_operator" + [(match_operand 3 "flags_reg_operand") (const_int 0)])) + (const_int 0))) + (set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m") + (minus:SWI + (match_dup 1) + (match_op_dup 2 [(match_dup 3) (const_int 0)])))] + "ix86_match_ccmode (insn, CCGOCmode) + && (!MEM_P (operands[0]) || rtx_equal_p (operands[0], operands[1]))" + "sbb{<imodesuffix>}\t{$0, %0|%0, 0}" + [(set_attr "type" "alu") + (set_attr "use_carry" "1") + (set_attr "pent_pair" "pu") + (set_attr "mode" "<MODE>")]) + (define_insn "*sub<mode>3_carry_0r" [(set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m") (minus:SWI @@ -9484,6 +9602,26 @@ (set_attr "pent_pair" "pu") (set_attr "mode" "<MODE>")]) +(define_insn "*sub<mode>3_carry_0r_cc" + [(set (reg FLAGS_REG) + (compare + (minus:SWI + (match_operand:SWI 1 "nonimmediate_operand" "0") + (match_operator:SWI 2 "ix86_carry_flag_unset_operator" + [(match_operand 3 "flags_reg_operand") (const_int 0)])) + (const_int 0))) + (set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m") + (minus:SWI + (match_dup 1) + (match_op_dup 2 [(match_dup 3) (const_int 0)])))] + "ix86_match_ccmode (insn, CCGOCmode) + && (!MEM_P (operands[0]) || rtx_equal_p (operands[0], operands[1]))" + "adc{<imodesuffix>}\t{$-1, %0|%0, -1}" + [(set_attr "type" "alu") + (set_attr "use_carry" "1") + (set_attr "pent_pair" "pu") + (set_attr "mode" "<MODE>")]) + (define_insn "*subqi3_carry_zext<mode>" [(set (match_operand:SWI248x 0 "register_operand" "=r,r") (zero_extend:SWI248x diff --git a/gcc/testsuite/gcc.target/i386/pr122390-1.c b/gcc/testsuite/gcc.target/i386/pr122390-1.c new file mode 100644 index 000000000000..9120dd440e4e --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr122390-1.c @@ -0,0 +1,26 @@ +/* PR target/122390 */ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +int f (int); +int g (int); + +int f1 (unsigned a, unsigned b) +{ + unsigned t = a < b; + int tt = a + b + t; + if (tt < 0) + return f(tt); + return g(tt); +} + +int f2 (unsigned a, unsigned b) +{ + unsigned t = a < b; + int tt = a - b - t; + if (tt < 0) + return f(tt); + return g(tt); +} + +/* { dg-final { scan-assembler-not "test" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr122390.c b/gcc/testsuite/gcc.target/i386/pr122390.c new file mode 100644 index 000000000000..a12849a47006 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr122390.c @@ -0,0 +1,44 @@ +/* PR target/122390 */ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +int f (int); +int g (int); + +int f1 (unsigned a, unsigned b) +{ + unsigned t = a < b; + int tt = a + t; + if (tt == 0) + return f(tt); + return g(tt); +} + +int f2 (unsigned a, unsigned b) +{ + unsigned t = a <= b; + int tt = a + t; + if (tt < 0) + return f(tt); + return g(tt); +} + +int f3 (unsigned a, unsigned b) +{ + unsigned t = a > b; + int tt = a - t; + if (tt == 0) + return f(tt); + return g(tt); +} + +int f4 (unsigned a, unsigned b) +{ + unsigned t = a >= b; + int tt = a - t; + if (tt < 0) + return f(tt); + return g(tt); +} + +/* { dg-final { scan-assembler-not "test" } } */
