https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93141

--- Comment #3 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Untested fix, though this is just about double-word uaddv4, would be good to
handle double-word usubv4, addv4 and subv4 similarly.

--- gcc/config/i386/i386.md.jj  2020-01-03 11:10:43.839511446 +0100
+++ gcc/config/i386/i386.md     2020-01-03 17:05:51.435808734 +0100
@@ -1036,6 +1036,9 @@
 (define_mode_iterator DWI [(DI "!TARGET_64BIT")
                           (TI "TARGET_64BIT")])

+;; SWI and DWI together.
+(define_mode_iterator SWIDWI [QI HI SI DI (TI "TARGET_64BIT")])
+
 ;; GET_MODE_SIZE for selected modes.  As GET_MODE_SIZE is not
 ;; compile time constant, it is faster to use <MODE_SIZE> than
 ;; GET_MODE_SIZE (<MODE>mode).  For XFmode which depends on
@@ -6121,12 +6124,12 @@
 (define_expand "uaddv<mode>4"
   [(parallel [(set (reg:CCC FLAGS_REG)
                   (compare:CCC
-                    (plus:SWI
-                      (match_operand:SWI 1 "nonimmediate_operand")
-                      (match_operand:SWI 2 "<general_operand>"))
+                    (plus:SWIDWI
+                      (match_operand:SWIDWI 1 "nonimmediate_operand")
+                      (match_operand:SWIDWI 2 "<general_operand>"))
                     (match_dup 1)))
-             (set (match_operand:SWI 0 "register_operand")
-                  (plus:SWI (match_dup 1) (match_dup 2)))])
+             (set (match_operand:SWIDWI 0 "register_operand")
+                  (plus:SWIDWI (match_dup 1) (match_dup 2)))])
    (set (pc) (if_then_else
               (ltu (reg:CCC FLAGS_REG) (const_int 0))
               (label_ref (match_operand 3))
@@ -6885,6 +6888,49 @@
   [(set_attr "type" "alu")
    (set_attr "mode" "SI")])

+(define_insn_and_split "*add<dwi>3_doubleword_cc_overflow_1"
+  [(set (reg:CCC FLAGS_REG)
+       (compare:CCC
+         (plus:<DWI>
+           (match_operand:<DWI> 1 "nonimmediate_operand" "%0,0")
+           (match_operand:<DWI> 2 "x86_64_hilo_general_operand" "r<di>,o"))
+         (match_dup 1)))
+   (set (match_operand:<DWI> 0 "nonimmediate_operand" "=ro,r")
+       (plus:<DWI> (match_dup 1) (match_dup 2)))]
+  "ix86_binary_operator_ok (PLUS, <DWI>mode, operands)"
+  "#"
+  "reload_completed"
+  [(parallel [(set (reg:CCC FLAGS_REG)
+                  (compare:CCC
+                    (plus:DWIH (match_dup 1) (match_dup 2))
+                    (match_dup 1)))
+             (set (match_dup 0)
+                  (plus:DWIH (match_dup 1) (match_dup 2)))])
+   (parallel [(set (reg:CCC FLAGS_REG)
+                  (compare:CCC
+                    (zero_extend:<DWI>
+                      (plus:DWIH
+                        (plus:DWIH
+                          (ltu:DWIH (reg:CC FLAGS_REG) (const_int 0))
+                          (match_dup 4))
+                        (match_dup 5)))
+                    (plus:<DWI>
+                      (zero_extend:<DWI> (match_dup 5))
+                      (ltu:<DWI> (reg:CC FLAGS_REG) (const_int 0)))))
+             (set (match_dup 3)
+                  (plus:DWIH
+                    (plus:DWIH (ltu:DWIH (reg:CC FLAGS_REG) (const_int 0))
+                               (match_dup 4))
+                    (match_dup 5)))])]
+{
+  split_double_mode (<DWI>mode, &operands[0], 3, &operands[0], &operands[3]);
+  if (operands[2] == const0_rtx)
+    {
+      emit_insn (gen_addcarry<mode>_0 (operands[3], operands[4],
operands[5]));
+      DONE;
+    }
+})
+
 ;; x == 0 with zero flag test can be done also as x < 1U with carry flag
 ;; test, where the latter is preferrable if we have some carry consuming
 ;; instruction.

Reply via email to