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.