]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
i386: Add more forms peephole2 for adc/sbb
authorHu, Lin1 <lin1.hu@intel.com>
Wed, 19 Feb 2025 07:51:40 +0000 (15:51 +0800)
committerHu, Lin1 <lin1.hu@intel.com>
Wed, 4 Jun 2025 05:36:43 +0000 (13:36 +0800)
Enable -mapxf will change some patterns about adc/sbb.

Hence gcc will raise an extra mov like
         movq    8(%rdi), %rax
         adcq    %rax, 8(%rsi), %rax
         movq    %rax, 8(%rdi)
rather than
         movq    8(%rsi), %rax
         adcq    %rax, 8(%rdi)

The patch add more kinds of peephole2 to eliminate the extra mov.

gcc/ChangeLog:

* config/i386/i386.md: Add 4 new peephole2 by swap the original
peephole2's operands' order to support new pattern.

gcc/testsuite/ChangeLog:

* gcc.target/i386/pr79173-13.c: New test.
* gcc.target/i386/pr79173-14.c: Ditto.
* gcc.target/i386/pr79173-15.c: Ditto.
* gcc.target/i386/pr79173-16.c: Ditto.
* gcc.target/i386/pr79173-17.c: Ditto.
* gcc.target/i386/pr79173-18.c: Ditto.

gcc/config/i386/i386.md
gcc/testsuite/gcc.target/i386/pr79173-13.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr79173-14.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr79173-15.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr79173-16.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr79173-17.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr79173-18.c [new file with mode: 0644]

index b7a18d583da3707a901ece3d1b0ca8b66cb8cfa8..4c9cb81d5f9ddce214a4003ed82c85c3e35eac24 100644 (file)
              (set (match_dup 1)
                   (minus:SWI (match_dup 1) (match_dup 0)))])])
 
+;; Under APX NDD, 'sub reg, mem, reg' is valid.
+;; New format for
+;; mov reg0, mem1
+;; sub reg0, mem2, reg0
+;; mov mem2, reg0
+;; to
+;; mov reg0, mem1
+;; sub mem2, reg0
+(define_peephole2
+  [(set (match_operand:SWI 0 "general_reg_operand")
+       (match_operand:SWI 1 "memory_operand"))
+   (parallel [(set (reg:CC FLAGS_REG)
+                  (compare:CC (match_operand:SWI 2 "memory_operand")
+                              (match_dup 0)))
+             (set (match_dup 0)
+                  (minus:SWI (match_dup 2) (match_dup 0)))])
+   (set (match_dup 2) (match_dup 0))]
+  "TARGET_APX_NDD
+   && (TARGET_READ_MODIFY_WRITE || optimize_insn_for_size_p ())
+   && peep2_reg_dead_p (3, operands[0])
+   && !reg_overlap_mentioned_p (operands[0], operands[1])
+   && !reg_overlap_mentioned_p (operands[0], operands[2])"
+  [(set (match_dup 0) (match_dup 1))
+   (parallel [(set (reg:CC FLAGS_REG)
+                  (compare:CC (match_dup 2) (match_dup 0)))
+             (set (match_dup 2)
+                  (minus:SWI (match_dup 2) (match_dup 0)))])])
+
 ;; decl %eax; cmpl $-1, %eax; jne .Lxx; can be optimized into
 ;; subl $1, %eax; jnc .Lxx;
 (define_peephole2
                                           (match_dup 1))
                               (match_dup 0)))])])
 
+;; Under APX NDD, 'adc reg, mem, reg' is valid.
+;;
+;; New format for
+;; mov reg0, mem1
+;; adc reg0, mem2, reg0
+;; mov mem1, reg0
+;; to
+;; mov reg0, mem2
+;; adc mem1, reg0
+(define_peephole2
+  [(set (match_operand:SWI48 0 "general_reg_operand")
+       (match_operand:SWI48 1 "memory_operand"))
+   (parallel [(set (reg:CCC FLAGS_REG)
+                  (compare:CCC
+                    (zero_extend:<DWI>
+                      (plus:SWI48
+                        (plus:SWI48
+                          (match_operator:SWI48 5 "ix86_carry_flag_operator"
+                            [(match_operand 3 "flags_reg_operand")
+                             (const_int 0)])
+                          (match_operand:SWI48 2 "memory_operand"))
+                        (match_dup 0)))
+                    (plus:<DWI>
+                      (match_operator:<DWI> 4 "ix86_carry_flag_operator"
+                        [(match_dup 3) (const_int 0)])
+                      (zero_extend:<DWI> (match_dup 0)))))
+             (set (match_dup 0)
+                  (plus:SWI48 (plus:SWI48 (match_op_dup 5
+                                            [(match_dup 3) (const_int 0)])
+                                          (match_dup 2))
+                              (match_dup 0)))])
+   (set (match_dup 1) (match_dup 0))]
+  "TARGET_APX_NDD
+   && (TARGET_READ_MODIFY_WRITE || optimize_insn_for_size_p ())
+   && peep2_reg_dead_p (3, operands[0])
+   && !reg_overlap_mentioned_p (operands[0], operands[1])
+   && !reg_overlap_mentioned_p (operands[0], operands[2])"
+  [(set (match_dup 0) (match_dup 2))
+   (parallel [(set (reg:CCC FLAGS_REG)
+                  (compare:CCC
+                    (zero_extend:<DWI>
+                      (plus:SWI48
+                        (plus:SWI48
+                          (match_op_dup 5
+                            [(match_dup 3) (const_int 0)])
+                          (match_dup 1))
+                        (match_dup 0)))
+                    (plus:<DWI>
+                      (match_op_dup 4
+                        [(match_dup 3) (const_int 0)])
+                      (zero_extend:<DWI> (match_dup 0)))))
+             (set (match_dup 1)
+                  (plus:SWI48 (plus:SWI48 (match_op_dup 5
+                                            [(match_dup 3) (const_int 0)])
+                                          (match_dup 1))
+                              (match_dup 0)))])])
+
+;; New format for
+;; mov reg0, mem1
+;; adc reg0, mem2, reg0
+;; mov mem2, reg0
+;; to
+;; mov reg0, mem1
+;; adc mem2, reg0
+(define_peephole2
+  [(set (match_operand:SWI48 0 "general_reg_operand")
+       (match_operand:SWI48 1 "memory_operand"))
+   (parallel [(set (reg:CCC FLAGS_REG)
+                  (compare:CCC
+                    (zero_extend:<DWI>
+                      (plus:SWI48
+                        (plus:SWI48
+                          (match_operator:SWI48 5 "ix86_carry_flag_operator"
+                            [(match_operand 3 "flags_reg_operand")
+                             (const_int 0)])
+                          (match_operand:SWI48 2 "memory_operand"))
+                        (match_dup 0)))
+                    (plus:<DWI>
+                      (match_operator:<DWI> 4 "ix86_carry_flag_operator"
+                        [(match_dup 3) (const_int 0)])
+                      (zero_extend:<DWI> (match_dup 0)))))
+             (set (match_dup 0)
+                  (plus:SWI48 (plus:SWI48 (match_op_dup 5
+                                            [(match_dup 3) (const_int 0)])
+                                          (match_dup 2))
+                              (match_dup 0)))])
+   (set (match_dup 2) (match_dup 0))]
+  "TARGET_APX_NDD
+   && (TARGET_READ_MODIFY_WRITE || optimize_insn_for_size_p ())
+   && peep2_reg_dead_p (3, operands[0])
+   && !reg_overlap_mentioned_p (operands[0], operands[1])
+   && !reg_overlap_mentioned_p (operands[0], operands[2])"
+  [(set (match_dup 0) (match_dup 1))
+   (parallel [(set (reg:CCC FLAGS_REG)
+                  (compare:CCC
+                    (zero_extend:<DWI>
+                      (plus:SWI48
+                        (plus:SWI48
+                          (match_op_dup 5
+                            [(match_dup 3) (const_int 0)])
+                          (match_dup 2))
+                        (match_dup 0)))
+                    (plus:<DWI>
+                      (match_op_dup 4
+                        [(match_dup 3) (const_int 0)])
+                      (zero_extend:<DWI> (match_dup 0)))))
+             (set (match_dup 2)
+                  (plus:SWI48 (plus:SWI48 (match_op_dup 5
+                                            [(match_dup 3) (const_int 0)])
+                                          (match_dup 2))
+                              (match_dup 0)))])])
+
 (define_peephole2
   [(parallel [(set (reg:CCC FLAGS_REG)
                   (compare:CCC
                                               [(match_dup 3) (const_int 0)]))
                                (match_dup 0)))])])
 
+;; Under APX NDD, 'sbb reg, mem, reg' is valid.
+;;
+;; New format for
+;; mov reg0, mem1
+;; sbb reg0, mem2, reg0
+;; mov mem2, reg0
+;; to
+;; mov reg0, mem1
+;; sbb mem2, reg0
+(define_peephole2
+  [(set (match_operand:SWI48 0 "general_reg_operand")
+       (match_operand:SWI48 1 "memory_operand"))
+   (parallel [(set (reg:CCC FLAGS_REG)
+                  (compare:CCC
+                    (zero_extend:<DWI> (match_operand:SWI48 2 "memory_operand"))
+                    (plus:<DWI>
+                      (match_operator:<DWI> 4 "ix86_carry_flag_operator"
+                        [(match_operand 3 "flags_reg_operand") (const_int 0)])
+                      (zero_extend:<DWI>
+                        (match_dup 0)))))
+             (set (match_dup 0)
+                  (minus:SWI48
+                    (minus:SWI48
+                      (match_dup 2)
+                      (match_operator:SWI48 5 "ix86_carry_flag_operator"
+                        [(match_dup 3) (const_int 0)]))
+                    (match_dup 0)))])
+   (set (match_dup 2) (match_dup 0))]
+  "TARGET_APX_NDD
+   && (TARGET_READ_MODIFY_WRITE || optimize_insn_for_size_p ())
+   && peep2_reg_dead_p (3, operands[0])
+   && !reg_overlap_mentioned_p (operands[0], operands[1])
+   && !reg_overlap_mentioned_p (operands[0], operands[2])"
+  [(set (match_dup 0) (match_dup 1))
+   (parallel [(set (reg:CCC FLAGS_REG)
+                  (compare:CCC
+                    (zero_extend:<DWI> (match_dup 2))
+                    (plus:<DWI> (match_op_dup 4
+                                  [(match_dup 3) (const_int 0)])
+                                (zero_extend:<DWI> (match_dup 0)))))
+             (set (match_dup 2)
+                  (minus:SWI48 (minus:SWI48 (match_dup 2)
+                                            (match_op_dup 5
+                                              [(match_dup 3) (const_int 0)]))
+                               (match_dup 0)))])])
+
 (define_peephole2
   [(set (match_operand:SWI48 6 "general_reg_operand")
        (match_operand:SWI48 7 "memory_operand"))
diff --git a/gcc/testsuite/gcc.target/i386/pr79173-13.c b/gcc/testsuite/gcc.target/i386/pr79173-13.c
new file mode 100644 (file)
index 0000000..7d5818b
--- /dev/null
@@ -0,0 +1,59 @@
+/* PR middle-end/79173 */
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -fno-stack-protector -masm=att -mapxf" } */
+/* { dg-final { scan-assembler-times "addq\t%r\[^\n\r]*, \\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "adcq\t%r\[^\n\r]*, 8\\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "adcq\t%r\[^\n\r]*, 16\\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "adcq\t%r\[^\n\r]*, 24\\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "subq\t%r\[^\n\r]*, \\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "sbbq\t%r\[^\n\r]*, 8\\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "sbbq\t%r\[^\n\r]*, 16\\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "sbbq\t%r\[^\n\r]*, 24\\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "addl\t%e\[^\n\r]*, \\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "adcl\t%e\[^\n\r]*, 4\\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "adcl\t%e\[^\n\r]*, 8\\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "adcl\t%e\[^\n\r]*, 12\\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "subl\t%e\[^\n\r]*, \\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "sbbl\t%e\[^\n\r]*, 4\\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "sbbl\t%e\[^\n\r]*, 8\\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "sbbl\t%e\[^\n\r]*, 12\\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+
+static unsigned long
+uaddc (unsigned long x, unsigned long y, unsigned long carry_in, unsigned long *carry_out)
+{
+  unsigned long r;
+  unsigned long c1 = __builtin_add_overflow (x, y, &r);
+  unsigned long c2 = __builtin_add_overflow (r, carry_in, &r);
+  *carry_out = c1 + c2;
+  return r;
+}
+
+static unsigned long
+usubc (unsigned long x, unsigned long y, unsigned long carry_in, unsigned long *carry_out)
+{
+  unsigned long r;
+  unsigned long c1 = __builtin_sub_overflow (x, y, &r);
+  unsigned long c2 = __builtin_sub_overflow (r, carry_in, &r);
+  *carry_out = c1 + c2;
+  return r;
+}
+
+void
+foo (unsigned long *p, unsigned long *q)
+{
+  unsigned long c;
+  p[0] = uaddc (p[0], q[0], 0, &c);
+  p[1] = uaddc (p[1], q[1], c, &c);
+  p[2] = uaddc (p[2], q[2], c, &c);
+  p[3] = uaddc (p[3], q[3], c, &c);
+}
+
+void
+bar (unsigned long *p, unsigned long *q)
+{
+  unsigned long c;
+  p[0] = usubc (p[0], q[0], 0, &c);
+  p[1] = usubc (p[1], q[1], c, &c);
+  p[2] = usubc (p[2], q[2], c, &c);
+  p[3] = usubc (p[3], q[3], c, &c);
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr79173-14.c b/gcc/testsuite/gcc.target/i386/pr79173-14.c
new file mode 100644 (file)
index 0000000..de85051
--- /dev/null
@@ -0,0 +1,59 @@
+/* PR middle-end/79173 */
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -fno-stack-protector -masm=att -mapxf" } */
+/* { dg-final { scan-assembler-times "addq\t%r\[^\n\r]*, \\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "adcq\t%r\[^\n\r]*, 8\\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "adcq\t%r\[^\n\r]*, 16\\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "adcq\t%r\[^\n\r]*, 24\\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "subq\t%r\[^\n\r]*, \\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "sbbq\t%r\[^\n\r]*, 8\\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "sbbq\t%r\[^\n\r]*, 16\\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "sbbq\t%r\[^\n\r]*, 24\\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "addl\t%e\[^\n\r]*, \\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "adcl\t%e\[^\n\r]*, 4\\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "adcl\t%e\[^\n\r]*, 8\\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "adcl\t%e\[^\n\r]*, 12\\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "subl\t%e\[^\n\r]*, \\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "sbbl\t%e\[^\n\r]*, 4\\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "sbbl\t%e\[^\n\r]*, 8\\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "sbbl\t%e\[^\n\r]*, 12\\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+
+static unsigned long
+uaddc (unsigned long x, unsigned long y, _Bool carry_in, _Bool *carry_out)
+{
+  unsigned long r;
+  _Bool c1 = __builtin_add_overflow (x, y, &r);
+  _Bool c2 = __builtin_add_overflow (r, carry_in, &r);
+  *carry_out = c1 | c2;
+  return r;
+}
+
+static unsigned long
+usubc (unsigned long x, unsigned long y, _Bool carry_in, _Bool *carry_out)
+{
+  unsigned long r;
+  _Bool c1 = __builtin_sub_overflow (x, y, &r);
+  _Bool c2 = __builtin_sub_overflow (r, carry_in, &r);
+  *carry_out = c1 | c2;
+  return r;
+}
+
+void
+foo (unsigned long *p, unsigned long *q)
+{
+  _Bool c;
+  p[0] = uaddc (p[0], q[0], 0, &c);
+  p[1] = uaddc (p[1], q[1], c, &c);
+  p[2] = uaddc (p[2], q[2], c, &c);
+  p[3] = uaddc (p[3], q[3], c, &c);
+}
+
+void
+bar (unsigned long *p, unsigned long *q)
+{
+  _Bool c;
+  p[0] = usubc (p[0], q[0], 0, &c);
+  p[1] = usubc (p[1], q[1], c, &c);
+  p[2] = usubc (p[2], q[2], c, &c);
+  p[3] = usubc (p[3], q[3], c, &c);
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr79173-15.c b/gcc/testsuite/gcc.target/i386/pr79173-15.c
new file mode 100644 (file)
index 0000000..c3017f7
--- /dev/null
@@ -0,0 +1,61 @@
+/* PR middle-end/79173 */
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -fno-stack-protector -masm=att -mapxf" } */
+/* { dg-final { scan-assembler-times "addq\t%r\[^\n\r]*, \\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "adcq\t%r\[^\n\r]*, 8\\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "adcq\t%r\[^\n\r]*, 16\\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "adcq\t%r\[^\n\r]*, 24\\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "subq\t%r\[^\n\r]*, \\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "sbbq\t%r\[^\n\r]*, 8\\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "sbbq\t%r\[^\n\r]*, 16\\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "sbbq\t%r\[^\n\r]*, 24\\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "addl\t%e\[^\n\r]*, \\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "adcl\t%e\[^\n\r]*, 4\\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "adcl\t%e\[^\n\r]*, 8\\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "adcl\t%e\[^\n\r]*, 12\\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "subl\t%e\[^\n\r]*, \\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "sbbl\t%e\[^\n\r]*, 4\\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "sbbl\t%e\[^\n\r]*, 8\\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "sbbl\t%e\[^\n\r]*, 12\\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+
+static unsigned long
+uaddc (unsigned long x, unsigned long y, unsigned long carry_in, unsigned long *carry_out)
+{
+  unsigned long r;
+  unsigned long c1 = __builtin_add_overflow (x, y, &r);
+  unsigned long c2 = __builtin_add_overflow (r, carry_in, &r);
+  *carry_out = c1 + c2;
+  return r;
+}
+
+static unsigned long
+usubc (unsigned long x, unsigned long y, unsigned long carry_in, unsigned long *carry_out)
+{
+  unsigned long r;
+  unsigned long c1 = __builtin_sub_overflow (x, y, &r);
+  unsigned long c2 = __builtin_sub_overflow (r, carry_in, &r);
+  *carry_out = c1 + c2;
+  return r;
+}
+
+unsigned long
+foo (unsigned long *p, unsigned long *q)
+{
+  unsigned long c;
+  p[0] = uaddc (p[0], q[0], 0, &c);
+  p[1] = uaddc (p[1], q[1], c, &c);
+  p[2] = uaddc (p[2], q[2], c, &c);
+  p[3] = uaddc (p[3], q[3], c, &c);
+  return c;
+}
+
+unsigned long
+bar (unsigned long *p, unsigned long *q)
+{
+  unsigned long c;
+  p[0] = usubc (p[0], q[0], 0, &c);
+  p[1] = usubc (p[1], q[1], c, &c);
+  p[2] = usubc (p[2], q[2], c, &c);
+  p[3] = usubc (p[3], q[3], c, &c);
+  return c;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr79173-16.c b/gcc/testsuite/gcc.target/i386/pr79173-16.c
new file mode 100644 (file)
index 0000000..91062fb
--- /dev/null
@@ -0,0 +1,61 @@
+/* PR middle-end/79173 */
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -fno-stack-protector -masm=att -mapxf" } */
+/* { dg-final { scan-assembler-times "addq\t%r\[^\n\r]*, \\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "adcq\t%r\[^\n\r]*, 8\\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "adcq\t%r\[^\n\r]*, 16\\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "adcq\t%r\[^\n\r]*, 24\\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "subq\t%r\[^\n\r]*, \\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "sbbq\t%r\[^\n\r]*, 8\\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "sbbq\t%r\[^\n\r]*, 16\\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "sbbq\t%r\[^\n\r]*, 24\\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "addl\t%e\[^\n\r]*, \\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "adcl\t%e\[^\n\r]*, 4\\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "adcl\t%e\[^\n\r]*, 8\\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "adcl\t%e\[^\n\r]*, 12\\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "subl\t%e\[^\n\r]*, \\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "sbbl\t%e\[^\n\r]*, 4\\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "sbbl\t%e\[^\n\r]*, 8\\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "sbbl\t%e\[^\n\r]*, 12\\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+
+static unsigned long
+uaddc (unsigned long x, unsigned long y, _Bool carry_in, _Bool *carry_out)
+{
+  unsigned long r;
+  _Bool c1 = __builtin_add_overflow (x, y, &r);
+  _Bool c2 = __builtin_add_overflow (r, carry_in, &r);
+  *carry_out = c1 ^ c2;
+  return r;
+}
+
+static unsigned long
+usubc (unsigned long x, unsigned long y, _Bool carry_in, _Bool *carry_out)
+{
+  unsigned long r;
+  _Bool c1 = __builtin_sub_overflow (x, y, &r);
+  _Bool c2 = __builtin_sub_overflow (r, carry_in, &r);
+  *carry_out = c1 ^ c2;
+  return r;
+}
+
+_Bool
+foo (unsigned long *p, unsigned long *q)
+{
+  _Bool c;
+  p[0] = uaddc (p[0], q[0], 0, &c);
+  p[1] = uaddc (p[1], q[1], c, &c);
+  p[2] = uaddc (p[2], q[2], c, &c);
+  p[3] = uaddc (p[3], q[3], c, &c);
+  return c;
+}
+
+_Bool
+bar (unsigned long *p, unsigned long *q)
+{
+  _Bool c;
+  p[0] = usubc (p[0], q[0], 0, &c);
+  p[1] = usubc (p[1], q[1], c, &c);
+  p[2] = usubc (p[2], q[2], c, &c);
+  p[3] = usubc (p[3], q[3], c, &c);
+  return c;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr79173-17.c b/gcc/testsuite/gcc.target/i386/pr79173-17.c
new file mode 100644 (file)
index 0000000..e27f4b9
--- /dev/null
@@ -0,0 +1,32 @@
+/* PR middle-end/79173 */
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -fno-stack-protector -masm=att -mapxf" } */
+/* { dg-final { scan-assembler-times "addq\t%r\[^\n\r]*, \\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "adcq\t%r\[^\n\r]*, 8\\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "adcq\t%r\[^\n\r]*, 16\\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "adcq\t%r\[^\n\r]*, 24\\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "addl\t%e\[^\n\r]*, \\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "adcl\t%e\[^\n\r]*, 4\\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "adcl\t%e\[^\n\r]*, 8\\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "adcl\t%e\[^\n\r]*, 12\\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+
+static unsigned long
+uaddc (unsigned long x, unsigned long y, unsigned long carry_in, unsigned long *carry_out)
+{
+  unsigned long r = x + y;
+  unsigned long c1 = r < x;
+  r += carry_in;
+  unsigned long c2 = r < carry_in;
+  *carry_out = c1 + c2;
+  return r;
+}
+
+void
+foo (unsigned long *p, unsigned long *q)
+{
+  unsigned long c;
+  p[0] = uaddc (p[0], q[0], 0, &c);
+  p[1] = uaddc (p[1], q[1], c, &c);
+  p[2] = uaddc (p[2], q[2], c, &c);
+  p[3] = uaddc (p[3], q[3], c, &c);
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr79173-18.c b/gcc/testsuite/gcc.target/i386/pr79173-18.c
new file mode 100644 (file)
index 0000000..2728ae7
--- /dev/null
@@ -0,0 +1,33 @@
+/* PR middle-end/79173 */
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -fno-stack-protector -masm=att -mapxf" } */
+/* { dg-final { scan-assembler-times "addq\t%r\[^\n\r]*, \\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "adcq\t%r\[^\n\r]*, 8\\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "adcq\t%r\[^\n\r]*, 16\\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "adcq\t%r\[^\n\r]*, 24\\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "addl\t%e\[^\n\r]*, \\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "adcl\t%e\[^\n\r]*, 4\\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "adcl\t%e\[^\n\r]*, 8\\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "adcl\t%e\[^\n\r]*, 12\\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+
+static unsigned long
+uaddc (unsigned long x, unsigned long y, unsigned long carry_in, unsigned long *carry_out)
+{
+  unsigned long r = x + y;
+  unsigned long c1 = r < x;
+  r += carry_in;
+  unsigned long c2 = r < carry_in;
+  *carry_out = c1 + c2;
+  return r;
+}
+
+unsigned long
+foo (unsigned long *p, unsigned long *q)
+{
+  unsigned long c;
+  p[0] = uaddc (p[0], q[0], 0, &c);
+  p[1] = uaddc (p[1], q[1], c, &c);
+  p[2] = uaddc (p[2], q[2], c, &c);
+  p[3] = uaddc (p[3], q[3], c, &c);
+  return c;
+}