From: Jakub Jelinek Date: Tue, 7 Apr 2020 19:30:12 +0000 (+0200) Subject: combine: Fix split_i2i3 ICE [PR94291] X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=c23c899aedf11069e992eed7358802b262d62f98;p=gcc.git 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 [ ]) (const_int 0 [0]))) (set (reg:SI 125) (reg:SI 121 [ ])) ]) "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 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. --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a1ab9fb4ef3..12803e90b0a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2020-04-07 Jakub Jelinek + + 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 PR middle-end/94479 diff --git a/gcc/combine.c b/gcc/combine.c index 58366a6d331..cff76cd3303 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 71b5a14bcbe..3cbf891d58d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2020-04-07 Jakub Jelinek + + PR rtl-optimization/94291 + PR rtl-optimization/84169 + * gcc.dg/pr94291.c: New test. + 2020-04-07 Richard Biener 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 00000000000..7daa2b01166 --- /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; +}