aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2020-04-07 21:30:12 +0200
committerJakub Jelinek <jakub@redhat.com>2020-04-07 21:30:12 +0200
commitc23c899aedf11069e992eed7358802b262d62f98 (patch)
tree1e7c842bfc7d60ae247ba8287765a417c8feb402
parent88e508f9f112acd07d0c49c53589160db8c85fcd (diff)
downloadgcc-c23c899aedf11069e992eed7358802b262d62f98.zip
gcc-c23c899aedf11069e992eed7358802b262d62f98.tar.gz
gcc-c23c899aedf11069e992eed7358802b262d62f98.tar.bz2
combine: Fix split_i2i3 ICE [PR94291]
The following testcase ICEs on armv7hl-linux-gnueabi. try_combine is called on: (gdb) p debug_rtx (i3) (insn 20 12 22 2 (set (mem/c:SI (plus:SI (reg/f:SI 102 sfp) (const_int -4 [0xfffffffffffffffc])) [1 x+0 S4 A32]) (reg:SI 125)) "pr94291.c":7:8 241 {*arm_movsi_insn} (expr_list:REG_DEAD (reg:SI 125) (nil))) (gdb) p debug_rtx (i2) (insn 12 7 20 2 (parallel [ (set (reg:CC 100 cc) (compare:CC (reg:SI 121 [ <retval> ]) (const_int 0 [0]))) (set (reg:SI 125) (reg:SI 121 [ <retval> ])) ]) "pr94291.c":7:8 248 {*movsi_compare0} (expr_list:REG_UNUSED (reg:CC 100 cc) (nil))) and tries to recognize cc = r121 cmp 0; [sfp-4] = r121 parallel, but that isn't recognized, so it splits it into two: split_i2i3 [sfp-4] = r121 followed by cc = r121 cmp 0 which is recognized, but ICEs because the code below insist that the SET_DEST of newi2pat (or first set in PARALLEL thereof) must be a REG or SUBREG of REG, but it is a MEM in this case. I don't see any condition that would guarantee that, perhaps for the swap_i2i3 case it was somehow guaranteed. As the code just wants to update LOG_LINKS and LOG_LINKS are only for registers, not for MEM or anything else, the patch just doesn't update those if it isn't a REG or SUBREG of REG. 2020-04-07 Jakub Jelinek <jakub@redhat.com> PR rtl-optimization/94291 PR rtl-optimization/84169 * combine.c (try_combine): For split_i2i3, don't assume SET_DEST must be a REG or SUBREG of REG; if it is not one of these, don't update LOG_LINKs. * gcc.dg/pr94291.c: New test.
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/combine.c42
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.dg/pr94291.c14
4 files changed, 51 insertions, 19 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index a1ab9fb..12803e9 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2020-04-07 Jakub Jelinek <jakub@redhat.com>
+
+ PR rtl-optimization/94291
+ PR rtl-optimization/84169
+ * combine.c (try_combine): For split_i2i3, don't assume SET_DEST
+ must be a REG or SUBREG of REG; if it is not one of these, don't
+ update LOG_LINKs.
+
2020-04-07 Richard Biener <rguenther@suse.de>
PR middle-end/94479
diff --git a/gcc/combine.c b/gcc/combine.c
index 58366a6..cff76cd 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -4351,25 +4351,29 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
if (GET_CODE (x) == PARALLEL)
x = XVECEXP (newi2pat, 0, 0);
- /* It can only be a SET of a REG or of a SUBREG of a REG. */
- unsigned int regno = reg_or_subregno (SET_DEST (x));
-
- bool done = false;
- for (rtx_insn *insn = NEXT_INSN (i3);
- !done
- && insn
- && NONDEBUG_INSN_P (insn)
- && BLOCK_FOR_INSN (insn) == this_basic_block;
- insn = NEXT_INSN (insn))
- {
- struct insn_link *link;
- FOR_EACH_LOG_LINK (link, insn)
- if (link->insn == i3 && link->regno == regno)
- {
- link->insn = i2;
- done = true;
- break;
- }
+ if (REG_P (SET_DEST (x))
+ || (GET_CODE (SET_DEST (x)) == SUBREG
+ && REG_P (SUBREG_REG (SET_DEST (x)))))
+ {
+ unsigned int regno = reg_or_subregno (SET_DEST (x));
+
+ bool done = false;
+ for (rtx_insn *insn = NEXT_INSN (i3);
+ !done
+ && insn
+ && NONDEBUG_INSN_P (insn)
+ && BLOCK_FOR_INSN (insn) == this_basic_block;
+ insn = NEXT_INSN (insn))
+ {
+ struct insn_link *link;
+ FOR_EACH_LOG_LINK (link, insn)
+ if (link->insn == i3 && link->regno == regno)
+ {
+ link->insn = i2;
+ done = true;
+ break;
+ }
+ }
}
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 71b5a14..3cbf891 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2020-04-07 Jakub Jelinek <jakub@redhat.com>
+
+ PR rtl-optimization/94291
+ PR rtl-optimization/84169
+ * gcc.dg/pr94291.c: New test.
+
2020-04-07 Richard Biener <rguenther@suse.de>
PR middle-end/94479
diff --git a/gcc/testsuite/gcc.dg/pr94291.c b/gcc/testsuite/gcc.dg/pr94291.c
new file mode 100644
index 0000000..7daa2b0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr94291.c
@@ -0,0 +1,14 @@
+/* PR rtl-optimization/94291 */
+/* { dg-do compile } */
+/* { dg-options "-Og" } */
+
+unsigned a;
+
+unsigned
+foo (void)
+{
+ unsigned x
+ = (__builtin_sub_overflow ((long long) a, 0, &x)
+ ? 1 : (__INTPTR_TYPE__) __builtin_memmove (&x, foo, 1));
+ return a;
+}