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".

2017-10-22  Uros Bizjak  <ubiz...@gmail.com>

    PR target/82628
    * config/i386/i386.md (cmp<dwi>_doubleword): New pattern.
    * config/i386/i386.c (ix86_expand_branch) <case E_TImode>:
    Expand with cmp<dwi>_doubleword.

2017-10-22  Uros Bizjak  <ubiz...@gmail.com>
        Jakub Jelinek  <ja...@redhat.com>

    PR target/82628
    * gcc.dg/torture/pr82628.c: New test.

Patch was bootstrapped and regression tested on x86_64-linux-gnu {,-m32}.

Committed to mainline SVN.

Uros.
Index: config/i386/i386.c
===================================================================
--- config/i386/i386.c  (revision 253949)
+++ config/i386/i386.c  (working copy)
@@ -22175,34 +22175,26 @@ ix86_expand_branch (enum rtx_code code, rtx op0, r
        switch (code)
          {
          case LE: case LEU: case GT: case GTU:
-           std::swap (lo[0], lo[1]);
-           std::swap (hi[0], hi[1]);
+           std::swap (op0, op1);
            code = swap_condition (code);
            /* FALLTHRU */
 
          case LT: case LTU: case GE: case GEU:
            {
-             rtx (*cmp_insn) (rtx, rtx);
-             rtx (*sbb_insn) (rtx, rtx, rtx);
+             rtx (*cmp_insn) (rtx, rtx, rtx);
 
              if (TARGET_64BIT)
-               cmp_insn = gen_cmpdi_1, sbb_insn = gen_subdi3_carry_ccgz;
+               cmp_insn = gen_cmpti_doubleword;
              else
-               cmp_insn = gen_cmpsi_1, sbb_insn = gen_subsi3_carry_ccgz;
+               cmp_insn = gen_cmpdi_doubleword;
 
-             if (!nonimmediate_operand (lo[0], submode))
-               lo[0] = force_reg (submode, lo[0]);
-             if (!x86_64_general_operand (lo[1], submode))
-               lo[1] = force_reg (submode, lo[1]);
+             if (!register_operand (op0, mode))
+               op0 = force_reg (mode, op0);
+             if (!x86_64_hilo_general_operand (op1, mode))
+               op1 = force_reg (mode, op1);
 
-             if (!register_operand (hi[0], submode))
-               hi[0] = force_reg (submode, hi[0]);
-             if (!x86_64_general_operand (hi[1], submode))
-               hi[1] = force_reg (submode, hi[1]);
+             emit_insn (cmp_insn (gen_rtx_SCRATCH (mode), op0, op1));
 
-             emit_insn (cmp_insn (lo[0], lo[1]));
-             emit_insn (sbb_insn (gen_rtx_SCRATCH (submode), hi[0], hi[1]));
-
              tmp = gen_rtx_REG (CCGZmode, FLAGS_REG);
 
              ix86_expand_branch (code, tmp, const0_rtx, label);
Index: config/i386/i386.md
===================================================================
--- config/i386/i386.md (revision 253949)
+++ config/i386/i386.md (working copy)
@@ -1262,6 +1262,26 @@
        (compare:CC (match_operand:SWI48 0 "nonimmediate_operand")
                    (match_operand:SWI48 1 "<general_operand>")))])
 
+(define_insn_and_split "cmp<dwi>_doubleword"
+  [(set (reg:CCGZ FLAGS_REG)
+       (compare:CCGZ
+         (match_operand:<DWI> 1 "register_operand" "0")
+         (match_operand:<DWI> 2 "x86_64_hilo_general_operand" "ro<di>")))
+   (clobber (match_scratch:<DWI> 0 "=r"))]
+  ""
+  "#"
+  "reload_completed"
+  [(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))))
+             (clobber (match_dup 3))])]
+  "split_double_mode (<DWI>mode, &operands[0], 3, &operands[0], 
&operands[3]);")
+
 (define_insn "*cmp<mode>_ccno_1"
   [(set (reg FLAGS_REG)
        (compare (match_operand:SWI 0 "nonimmediate_operand" "<r>,?m<r>")
@@ -6880,7 +6900,7 @@
    (set_attr "pent_pair" "pu")
    (set_attr "mode" "SI")])
 
-(define_insn "sub<mode>3_carry_ccgz"
+(define_insn "*sub<mode>3_carry_ccgz"
   [(set (reg:CCGZ FLAGS_REG)
        (compare:CCGZ
          (match_operand:DWIH 1 "register_operand" "0")
Index: testsuite/gcc.target/i386/pr82628.c
===================================================================
--- testsuite/gcc.target/i386/pr82628.c (nonexistent)
+++ testsuite/gcc.target/i386/pr82628.c (working copy)
@@ -0,0 +1,34 @@
+/* { dg-do run { target ia32 } } */
+/* { dg-options "-Os" } */
+
+void
+__attribute__ ((noipa))
+foo (const char *x)
+{
+  asm volatile ("" : "+g" (x) : : "memory");
+  if (x)
+    __builtin_abort ();
+}
+
+int a, b = 1;
+
+int
+main ()
+{
+  while (1)
+    {
+      unsigned long long d = 18446744073709551615UL;
+      while (1)
+       {
+         int e = b;
+         while (d < 2)
+           foo ("0");
+         if (a)
+           d++;
+         if (b)
+           break;
+       }
+      break;
+    }
+  return 0;
+}

Reply via email to