This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug rtl-optimization/67443] [5/6 regression] DSE removes required store instruction


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.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]