This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug rtl-optimization/67443] [5/6 regression] DSE removes required store instruction
- From: "wmi at google dot com" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: Sun, 18 Oct 2015 18:55:38 +0000
- Subject: [Bug rtl-optimization/67443] [5/6 regression] DSE removes required store instruction
- Auto-submitted: auto-generated
- References: <bug-67443-4 at http dot gcc dot gnu dot org/bugzilla/>
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67443
--- Comment #13 from wmi at google dot com ---
Use the extracted testcase vogt contributed. Here is some digging about why
rtx_refs_may_alias_p returns noalias for the load and store:
(gdb) c
Continuing.
Breakpoint 3, rtx_refs_may_alias_p (x=0x7ffff57fe768, mem=0x7ffff57fe708,
tbaa_p=true)
at ../../src/gcc/alias.c:385
385 if (!ao_ref_from_mem (&ref1, x)
******
(gdb) p print_rtl_single(stderr, x)
(mem/j:SI (reg/v/f:DI 1 %r1 [orig:64 ps ] [64]) [5 ps_8->f2+-1 S4 A32])
$1 = 1
(gdb) p print_rtl_single(stderr, mem)
(mem/j:QI (reg/v/f:DI 2 %r2 [orig:64 ps ] [64]) [5 ps_8->f1+0 S1 A32])
******
rtx_refs_may_alias_p(x, mem, true) returns no_alias for "x" and "mem".
>From RTL representation, x's starting address is ps_8->f2+-1, size is 4 //See
[5 ps_8->f2+-1 S4 A32]
mem's starting address is ps_8->f1+0, size is 1 // see [5 ps_8->f1+0 S1 A32]
So x and mem are aliased with each other.
******
(gdb) p ref1
$3 = {ref = 0x7ffff568d9f0, base = 0x7ffff57d7c30, offset = 8, size = 24,
max_size = 24, ref_alias_set = 5,
base_alias_set = -1, volatile_p = false}
(gdb) p ref2
$4 = {ref = 0x7ffff568d9c0, base = 0x7ffff57d7f50, offset = 0, size = 8,
max_size = 8, ref_alias_set = 5,
base_alias_set = -1, volatile_p = false}
(gdb) p debug_generic_expr(ref1.base)
*ps_8
$6 = void
(gdb) p debug_generic_expr(ref2.base)
*ps_8
$7 = void
******
rtx_refs_may_alias_p(x, mem, true) calls refs_may_alias_p_1(&ref1, &ref2, ...)
as its helper func. For ref1 and ref2, they have the same base -- *ps_8, but
they have non-overlapping accessing ranges -- ref1 from 8 to 8+24, ref2 from 0
to 8, so ref1 has no-alias with ref2.
The major difference is between ref1 and x. ref1 is initialized using
MEM_EXPR(x) (MEM_EXPR(x) is ps_8->f2). So ref1 has its offset to be 8 and its
size to be 24. However, x has starting address to be ps_8->f2-1 and size to be
32 bits. Usually ref1's offset and size will be adjusted according to
MEM_SIZE(x) and MEM_OFFSET(x). However, because of the if (...) clause below,
ao_ref_from_mem returns true without adjusting ref1->offset and ref1->size.
(gdb) p debug_generic_expr(MEM_EXPR(x))
ps_8->f2
(gdb) p MEM_OFFSET(x)
$11 = -1
(gdb) p MEM_SIZE(x)
$12 = 4
ao_ref_from_mem (ao_ref *ref, const_rtx mem)
{
tree expr = MEM_EXPR (mem);
...
ao_ref_init (ref, expr);
base = ao_ref_base (ref);
...
/* If the base decl is a parameter we can have negative MEM_OFFSET in
case of promoted subregs on bigendian targets. Trust the MEM_EXPR
here. */
if (MEM_OFFSET (mem) < 0
&& (MEM_SIZE (mem) + MEM_OFFSET (mem)) * BITS_PER_UNIT == ref->size)
return true;
ref->offset += MEM_OFFSET (mem) * BITS_PER_UNIT;
ref->size = MEM_SIZE (mem) * BITS_PER_UNIT;
...
}
I don't understand the code above well -- why can we trust MEM_EXPR instead of
relying on MEM_OFFSET and MEM_SIZE? It seems not the case for the testcase
here.