This is the mail archive of the gcc-patches@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]

Fix PR 33870


This patch fixes PR 33870.  There were a couple of things at play here
related to the way we compute sub-variables for structures and arrays.
 Particularly in the presence of nesting.

When alias analysis computes points-to information for a structure for
which we have sub-variables, it never adds all the variables to the
set.  It only adds the first SFT reachable by the pointer.

So, if we have a pointer p_1 pointing into some structure and we
dereference a field with p_1->fld, we can find out what offset to use
by calling get_base_ref_and_extent.  However, if that field is inside
a nested structure, the offset computed by get_ref_base_and_extent is
the offset from the start of the immediately containing structure.
However, to find out what other SFTs are affected by this reference,
we need to know the offsets starting at the root structure in the
nesting hierarchy.

For instance, given the following structure:

       struct X {
         int a;
         struct Y {
           int b;
           struct Z {
             int c[3];
           } d;
         } e;
       } m;

and the following address expression:

       p_1 = &m.e.d;

This structure will receive 5 SFTs, namely 2 for fields 'a' and 'b'
and 3 for the array 'c' in struct Z.  So, the reference p_1->c[2] and
m.e.d.c[2] access the exact same memory location (ie, SFT.5).

Now, alias analysis computed the points-to set for pointer p_1 as  {
SFT.3 } because that is the first field that p_1 actually points to.
When the expression p_1->c[2] is analyzed, get_ref_base_and_extent
will return an offset of 96 because we are accessing the third element
of the array.  But the SFT we are looking for is actually at offset
160, counting from the top of struct X.

Therefore, we need to adjust the offset given by
get_base_ref_and_extent by the offset of VAR so that we can get at all
the fields starting at VAR.

Notice that this adjustment is ONLY necessary if the pointer is
pointing inside a nested structure.  If p_1 is pointing at the base
structure of the nesting hierarchy, then no adjustment is necessary.

Since this adjustment was being applied with every field reference, we
were failing to add SFTs when some of the SFTs in the structure had
been partitioned away into an MPT.

In the specific case of PR 33870, there was a single field 'pDirty'
inside a large structure that was being referenced with a pointer and
with a regular variable.  The field had the subvariable SFT.12
associated with it, with an offset of X bytes.

Since SFT.12 was the only field that had not been partitioned away,
when we were adding SFTs in the operand scanner, we would blindly
adjust the offset of SFT.12 by X bytes and then trying to see if there
was any SFT at offset X + X.

There wasn't any, of course, and so no VOP was added to the memory
load expression, which was then taken out of the loop because it was
thought to be loop independent.  Leading to the runtime failure.

The only reason this didn't occur if partitioning was disabled was
that the same blind offset adjustment was adding SFT.12 because it had
ajdusted the offset of an SFT that was X bytes earlier in the
structure.  So, it was working by chance.

By recognizing that this offset adjustment is only required for nested
structures, we do not need to blindly adjust every offset and so we
don't end up adding SFTs by accident.

Tested on x86_64.  Committed.

Attachment: 20071107-33870.diff.txt
Description: Text document


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