https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92140
--- Comment #3 from Jakub Jelinek <jakub at gcc dot gnu.org> --- Untested patch that handles tst1 and tst2 and some more, but doesn't handle tst3 yet and is still missing some patterns. Unfortunately, it can result in quite a lot of define_insn_and_split patterns, while for !TARGET_64BIT it is just 9 per one in the source, for TARGET_64BIT 16, and we need always one for eq and one for ne, because those need to be handled quite differently, eq being easier because we don't need to change any other arguments, for ne we need to require the other argument to be a constant that we can change, as we need to negate it. Uros, does this look like a way forward? --- gcc/config/i386/i386.md.jj 2019-09-20 12:25:48.000000000 +0200 +++ gcc/config/i386/i386.md 2019-10-18 10:28:57.953445277 +0200 @@ -1001,6 +1001,9 @@ (define_mode_iterator SWI24 [HI SI]) ;; Single word integer modes. (define_mode_iterator SWI [QI HI SI (DI "TARGET_64BIT")]) +;; The same, for the case where we need to iterate on SWI x SWI +(define_mode_iterator SWIALT [QI HI SI (DI "TARGET_64BIT")]) + ;; Single word integer modes without QImode. (define_mode_iterator SWI248 [HI SI (DI "TARGET_64BIT")]) @@ -6843,6 +6846,100 @@ (define_insn "*addsi3_zext_cc_overflow_2 [(set_attr "type" "alu") (set_attr "mode" "SI")]) +(define_insn_and_split "*add<SWI:mode>3_eq<SWIALT:mode>" + [(set (match_operand:SWI 0 "nonimmediate_operand" "=<SWI:r>m,<SWI:r>") + (plus:SWI + (plus:SWI + (eq:SWI (match_operand:SWIALT 3 "nonimmediate_operand" + "<SWIALT:r>m,<SWIALT:r>m") + (const_int 0)) + (match_operand:SWI 1 "nonimmediate_operand" "%0,0")) + (match_operand:SWI 2 "<SWI:general_operand>" "<SWI:r><SWI:i>,m"))) + (clobber (reg:CC FLAGS_REG))] + "ix86_binary_operator_ok (PLUS, <SWI:MODE>mode, operands)" + "#" + "" + [(set (reg:CC FLAGS_REG) + (compare:CC (match_dup 3) (const_int 1))) + (parallel [(set (match_dup 0) + (plus:SWI + (plus:SWI (ltu:SWI (reg:CC FLAGS_REG) (const_int 0)) + (match_dup 1)) + (match_dup 2))) + (clobber (reg:CC FLAGS_REG))])]) + +(define_insn_and_split "*add<SWI:mode>3_eq<SWIALT:mode>_0" + [(set (match_operand:SWI 0 "nonimmediate_operand" "=<SWI:r>m") + (plus:SWI + (eq:SWI (match_operand:SWIALT 2 "nonimmediate_operand" "<SWIALT:r>m") + (const_int 0)) + (match_operand:SWI 1 "nonimmediate_operand" "0"))) + (clobber (reg:CC FLAGS_REG))] + "ix86_unary_operator_ok (PLUS, <SWI:MODE>mode, operands)" + "#" + "" + [(set (reg:CC FLAGS_REG) + (compare:CC (match_dup 2) (const_int 1))) + (parallel [(set (match_dup 0) + (plus:SWI (ltu:SWI (reg:CC FLAGS_REG) (const_int 0)) + (match_dup 1))) + (clobber (reg:CC FLAGS_REG))])]) + +(define_insn_and_split "*add<SWI:mode>3_ne<SWIALT:mode>_0" + [(set (match_operand:SWI 0 "nonimmediate_operand" "=<SWI:r>m") + (plus:SWI + (ne:SWI (match_operand:SWIALT 2 "nonimmediate_operand" "<SWIALT:r>m") + (const_int 0)) + (match_operand:SWI 1 "nonimmediate_operand" "0"))) + (clobber (reg:CC FLAGS_REG))] + "ix86_unary_operator_ok (PLUS, <SWI:MODE>mode, operands)" + "#" + "" + [(set (reg:CC FLAGS_REG) + (compare:CC (match_dup 2) (const_int 1))) + (parallel [(set (match_dup 0) + (minus:SWI (minus:SWI + (match_dup 1) + (ltu:SWI (reg:CC FLAGS_REG) (const_int 0))) + (const_int -1))) + (clobber (reg:CC FLAGS_REG))])]) + +(define_insn_and_split "*sub<SWI:mode>3_eq<SWIALT:mode>_0" + [(set (match_operand:SWI 0 "nonimmediate_operand" "=<SWI:r>m") + (minus:SWI + (match_operand:SWI 1 "nonimmediate_operand" "0") + (eq:SWI (match_operand:SWIALT 2 "nonimmediate_operand" "<SWIALT:r>m") + (const_int 0)))) + (clobber (reg:CC FLAGS_REG))] + "ix86_unary_operator_ok (MINUS, <SWI:MODE>mode, operands)" + "#" + "" + [(set (reg:CC FLAGS_REG) + (compare:CC (match_dup 2) (const_int 1))) + (parallel [(set (match_dup 0) + (minus:SWI (match_dup 1) + (ltu:SWI (reg:CC FLAGS_REG) (const_int 0)))) + (clobber (reg:CC FLAGS_REG))])]) + +(define_insn_and_split "*sub<SWI:mode>3_ne<SWIALT:mode>_0" + [(set (match_operand:SWI 0 "nonimmediate_operand" "=<SWI:r>m") + (minus:SWI + (match_operand:SWI 1 "nonimmediate_operand" "0") + (ne:SWI (match_operand:SWIALT 2 "nonimmediate_operand" "<SWIALT:r>m") + (const_int 0)))) + (clobber (reg:CC FLAGS_REG))] + "ix86_unary_operator_ok (MINUS, <SWI:MODE>mode, operands)" + "#" + "" + [(set (reg:CC FLAGS_REG) + (compare:CC (match_dup 2) (const_int 1))) + (parallel [(set (match_dup 0) + (plus:SWI (plus:SWI + (ltu:SWI (reg:CC FLAGS_REG) (const_int 0)) + (match_dup 1)) + (const_int -1))) + (clobber (reg:CC FLAGS_REG))])]) + ;; The patterns that match these are at the end of this file. (define_expand "<plusminus_insn>xf3"