This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[committed] Fix can_combine_p (PR target/80125)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: Segher Boessenkool <segher at kernel dot crashing dot org>
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Tue, 21 Mar 2017 15:54:04 +0100
- Subject: [committed] Fix can_combine_p (PR target/80125)
- Authentication-results: sourceware.org; auth=none
- Authentication-results: ext-mx10.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com
- Authentication-results: ext-mx10.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=jakub at redhat dot com
- Dkim-filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 7AF639E616
- Dmarc-filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 7AF639E616
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
Hi!
As mentioned in the PR, combiner sometimes artificially splits a parallel
into two instructions, the first one not really in the insn stream, both
with the same uid and PREV_INSN (i1) == 0 and NEXT_INSN (i1) == i2.
In that case, calling reg_used_between_p (x, y, i1) crashes the compiler,
because it doesn't find i1 by walking from y forward.
Furthermore, the (succ2 && reg_used_between_p (dest, succ, succ2))
test has been already present, so no need to duplicate it.
Bootstrapped/regtested on powerpc64le-linux, approved on IRC by Segher,
committed to trunk.
2017-03-21 Jakub Jelinek <jakub@redhat.com>
Segher Boessenkool <segher@kernel.crashing.org>
PR target/80125
* combine.c (can_combine_p): Revert the 2017-03-20 change, only
check reg_used_between_p between insn and one of succ or succ2
depending on if succ is artificial insn not inserted into insn
stream.
* gcc.target/powerpc/pr80125.c: New test.
--- gcc/combine.c.jj 2017-03-21 07:57:01.000000000 +0100
+++ gcc/combine.c 2017-03-21 11:02:51.170746744 +0100
@@ -1954,15 +1954,20 @@ can_combine_p (rtx_insn *insn, rtx_insn
/* Don't substitute into a non-local goto, this confuses CFG. */
|| (JUMP_P (i3) && find_reg_note (i3, REG_NON_LOCAL_GOTO, NULL_RTX))
/* Make sure that DEST is not used after INSN but before SUCC, or
- between SUCC and SUCC2. */
- || (succ && reg_used_between_p (dest, insn, succ))
- || (succ2 && reg_used_between_p (dest, succ, succ2))
- /* Make sure that DEST is not used after SUCC but before I3. */
+ after SUCC and before SUCC2, or after SUCC2 but before I3. */
|| (!all_adjacent
&& ((succ2
&& (reg_used_between_p (dest, succ2, i3)
|| reg_used_between_p (dest, succ, succ2)))
- || (!succ2 && succ && reg_used_between_p (dest, succ, i3))))
+ || (!succ2 && succ && reg_used_between_p (dest, succ, i3))
+ || (succ
+ /* SUCC and SUCC2 can be split halves from a PARALLEL; in
+ that case SUCC is not in the insn stream, so use SUCC2
+ instead for this test. */
+ && reg_used_between_p (dest, insn,
+ succ2
+ && INSN_UID (succ) == INSN_UID (succ2)
+ ? succ2 : succ))))
/* Make sure that the value that is to be substituted for the register
does not use any registers whose values alter in between. However,
If the insns are adjacent, a use can't cross a set even though we
--- gcc/testsuite/gcc.target/powerpc/pr80125.c.jj 2017-03-21 10:23:31.409808224 +0100
+++ gcc/testsuite/gcc.target/powerpc/pr80125.c 2017-03-21 10:22:23.000000000 +0100
@@ -0,0 +1,23 @@
+/* PR target/80125 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -maltivec" } */
+
+#include <altivec.h>
+
+int a[1];
+
+void
+foo ()
+{
+ vector int b, e, f, g, h, j, n;
+ vector unsigned c, d;
+ f = vec_sums (h, b);
+ vector int i = vec_mergel (f, g);
+ vector int k = vec_mergel (i, j);
+ vector int l = vec_sl (k, c);
+ vector int m = vec_sl (l, d);
+ vector char o;
+ vector int p = vec_perm (m, n, o);
+ e = vec_sra (p, c);
+ vec_st (e, 0, a);
+}
Jakub