PR101260 regcprop: Add mode change check for copy reg

When propagating a multi-word register into an access with a smaller
mode the can_change_mode backend hook is already consulted for the
original register.  This however is also required for the intermediate
copy in copy_regno which might use a different register class.

gcc/ChangeLog:

	PR rtl-optimization/101260
	* regcprop.cc (maybe_mode_change): Invoke mode_change_ok also for
	copy_regno.

gcc/testsuite/ChangeLog:

	PR rtl-optimization/101260
	* gcc.target/s390/pr101260.c: New testcase.
This commit is contained in:
Andreas Krebbel 2022-02-01 13:33:55 +01:00
parent 34afa19d29
commit b9ebf6c330
2 changed files with 65 additions and 1 deletions

View File

@ -426,7 +426,8 @@ maybe_mode_change (machine_mode orig_mode, machine_mode copy_mode,
if (orig_mode == new_mode)
return gen_raw_REG (new_mode, regno);
else if (mode_change_ok (orig_mode, new_mode, regno))
else if (mode_change_ok (orig_mode, new_mode, regno)
&& mode_change_ok (copy_mode, new_mode, copy_regno))
{
int copy_nregs = hard_regno_nregs (copy_regno, copy_mode);
int use_nregs = hard_regno_nregs (copy_regno, new_mode);

View File

@ -0,0 +1,63 @@
/* PR rtl-optimization/101260 */
/* { dg-do run { target s390_useable_hw } } */
/* { dg-options "-O1 -march=z14" } */
/* This used to fail with commit: 5dc1390b41d */
struct a
{
unsigned b:7;
int c;
int d;
short e;
} p, *q = &p;
int f, g, h, i, r, s;
static short j[8][1][6] = { };
char k[7];
short l, m;
int *n;
int **o = &n;
void
t ()
{
for (; f;)
;
}
static struct a
u (int x)
{
struct a a = { 4, 8, 5, 4 };
for (; i <= 6; i++)
{
struct a v = { };
for (; l; l++)
h = 0;
for (; h >= 0; h--)
{
j[i];
struct a *w = &p;
s = 0;
for (; s < 3; s++)
{
r ^= x;
m = j[i][g][h] == (k[g] = g);
*w = v;
}
r = 2;
for (; r; r--)
*o = &r;
}
}
t ();
return a;
}
int
main ()
{
*q = u (636);
if (p.b != 4)
__builtin_abort ();
}