https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127633
Richard Biener <rguenth at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
Component|tree-optimization |target
--- Comment #10 from Richard Biener <rguenth at gcc dot gnu.org> ---
(In reply to Richard Biener from comment #9)
> 2. Peephole2 Mislabeling:
> In gcc/config/i386/sse.md, the define_peephole2 pattern merging two
> adjacent 64-bit DFmode memory loads into a 128-bit V2DFmode movupd load
> matched the adjacent stack loads:
>
> 1 (define_peephole2
> 2 ...
> 3 [(set (match_dup 2) (match_dup 5))]
> 4 "operands[5] = adjust_address (operands[1], V2DFmode, 0);")
> adjust_address changes the mode of operands[1] (88(%rsp)) from DFmode to
> V2DFmode without validating whether the widened 16-byte access exceeds the
> bounds of the underlying object. As a result, the new 16-byte memory
> reference
> retained the MEM_EXPR (the spill slot pseudo) and MEM_ALIAS_SET of
> operands[1].
>
> 3. Missing Memory Dependence & Uninitialized Read in sched2:
> Before the load of bv, a store *by = ... initializes bv at 96(%rsp).
> During
> sched2, alias analysis (nonoverlapping_memrefs_p) was queried between the
> store through pointer by (alias set 3) and the 16-byte movupd load. Because
> the 16-byte load retained the MEM_EXPR of the spill slot, alias analysis
> concluded that the load from the spill slot could never alias with a
> pointer
> dereference storing to bv. Consequently, sched2 scheduled the 16-byte load
> before the store to bv, reading uninitialized stack data.
>
> The garbage value corrupted the return value of s, leading to a
> mismatched
> condition in q and triggering the infinite loop in n.
>
>
> adjust_address_1 has many conditions under which it clears MEM_EXPR and
> MEM_ALIAS_SET already, so it might be tempting to add one doing this iff
> the new modes size is not equal to the old size (at least MEM_EXPR cannot
> be correct then).
Oh, and there already is
if (maybe_ne (size, 0))
{
/* Drop the object if the new right end is not within its bounds. */
if (adjust_object && maybe_gt (offset + size, attrs.size))
{
attrs.expr = NULL_TREE;
attrs.alias = 0;
}
but this is guarded by adjust_object which is passed as 0.
adjust_bitfield_address would pass 1 which reads
/* Return a memory reference like MEMREF, but with its mode changed
to MODE and its address offset by OFFSET bytes. Assume that it's
for a bitfield and conservatively drop the underlying object if we
cannot be sure to stay within its bounds. */
#define adjust_bitfield_address(MEMREF, MODE, OFFSET) \
adjust_address_1 (MEMREF, MODE, OFFSET, 1, 1, 1, 0)
there's also widen_memory_access which might be a better fit here. I'm
testing a patch.