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.

Bootstrapped and regression tested on x86_64-linux-gnu {,-m32}.

Uros.
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 4a2232e4023..3ea2439526b 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -8860,6 +8860,35 @@ (define_peephole2
                             (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 @@ (define_insn "*add<mode>3_carry_0"
    (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 @@ (define_insn "*add<mode>3_carry_0r"
    (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 @@ (define_peephole2
                              (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 @@ (define_insn "*sub<mode>3_carry_0"
    (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 @@ (define_insn "*sub<mode>3_carry_0r"
    (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 00000000000..9120dd440e4
--- /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 00000000000..a12849a4700
--- /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" } } */

Reply via email to