mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-22 22:01:20 +08:00
re PR target/54589 (struct offset add should be folded into address calculation)
PR target/54589 * combine.c (find_split_point): For invalid memory address nonobj + obj + const, if reg + obj + const is valid addressing mode, split at nonobj. Use if rather than else if for the fallback. Comment fixes. * gcc.target/i386/pr54589.c: New test. From-SVN: r266707
This commit is contained in:
parent
1072cfdf34
commit
6b4f5050a9
@ -1,3 +1,11 @@
|
||||
2018-12-01 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR target/54589
|
||||
* combine.c (find_split_point): For invalid memory address
|
||||
nonobj + obj + const, if reg + obj + const is valid addressing
|
||||
mode, split at nonobj. Use if rather than else if for the
|
||||
fallback. Comment fixes.
|
||||
|
||||
2018-11-30 Indu Bhagat <indu.bhagat@oracle.com>
|
||||
|
||||
* coverage.c (get_coverage_counts): Use from_function_decl for precise
|
||||
|
@ -4945,7 +4945,7 @@ find_split_point (rtx *loc, rtx_insn *insn, bool set_src)
|
||||
}
|
||||
|
||||
/* If we have a PLUS whose second operand is a constant and the
|
||||
address is not valid, perhaps will can split it up using
|
||||
address is not valid, perhaps we can split it up using
|
||||
the machine-specific way to split large constants. We use
|
||||
the first pseudo-reg (one of the virtual regs) as a placeholder;
|
||||
it will not remain in the result. */
|
||||
@ -4960,7 +4960,7 @@ find_split_point (rtx *loc, rtx_insn *insn, bool set_src)
|
||||
|
||||
/* This should have produced two insns, each of which sets our
|
||||
placeholder. If the source of the second is a valid address,
|
||||
we can make put both sources together and make a split point
|
||||
we can put both sources together and make a split point
|
||||
in the middle. */
|
||||
|
||||
if (seq
|
||||
@ -5001,14 +5001,51 @@ find_split_point (rtx *loc, rtx_insn *insn, bool set_src)
|
||||
}
|
||||
}
|
||||
|
||||
/* If that didn't work and we have a nested plus, like:
|
||||
((REG1 * CONST1) + REG2) + CONST2 and (REG1 + REG2) + CONST2
|
||||
is valid address, try to split (REG1 * CONST1). */
|
||||
if (GET_CODE (XEXP (XEXP (x, 0), 0)) == PLUS
|
||||
&& !OBJECT_P (XEXP (XEXP (XEXP (x, 0), 0), 0))
|
||||
&& OBJECT_P (XEXP (XEXP (XEXP (x, 0), 0), 1))
|
||||
&& ! (GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == SUBREG
|
||||
&& OBJECT_P (SUBREG_REG (XEXP (XEXP (XEXP (x, 0),
|
||||
0), 0)))))
|
||||
{
|
||||
rtx tem = XEXP (XEXP (XEXP (x, 0), 0), 0);
|
||||
XEXP (XEXP (XEXP (x, 0), 0), 0) = reg;
|
||||
if (memory_address_addr_space_p (GET_MODE (x), XEXP (x, 0),
|
||||
MEM_ADDR_SPACE (x)))
|
||||
{
|
||||
XEXP (XEXP (XEXP (x, 0), 0), 0) = tem;
|
||||
return &XEXP (XEXP (XEXP (x, 0), 0), 0);
|
||||
}
|
||||
XEXP (XEXP (XEXP (x, 0), 0), 0) = tem;
|
||||
}
|
||||
else if (GET_CODE (XEXP (XEXP (x, 0), 0)) == PLUS
|
||||
&& OBJECT_P (XEXP (XEXP (XEXP (x, 0), 0), 0))
|
||||
&& !OBJECT_P (XEXP (XEXP (XEXP (x, 0), 0), 1))
|
||||
&& ! (GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1)) == SUBREG
|
||||
&& OBJECT_P (SUBREG_REG (XEXP (XEXP (XEXP (x, 0),
|
||||
0), 1)))))
|
||||
{
|
||||
rtx tem = XEXP (XEXP (XEXP (x, 0), 0), 1);
|
||||
XEXP (XEXP (XEXP (x, 0), 0), 1) = reg;
|
||||
if (memory_address_addr_space_p (GET_MODE (x), XEXP (x, 0),
|
||||
MEM_ADDR_SPACE (x)))
|
||||
{
|
||||
XEXP (XEXP (XEXP (x, 0), 0), 1) = tem;
|
||||
return &XEXP (XEXP (XEXP (x, 0), 0), 1);
|
||||
}
|
||||
XEXP (XEXP (XEXP (x, 0), 0), 1) = tem;
|
||||
}
|
||||
|
||||
/* If that didn't work, perhaps the first operand is complex and
|
||||
needs to be computed separately, so make a split point there.
|
||||
This will occur on machines that just support REG + CONST
|
||||
and have a constant moved through some previous computation. */
|
||||
|
||||
else if (!OBJECT_P (XEXP (XEXP (x, 0), 0))
|
||||
&& ! (GET_CODE (XEXP (XEXP (x, 0), 0)) == SUBREG
|
||||
&& OBJECT_P (SUBREG_REG (XEXP (XEXP (x, 0), 0)))))
|
||||
if (!OBJECT_P (XEXP (XEXP (x, 0), 0))
|
||||
&& ! (GET_CODE (XEXP (XEXP (x, 0), 0)) == SUBREG
|
||||
&& OBJECT_P (SUBREG_REG (XEXP (XEXP (x, 0), 0)))))
|
||||
return &XEXP (XEXP (x, 0), 0);
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,8 @@
|
||||
2018-12-01 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR target/54589
|
||||
* gcc.target/i386/pr54589.c: New test.
|
||||
|
||||
2018-11-30 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR testsuite/85368
|
||||
|
22
gcc/testsuite/gcc.target/i386/pr54589.c
Normal file
22
gcc/testsuite/gcc.target/i386/pr54589.c
Normal file
@ -0,0 +1,22 @@
|
||||
/* PR target/54589 */
|
||||
/* { dg-do compile { target { *-*-linux* && lp64 } } } */
|
||||
/* { dg-options "-O2 -masm=att" } */
|
||||
/* { dg-final { scan-assembler "movl\[ \t]+(?:t\\+336\\(%r..\\)|336\\(%r..,%r..\\)), %eax" } } */
|
||||
/* { dg-final { scan-assembler "movl\[ \t]+340\\(%r..,%r..\\), %eax" } } */
|
||||
/* { dg-final { scan-assembler-times "salq\[^\n\r]*4, %" 2 } } */
|
||||
/* { dg-final { scan-assembler-not "addq\[ \t]" } } */
|
||||
|
||||
struct S { int a, b, c, d; };
|
||||
struct T { struct S e[16]; struct S f[1024]; } t;
|
||||
|
||||
int
|
||||
foo (unsigned long x)
|
||||
{
|
||||
return t.f[x + 5].a;
|
||||
}
|
||||
|
||||
int
|
||||
bar (struct T *x, unsigned long y)
|
||||
{
|
||||
return x->f[y + 5].b;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user