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"

Reply via email to