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

Re: Help understanding gcc alias analysis


Richard Guenther wrote:
On Sun, Jan 11, 2009 at 7:59 PM, Raoul Gough <RaoulGough@yahoo.co.uk> wrote:
[snip]
I guess the situation is more complicated in C++, which has explicit
destructors. Consider the following example, which is getting closer to the
problem that originally got me interested in this subject:

void** global_free_list = 0;

inline void operator delete(void* p2) throw()
{
  // Save "next" pointer in re-used client storage. TODO - check for NULL
  *static_cast<void **>(p2) = global_free_list;
  global_free_list = static_cast<void **>(p2);
}

double foo(double* p1)
{
  double result = *p1;
  delete p1;
  return result;
}

Now, after inlining, this example looks very similar to my original one,
except we have pointers of type double* and void** sharing the same storage
space instead of int* and double*. Note - we can easily ensure that the
corresponding operator new() always allocates storage suitably sized and
aligned for a void*.

This is also invalid. You have to use placement new to change the dynamic type of memory.


Yes, I guess that makes sense. I've modified the example like this:


#include <new>

void** global_free_list = 0;

inline void operator delete(void* p2) throw()
{
   // Save "next" pointer in re-used client storage
   new (p2) (void *) (global_free_list);
   global_free_list = static_cast<void **>(p2);
}

double foo(double* p1)
{
   double result = *p1;
   delete p1;
   return result;
}


I've included the complete alias debug output below. This now includes global_free_list in the may-alias lists, which is interesting. Also there is a NULL-pointer check and branch, but I assume another optimization phases could, under some circumstances, remove this. For example, if foo() started with assert(p1) then this NULL pointer check would be redundant. That would leave it with more or less the same code tree as before, aside from the differences in the aliasing information.


So how is this example looking now? Does the alias analysis mean that g++ will never reorder the read and write via p1 and p2?

--
Thanks,
Raoul Gough.


;; Function double foo(double*) (_Z3fooPd)


Points-to analysis

Constraints:

ANYTHING = &ANYTHING
READONLY = &ANYTHING
INTEGER = &ANYTHING
p1 = &ANYTHING
D.1859_5 = p1
D.1860_6 = D.1859_5
iftmp.0_7 = D.1860_6
global_free_list = &ANYTHING
global_free_list.1_8 = global_free_list
*iftmp.0_7 = global_free_list.1_8
p2.2_9 = p1
global_free_list = p2.2_9

Collapsing static cycles and doing variable substitution
Building predecessor graph
Detecting pointer and location equivalences
Rewriting constraints and unifying variables
Uniting pointer but not location equivalent variables
Finding indirect cycles
Solving graph

Points-to sets

NULL = { }
ANYTHING = { ANYTHING }
READONLY = { ANYTHING }
INTEGER = { ANYTHING }
p1 = { ANYTHING } no-tbaa-pruning
D.1859_5 = same as p1
D.1860_6 = same as p1
iftmp.0_7 = same as p1
global_free_list.1_8 = same as p1
global_free_list = same as p1
p2.2_9 = same as p1

Memory partitioning NOT NEEDED for foo

Memory reference statistics for double foo(double*)

Number of memory statements:     4
Number of call sites:            0
Number of pure/const call sites: 0
Number of asm sites:             0
Estimated number of loads:       3 (1/stmt)
Actual number of loads:          3 (1/stmt)
Estimated number of stores:      3 (1/stmt)
Actual number of stores:         3 (1/stmt)
Partitioning thresholds:         MAX = 1000   AVG = 3 (NO NEED TO PARTITION)
Number of partitioned symbols:   0
Number of unpartitioned symbols: 5

Alias information for double foo(double*)


Memory partitions



0 memory partitions holding 0 symbols


Flow-insensitive alias information for double foo(double*)

Aliased symbols

SMT.7, UID D.1868, void *, is addressable, is global, score: 556356, direct reads: 0, direct writes: 0, indirect reads: 0, indirect writes: 1, call clobbered (stored in global, is global var), may aliases: { global_free_list }
SMT.8, UID D.1869, double, is addressable, is global, score: 320002, direct reads: 0, direct writes: 0, indirect reads: 1, indirect writes: 0, call clobbered (is global var, is incoming pointer), may aliases: { global_free_list }
NMT.9, UID D.1870, double, is addressable, is global, score: 8, direct reads: 1, direct writes: 0, indirect reads: 0, indirect writes: 0, call clobbered (is global var, is incoming pointer), may aliases: { global_free_list SMT.8 }
NMT.10, UID D.1871, void *, is addressable, is global, score: 16, direct reads: 0, direct writes: 1, indirect reads: 0, indirect writes: 0, call clobbered (stored in global, is global var), may aliases: { global_free_list SMT.7 }
global_free_list, UID D.1817, void * *, is addressable, is global, score: 1794558, direct reads: 1, direct writes: 1, indirect reads: 1, indirect writes: 1, call clobbered (stored in global, is global var, is incoming pointer)


Dereferenced pointers

iftmp.0, UID D.1861, void * *, symbol memory tag: SMT.7
global_free_list.1, UID D.1862, void * *, symbol memory tag: SMT.7
p2.2, UID D.1863, void * *, symbol memory tag: SMT.7
p1, UID D.1842, double *, symbol memory tag: SMT.8, default def: p1_1(D)

Symbol memory tags

SMT.7, UID D.1868, void *, is addressable, is global, score: 556356, direct reads: 0, direct writes: 0, indirect reads: 0, indirect writes: 1, call clobbered (stored in global, is global var), may aliases: { global_free_list }
SMT.8, UID D.1869, double, is addressable, is global, score: 320002, direct reads: 0, direct writes: 0, indirect reads: 1, indirect writes: 0, call clobbered (is global var, is incoming pointer), may aliases: { global_free_list }



Flow-sensitive alias information for double foo(double*)


SSA_NAME pointers

p1_1(D), name memory tag: NMT.9, is dereferenced, its value escapes, points-to vars: { global_free_list SMT.8 }

iftmp.0_7, name memory tag: NMT.10, is dereferenced, points-to vars: { global_free_list SMT.7 }

global_free_list.1_8, name memory tag: NMT.10, is dereferenced, its value escapes, points-to vars: { global_free_list SMT.7 }

p2.2_9, name memory tag: NMT.10, is dereferenced, its value escapes, points-to vars: { global_free_list SMT.7 }


Name memory tags


NMT.9, UID D.1870, double, is addressable, is global, score: 8, direct reads: 1, direct writes: 0, indirect reads: 0, indirect writes: 0, call clobbered (is global var, is incoming pointer), may aliases: { global_free_list SMT.8 }
NMT.10, UID D.1871, void *, is addressable, is global, score: 16, direct reads: 0, direct writes: 1, indirect reads: 0, indirect writes: 0, call clobbered (stored in global, is global var), may aliases: { global_free_list SMT.7 }




Pointed-to sets for pointers in double foo(double*)

p1_1(D), name memory tag: NMT.9, is dereferenced, its value escapes, points-to vars: { global_free_list SMT.8 }

D.1859_5, points-to anything
D.1860_6, points-to anything
iftmp.0_7, name memory tag: NMT.10, is dereferenced, points-to vars: { global_free_list SMT.7 }


global_free_list.1_8, name memory tag: NMT.10, is dereferenced, its value escapes, points-to vars: { global_free_list SMT.7 }

p2.2_9, name memory tag: NMT.10, is dereferenced, its value escapes, points-to vars: { global_free_list SMT.7 }




Symbols to be put in SSA form


{ global_free_list SMT.7 SMT.8 NMT.9 NMT.10 }


Incremental SSA update started at block: 0


Number of blocks in CFG: 5
Number of blocks to update: 4 ( 80%)



double foo(double*) (p1)
{
 void * D.1860;
 void * * iftmp.0;
 void * * global_free_list.1;
 void * * p2.2;
 void * D.1859;
 void * D.1859;
 double result;

<bb 2>:
 result_2 = *p1_1(D);
 D.1859_5 = p1_1(D);
 D.1860_6 = D.1859_5;
 iftmp.0_7 = (void * *) D.1860_6;
 if (iftmp.0_7 != 0B)
   goto <bb 3>;
 else
   goto <bb 4>;

<bb 3>:
 global_free_list.1_8 = global_free_list;
 *iftmp.0_7 = global_free_list.1_8;

<bb 4>:
 p2.2_9 = (void * *) p1_1(D);
 global_free_list = p2.2_9;
 return result_2;

}








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