combine: Do another check before splitting a parallel (PR86771)
authorSegher Boessenkool <segher@kernel.crashing.org>
Wed, 22 Aug 2018 13:41:05 +0000 (15:41 +0200)
committerSegher Boessenkool <segher@gcc.gnu.org>
Wed, 22 Aug 2018 13:41:05 +0000 (15:41 +0200)
When combine splits a resulting parallel into its two SETs, it has to
place one at i2, and the other stays at i3.  This does not work if the
destination of the SET that will be placed at i2 is modified between
i2 and i3.  This patch fixes it.

* combine.c (try_combine): Do not allow splitting a resulting PARALLEL
of two SETs into those two SETs, one to be placed at i2, if that SETs
destination is modified between i2 and i3.

From-SVN: r263776

gcc/ChangeLog
gcc/combine.c

index c5515e4c038a742707d8c6ff7694b761c7f8be70..fb267ab40ad9ac5080b9590ac32e676f6b8a5f40 100644 (file)
@@ -1,3 +1,9 @@
+2018-08-22  Segher Boessenkool  <segher@kernel.crashing.org>
+
+       * combine.c (try_combine): Do not allow splitting a resulting PARALLEL
+       of two SETs into those two SETs, one to be placed at i2, if that SETs
+       destination is modified between i2 and i3.
+
 2018-08-22  Richard Sandiford  <richard.sandiford@arm.com>
 
        PR tree-optimization/86725
index 7a0abf2f7433603be7d4d75c8f550625cde35c75..d322614ed577971535feea08de5f0b3f2e08770d 100644 (file)
@@ -4036,7 +4036,10 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
      other insns to combine, but the destination of that SET is still live.
 
      Also do this if we started with two insns and (at least) one of the
-     resulting sets is a noop; this noop will be deleted later.  */
+     resulting sets is a noop; this noop will be deleted later.
+
+     Also do this if we started with two insns neither of which was a simple
+     move.  */
 
   else if (insn_code_number < 0 && asm_noperands (newpat) < 0
           && GET_CODE (newpat) == PARALLEL
@@ -4066,13 +4069,15 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
         one which uses any regs/memory set in between i2 and i3 can't
         be first.  The PARALLEL might also have been pre-existing in i3,
         so we need to make sure that we won't wrongly hoist a SET to i2
-        that would conflict with a death note present in there.  */
+        that would conflict with a death note present in there, or would
+        have its dest modified between i2 and i3.  */
       if (!modified_between_p (SET_SRC (set1), i2, i3)
          && !(REG_P (SET_DEST (set1))
               && find_reg_note (i2, REG_DEAD, SET_DEST (set1)))
          && !(GET_CODE (SET_DEST (set1)) == SUBREG
               && find_reg_note (i2, REG_DEAD,
                                 SUBREG_REG (SET_DEST (set1))))
+         && !modified_between_p (SET_DEST (set1), i2, i3)
          && (!HAVE_cc0 || !reg_referenced_p (cc0_rtx, set0))
          /* If I3 is a jump, ensure that set0 is a jump so that
             we do not create invalid RTL.  */
@@ -4088,6 +4093,7 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
               && !(GET_CODE (SET_DEST (set0)) == SUBREG
                    && find_reg_note (i2, REG_DEAD,
                                      SUBREG_REG (SET_DEST (set0))))
+              && !modified_between_p (SET_DEST (set0), i2, i3)
               && (!HAVE_cc0 || !reg_referenced_p (cc0_rtx, set1))
               /* If I3 is a jump, ensure that set1 is a jump so that
                  we do not create invalid RTL.  */