On May 11, 2005, at 11:42 AM, Mark Mitchell wrote:

Kenny and I had a long conversation about the aliasing issue, and reached the following proposed solution.

In short, the issue is, when given the following code:

  struct A {...};
  struct B { ...; struct A a; ...; };

  void f() {
    B b;
    g(&b.a);
  }

does the compiler have to assume that "g" may access the parts of "b" outside of "a". If the compiler can see the body of "g" than it may be able to figure out that it can't access any other parts, or figure out which parts it can access, and in that case it can of course use that information. The interesting case, therefore, is when the body of "g" is not available, or is insufficient to make a conclusive determination.

Our proposed approach is to -- by default -- assume that "g" may access all of "b". However, in the event that the corresponding parameter to "g" has an attribute (name TBD, possibly the same as the one that appears in Danny's recent patch), then we may assume that "g" (and its callees) do not use the pointer to obtain access to any fields of "b".

For example:

  void g(A *p __attribute__((X)));

  void f() {
    B b;
    g(&b.a); /* Compiler may assume the rest of b is not accessed
                in "g".  */
  }

This approach allows users to annotate code to get better optimization while still perserving the behavior of current, possibly conforming, progrBams.\

I assume the type of the field is irrelevant (although you chose a struct for your example)?


I assume the attribute has both positive and negative forms?

I assume the semantics have nothing to do with B per se, but apply to all possible containing structs?
(Mail.app *will* screw this up, please be tolerant):


struct  B { ...; struct A a1; struct A a2; ... };
struct C  { ...; struct A a; ... };
struct D  { ... ; struct B b;   };

  void g(A *p __attribute__((X)), int field_addressed);

void f() {
B b; C c; D d;
g(&b.a1, 1); /* Compiler may assume the rest of b is not accessed in "g". */
g(&b.a2, 2): /* How about now? */
g(&c.a, 3); /* What b? */
g(&d.b.a1, 4); /* cannot alter rest of d.b, how about rest of d? */


If, in future, the commitee reaches the conclusion that all functions should be treated as if they had the attribute, i.e., that you cannot perform the kinds of operations shown above in the example for "g", then we will modify the compiler so that, by default, the compiler treats all parameters as if they had this atrribute. We would then also add a switch to disable the optimization for people who have legacy code, just as we have -fno-strict-aliasing.

[ I did not discuss this with Kenny, but another option is to have a -fassume-X switch, off by default, which treats your code as if you had the magic attribute everywhere. ]

I'm not so sure an attribute is a good idea. That's definitely a language extension, one way
or another; I'm thinking more along the lines of trying to follow the standard, with the problem
being that we can't figure out what it says. The flag seems cleaner to me. Also certain
optimizations are slightly easier that way, e.g. figuring out whether a field can be kept in
a register when another field's address is taken just requires looking at the global flag
rather than every call in the function (not a big deal).


The attribute might well be unnecessary, and once it's in it's in forever. And I suspect supporting
different semantics for different calls will create problems down the line, somehow or other
(although I confess I don't think of any offhand).




Reply via email to