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.
This commit is contained in:
parent
88e508f9f1
commit
c23c899aed
@ -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
|
||||
|
||||
@ -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))
|
||||
if (REG_P (SET_DEST (x))
|
||||
|| (GET_CODE (SET_DEST (x)) == SUBREG
|
||||
&& REG_P (SUBREG_REG (SET_DEST (x)))))
|
||||
{
|
||||
struct insn_link *link;
|
||||
FOR_EACH_LOG_LINK (link, insn)
|
||||
if (link->insn == i3 && link->regno == regno)
|
||||
{
|
||||
link->insn = i2;
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
14
gcc/testsuite/gcc.dg/pr94291.c
Normal file
14
gcc/testsuite/gcc.dg/pr94291.c
Normal file
@ -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;
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user