On Sun, Oct 22, 2017 at 08:04:28PM +0200, Uros Bizjak wrote:
> Hello!
> 
> In PR 82628 Jakub figured out that insn patterns that consume carry
> flag were not 100% correct. Due to this issue, combine is able to
> simplify various CC_REG propagations that result in invalid code.
> 
> Attached patch fixes (well, mitigates) the above problem by splitting
> the double-mode compare after the reload, in the same way other
> *_doubleword patterns are handled from "the beginning of the time".

I'm afraid this is going to haunt us sooner or later, combine isn't the
only pass that uses simplify-rtx.c infrastructure heavily and when we lie
in the RTL pattern, eventually something will be simplified wrongly.

So, at least we'd need to use UNSPEC for the pattern, like (only lightly
tested so far) below.

I'm not sure the double-word pattern is a win though, it causes PR82662
you've filed (the problem is that during ifcvt because of the double-word
comparison the condition is canonicalized as (lt (reg:TI) (reg:TI)) and
there is no instruction in the MD that would take such arguments, there
are only instructions that compare flags registers.
If you look at say normal DImode comparisons, it is the same thing,
ifcvt also can't do anything with those, the reason they work is that we
have a cstoredi4 optab (for 64-bit), but don't have a cstoreti4 optab.
So, we'd need that (and only handle the GE/GEU/LT/LTU + the others that can
be handled by swapping the operands).
I think the double-word pattern has other issues, it will result in RA not
knowing in detail what is going on and thus can at least reserve one extra
register that otherwise would not be needed.  The reason we have the
doubleword patterns elsewhere is that splitting double-word early makes it
harder/impossible for STV to use SSE registers; in this case we don't have
something reasonable to expand to anyway, we always split.

The alternative I have is the patch attached in the PR, if the unrelated
addcarry/subborrow changes are removed, then it doesn't regress anything,
the pr50038.c FAIL is from some other earlier change even on vanilla
branch and pr67317-* FAILs were caused by the addcarry/subborrow changes,
will look at those in detail.

2017-10-23  Jakub Jelinek  <ja...@redhat.com>

        PR target/82628
        * config/i386/i386.md (UNSPEC_SBB): New unspec.
        (cmp<dwi>_doubleword): Use unspec instead of compare.
        (sub<mode>3_carry_ccgz): Use unspec instead of compare.

--- gcc/config/i386/i386.md.jj  2017-10-23 10:13:05.462218947 +0200
+++ gcc/config/i386/i386.md     2017-10-23 11:07:55.470376791 +0200
@@ -112,6 +112,7 @@ (define_c_enum "unspec" [
   UNSPEC_STOS
   UNSPEC_PEEPSIB
   UNSPEC_INSN_FALSE_DEP
+  UNSPEC_SBB
 
   ;; For SSE/MMX support:
   UNSPEC_FIX_NOTRUNC
@@ -1285,11 +1286,10 @@ (define_insn_and_split "cmp<dwi>_doublew
   [(set (reg:CC FLAGS_REG)
        (compare:CC (match_dup 1) (match_dup 2)))
    (parallel [(set (reg:CCGZ FLAGS_REG)
-                  (compare: CCGZ
-                    (match_dup 4)
-                    (plus:DWIH
-                      (ltu:DWIH (reg:CC FLAGS_REG) (const_int 0))
-                      (match_dup 5))))
+                  (unspec:CCGZ [(match_dup 4)
+                                (match_dup 5)
+                                (ltu:DWIH (reg:CC FLAGS_REG) (const_int 0))]
+                   UNSPEC_SBB))
              (clobber (match_dup 3))])]
   "split_double_mode (<DWI>mode, &operands[0], 3, &operands[0], 
&operands[3]);")
 
@@ -6911,13 +6911,18 @@ (define_insn "*subsi3_carry_zext"
    (set_attr "pent_pair" "pu")
    (set_attr "mode" "SI")])
 
+;; The sign flag is set from the
+;; (compare (match_dup 1) (plus:DWIH (ltu:DWIH ...) (match_dup 2)))
+;; result, the overflow flag likewise, but the overflow flag is also
+;; set if the (plus:DWIH (ltu:DWIH ...) (match_dup 2)) overflows.
+;; The borrow flag can be modelled, but differently from SF and OF
+;; and is quite difficult to handle.
 (define_insn "*sub<mode>3_carry_ccgz"
   [(set (reg:CCGZ FLAGS_REG)
-       (compare:CCGZ
-         (match_operand:DWIH 1 "register_operand" "0")
-         (plus:DWIH
-           (ltu:DWIH (reg:CC FLAGS_REG) (const_int 0))
-           (match_operand:DWIH 2 "x86_64_general_operand" "rme"))))
+       (unspec:CCGZ [(match_operand:DWIH 1 "register_operand" "0")
+                     (match_operand:DWIH 2 "x86_64_general_operand" "rme")
+                     (ltu:DWIH (reg:CC FLAGS_REG) (const_int 0))]
+                    UNSPEC_SBB))
    (clobber (match_scratch:DWIH 0 "=r"))]
   ""
   "sbb{<imodesuffix>}\t{%2, %0|%0, %2}"


        Jakub

Reply via email to