ecog: Return 1 from insn_invalid_p if REG_INC reg overlaps some stored reg [PR103775]
The following testcase ICEs on aarch64-linux with -g and assembles with a warning otherwise, because it emits ldrb w0,[x0,16]! instruction which sets the x0 register multiple times. Due to disabled DCE (from -Og) we end up before REE with: (insn 12 39 13 2 (set (reg:SI 1 x1 [orig:93 _2 ] [93]) (zero_extend:SI (mem/c:QI (pre_modify:DI (reg/f:DI 0 x0 [114]) (plus:DI (reg/f:DI 0 x0 [114]) (const_int 16 [0x10]))) [1 u128_1+0 S1 A128]))) "pr103775.c":5:35 117 {*zero_extendqisi2_aarch64} (expr_list:REG_INC (reg/f:DI 0 x0 [114]) (nil))) (insn 13 12 14 2 (set (reg:DI 0 x0 [orig:112 _2 ] [112]) (zero_extend:DI (reg:SI 1 x1 [orig:93 _2 ] [93]))) "pr103775.c":5:16 111 {*zero_extendsidi2_aarch64} (nil)) which is valid but not exactly efficient as x0 is dead after the insn that auto-increments it. REE turns it into: (insn 12 39 44 2 (set (reg:DI 0 x0) (zero_extend:DI (mem/c:QI (pre_modify:DI (reg/f:DI 0 x0 [114]) (plus:DI (reg/f:DI 0 x0 [114]) (const_int 16 [0x10]))) [1 u128_1+0 S1 A128]))) "pr103775.c":5:35 119 {*zero_extendqidi2_aarch64} (expr_list:REG_INC (reg/f:DI 0 x0 [114]) (nil))) (insn 44 12 14 2 (set (reg:DI 1 x1) (reg:DI 0 x0)) "pr103775.c":5:35 -1 (nil)) which is invalid because it sets x0 multiple times, one in SET_DEST of the PATTERN and once in PRE_MODIFY. As perhaps other passes than REE might suffer from it, IMHO it is better to reject this during change validation. 2022-03-26 Jakub Jelinek <jakub@redhat.com> PR rtl-optimization/103775 * recog.cc (check_invalid_inc_dec): New function. (insn_invalid_p): Return 1 if REG_INC operand overlaps any stored REGs. * gcc.dg/pr103775.c: New test.
This commit is contained in:
parent
ff465bd8a0
commit
6459e65376
22
gcc/recog.cc
22
gcc/recog.cc
|
@ -329,6 +329,17 @@ canonicalize_change_group (rtx_insn *insn, rtx x)
|
|||
return false;
|
||||
}
|
||||
|
||||
/* Check if REG_INC argument in *data overlaps a stored REG. */
|
||||
|
||||
static void
|
||||
check_invalid_inc_dec (rtx reg, const_rtx, void *data)
|
||||
{
|
||||
rtx *pinc = (rtx *) data;
|
||||
if (*pinc == NULL_RTX || MEM_P (reg))
|
||||
return;
|
||||
if (reg_overlap_mentioned_p (reg, *pinc))
|
||||
*pinc = NULL_RTX;
|
||||
}
|
||||
|
||||
/* This subroutine of apply_change_group verifies whether the changes to INSN
|
||||
were valid; i.e. whether INSN can still be recognized.
|
||||
|
@ -386,6 +397,17 @@ insn_invalid_p (rtx_insn *insn, bool in_group)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/* Punt if REG_INC argument overlaps some stored REG. */
|
||||
for (rtx link = FIND_REG_INC_NOTE (insn, NULL_RTX);
|
||||
link; link = XEXP (link, 1))
|
||||
if (REG_NOTE_KIND (link) == REG_INC)
|
||||
{
|
||||
rtx reg = XEXP (link, 0);
|
||||
note_stores (insn, check_invalid_inc_dec, ®);
|
||||
if (reg == NULL_RTX)
|
||||
return 1;
|
||||
}
|
||||
|
||||
INSN_CODE (insn) = icode;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
/* PR rtl-optimization/103775 */
|
||||
/* { dg-do assemble { target int128 } } */
|
||||
/* { dg-options "-Og -fno-forward-propagate -free -g" } */
|
||||
|
||||
int
|
||||
foo (char a, short b, int c, __int128 d, char e, short f, int g, __int128 h)
|
||||
{
|
||||
long i = __builtin_clrsbll ((char) h);
|
||||
__builtin_memset ((char *) &h + 4, d, 3);
|
||||
c &= (char) h;
|
||||
return c + i;
|
||||
}
|
Loading…
Reference in New Issue