ObjCARCAliasAnalysis implements custom getMemoryEffects/getModRefInfo for a few objc intrinsics. However, this is not necessary, as these intrinsics can be described using ordinary readnone/inaccessiblememonly intrinsic attributes. Do that, and drop the special handling from the AA pass.
Diff Detail
Event Timeline
llvm/lib/Analysis/ObjCARCAliasAnalysis.cpp | ||
---|---|---|
123 | The comment below doesn't seem correct as I think these functions can indirectly cause a memory location that is visible to the compiler to be modified. For example, in the code below, method retain, which gets called when an object of type C is passed to objc_retain, modifies cnt. @interface C : NSObject { @public unsigned cnt; } - (instancetype)retain; @end @implementation C - (instancetype)retain { ++cnt; return [super retain]; } cnt can easily be accessed by the code generated by the compiler. For example: void test(C *c) { c->cnt = 0; } John, does ARC assume that objc_retain doesn't access any memory visible to the compiler? |
The ARC spec describes the semantic restrictions on retain/release implementations:
https://clang.llvm.org/docs/AutomaticReferenceCounting.html#arc-objects-retains
Those semantics do not forbid changing visible memory, they just permit retains and releases to be moved regardless of their impact on visible memory. This is in keeping with the very operational definition of ObjC ARC optimization. There's an implicit assumption here that moving retains and releases won't make other optimizations unsound, which I think can most easily be satisfied by not moving retains and releases to places where there aren't already retains and releases of that object.
Thanks for the comments. I'm a bit unclear on what the right way forward here is. It sounds like the existing behavior is already incorrect (I think reporting NoModRef allows transforms that are not equivalent to a move of retain/release) and the correct action here would be to drop ARCInstKind::Retain and a few others from the getModRefInfo() implementation instead?
The comment below doesn't seem correct as I think these functions can indirectly cause a memory location that is visible to the compiler to be modified.
For example, in the code below, method retain, which gets called when an object of type C is passed to objc_retain, modifies cnt.
cnt can easily be accessed by the code generated by the compiler. For example:
John, does ARC assume that objc_retain doesn't access any memory visible to the compiler?