re PR target/85095 (worse code generated)
authorJakub Jelinek <jakub@redhat.com>
Wed, 28 Mar 2018 19:16:50 +0000 (21:16 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Wed, 28 Mar 2018 19:16:50 +0000 (21:16 +0200)
PR target/85095
* config/i386/i386.md (*add<mode>3_carry_0, *addsi3_carry_zext_0,
*sub<mode>3_carry_0, *subsi3_carry_zext_0): New patterns.

* gcc.target/i386/pr85095-1.c: New test.
* gcc.target/i386/pr85095-2.c: New test.
* gcc.c-torture/execute/pr85095.c: New test.

From-SVN: r258931

gcc/ChangeLog
gcc/config/i386/i386.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/pr85095.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr85095-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr85095-2.c [new file with mode: 0644]

index 3ac9f9bdd5cedd5dcbf1f5958c73e9c0d52cbdc9..8da14418a397ea812ce07bc0f6d2e9bf120470f5 100644 (file)
@@ -1,5 +1,9 @@
 2018-03-28  Jakub Jelinek  <jakub@redhat.com>
 
+       PR target/85095
+       * config/i386/i386.md (*add<mode>3_carry_0, *addsi3_carry_zext_0,
+       *sub<mode>3_carry_0, *subsi3_carry_zext_0): New patterns.
+
        PR tree-optimization/82004
        * gimple-match-head.c (optimize_pow_to_exp): New function.
        * match.pd (pow(C,x) -> exp(log(C)*x)): Wrap with #if GIMPLE.
index 5eb9e2fa0e698b3d9abef9d5c2d055a64d13bbcd..b28e783103088bba9496440944b50db76cec37c7 100644 (file)
    (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
+         (match_operator:SWI 3 "ix86_carry_flag_operator"
+           [(match_operand 2 "flags_reg_operand") (const_int 0)])
+         (match_operand:SWI 1 "nonimmediate_operand" "0")))
+   (clobber (reg:CC FLAGS_REG))]
+  "ix86_unary_operator_ok (PLUS, <MODE>mode, operands)"
+  "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 "*addsi3_carry_zext"
   [(set (match_operand:DI 0 "register_operand" "=r")
        (zero_extend:DI
    (set_attr "pent_pair" "pu")
    (set_attr "mode" "SI")])
 
+(define_insn "*addsi3_carry_zext_0"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (zero_extend:DI
+         (plus:SI (match_operator:SI 2 "ix86_carry_flag_operator"
+                   [(reg FLAGS_REG) (const_int 0)])
+                  (match_operand:SI 1 "register_operand" "0"))))
+   (clobber (reg:CC FLAGS_REG))]
+  "TARGET_64BIT"
+  "adc{l}\t{$0, %k0|%k0, 0}"
+  [(set_attr "type" "alu")
+   (set_attr "use_carry" "1")
+   (set_attr "pent_pair" "pu")
+   (set_attr "mode" "SI")])
+
 ;; There is no point to generate ADCX instruction. ADC is shorter and faster.
 
 (define_insn "addcarry<mode>"
    (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
+         (match_operand:SWI 1 "nonimmediate_operand" "0")
+         (match_operator:SWI 3 "ix86_carry_flag_operator"
+           [(match_operand 2 "flags_reg_operand") (const_int 0)])))
+   (clobber (reg:CC FLAGS_REG))]
+  "ix86_unary_operator_ok (MINUS, <MODE>mode, operands)"
+  "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 "*subsi3_carry_zext"
   [(set (match_operand:DI 0 "register_operand" "=r")
        (zero_extend:DI
    (set_attr "pent_pair" "pu")
    (set_attr "mode" "SI")])
 
+(define_insn "*subsi3_carry_zext_0"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (zero_extend:DI
+         (minus:SI
+           (match_operand:SI 1 "register_operand" "0")
+           (match_operator:SI 2 "ix86_carry_flag_operator"
+             [(reg FLAGS_REG) (const_int 0)]))))
+   (clobber (reg:CC FLAGS_REG))]
+  "TARGET_64BIT"
+  "sbb{l}\t{$0, %k0|%k0, 0}"
+  [(set_attr "type" "alu")
+   (set_attr "use_carry" "1")
+   (set_attr "pent_pair" "pu")
+   (set_attr "mode" "SI")])
+
 (define_insn "sub<mode>3_carry_ccc"
   [(set (reg:CCC FLAGS_REG)
        (compare:CCC
index 78a1ebb3c8b2ff78732aa4550afa544027400aa1..62111d459d3a015ce262b1fca5d03fea58a200cd 100644 (file)
@@ -1,5 +1,10 @@
 2018-03-28  Jakub Jelinek  <jakub@redhat.com>
 
+       PR target/85095
+       * gcc.target/i386/pr85095-1.c: New test.
+       * gcc.target/i386/pr85095-2.c: New test.
+       * gcc.c-torture/execute/pr85095.c: New test.
+
        PR tree-optimization/82004
        * gcc.dg/pr82004.c: New test.
 
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr85095.c b/gcc/testsuite/gcc.c-torture/execute/pr85095.c
new file mode 100644 (file)
index 0000000..8b78b58
--- /dev/null
@@ -0,0 +1,52 @@
+/* PR target/85095 */
+
+__attribute__((noipa)) unsigned long
+f1 (unsigned long a, unsigned long b)
+{
+  unsigned long i = __builtin_add_overflow (a, b, &a);
+  return a + i;
+}
+
+__attribute__((noipa)) unsigned long
+f2 (unsigned long a, unsigned long b)
+{
+  unsigned long i = __builtin_add_overflow (a, b, &a);
+  return a - i;
+}
+
+__attribute__((noipa)) unsigned long
+f3 (unsigned int a, unsigned int b)
+{
+  unsigned int i = __builtin_add_overflow (a, b, &a);
+  return a + i;
+}
+
+__attribute__((noipa)) unsigned long
+f4 (unsigned int a, unsigned int b)
+{
+  unsigned int i = __builtin_add_overflow (a, b, &a);
+  return a - i;
+}
+
+int
+main ()
+{
+  if (f1 (16UL, -18UL) != -2UL
+      || f1 (16UL, -17UL) != -1UL
+      || f1 (16UL, -16UL) != 1UL
+      || f1 (16UL, -15UL) != 2UL
+      || f2 (24UL, -26UL) != -2UL
+      || f2 (24UL, -25UL) != -1UL
+      || f2 (24UL, -24UL) != -1UL
+      || f2 (24UL, -23UL) != 0UL
+      || f3 (32U, -34U) != -2U
+      || f3 (32U, -33U) != -1U
+      || f3 (32U, -32U) != 1U
+      || f3 (32U, -31U) != 2U
+      || f4 (35U, -37U) != -2U
+      || f4 (35U, -36U) != -1U
+      || f4 (35U, -35U) != -1U
+      || f4 (35U, -34U) != 0U)
+    __builtin_abort ();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr85095-1.c b/gcc/testsuite/gcc.target/i386/pr85095-1.c
new file mode 100644 (file)
index 0000000..4c882e0
--- /dev/null
@@ -0,0 +1,33 @@
+/* PR target/85095 *
+/* { dg-do compile } */
+/* { dg-options "-O2 -masm=att" } */
+
+unsigned int
+foo (unsigned int a, unsigned int b)
+{
+  a += b;
+  if (a < b) a++;
+  return a;
+}
+
+#ifdef __x86_64__
+unsigned long long
+bar (unsigned long long a, unsigned long long b)
+{
+  a += b;
+  if (a < b) a++;
+  return a;
+}
+
+unsigned long long
+baz (unsigned int a, unsigned int b)
+{
+  a += b;
+  if (a < b) a++;
+  return a;
+}
+#endif
+
+/* { dg-final { scan-assembler-times "adcl\t\\\$0," 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "adcl\t\\\$0," 2 { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-times "adcq\t\\\$0," 1 { target { ! ia32 } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr85095-2.c b/gcc/testsuite/gcc.target/i386/pr85095-2.c
new file mode 100644 (file)
index 0000000..fbd7992
--- /dev/null
@@ -0,0 +1,54 @@
+/* PR target/85095 *
+/* { dg-do compile } */
+/* { dg-options "-O2 -masm=att" } */
+
+unsigned int
+f1 (unsigned int a, unsigned int b)
+{
+  unsigned int i = __builtin_add_overflow (a, b, &a);
+  return a + i;
+}
+
+unsigned int
+f2 (unsigned int a, unsigned int b)
+{
+  unsigned int i = __builtin_add_overflow (a, b, &a);
+  return a - i;
+}
+
+#ifdef __x86_64__
+unsigned long long
+f3 (unsigned long long a, unsigned long long b)
+{
+  unsigned long long i = __builtin_add_overflow (a, b, &a);
+  return a + i;
+}
+
+unsigned long long
+f4 (unsigned long long a, unsigned long long b)
+{
+  unsigned long long i = __builtin_add_overflow (a, b, &a);
+  return a - i;
+}
+
+unsigned long long
+f5 (unsigned int a, unsigned int b)
+{
+  unsigned int i = __builtin_add_overflow (a, b, &a);
+  return a + i;
+}
+
+unsigned long long
+f6 (unsigned int a, unsigned int b)
+{
+  unsigned int i = __builtin_add_overflow (a, b, &a);
+  return a - i;
+}
+#endif
+
+/* { dg-final { scan-assembler-times "adcl\t\\\$0," 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "sbbl\t\\\$0," 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "adcl\t\\\$0," 2 { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-times "sbbl\t\\\$0," 2 { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-times "adcq\t\\\$0," 1 { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-times "sbbq\t\\\$0," 1 { target { ! ia32 } } } } */