r175386 - [CodeGen] tighten objc ivar invariant.load attribution

Saleem Abdulrasool compnerd at compnerd.org
Sat Feb 16 20:03:35 PST 2013


Author: compnerd
Date: Sat Feb 16 22:03:34 2013
New Revision: 175386

URL: http://llvm.org/viewvc/llvm-project?rev=175386&view=rev
Log:
[CodeGen] tighten objc ivar invariant.load attribution

An ivar ofset cannot be marked as invariant load in all cases.  The ivar offset
is a lazily initialised constant, which is dependent on an objc_msgSend
invocation to perform a fixup of the offset.  If the load is being performed on
a method implemented by the class then this load can safely be marked as an
inviarant because a message must have been passed to the class at some point,
forcing the ivar offset to be resolved.

An additional heuristic that can be used to identify an invariant load would be
if the ivar offset base is a parameter to an objc method.  However, without the
parameters available at hand, this is currently not possible.

Reviewed-by: John McCall <rjmccall at apple.com>
Signed-off-by: Saleem Abdulrasool <compnerd at compnerd.org>

Added:
    cfe/trunk/test/CodeGenObjC/ivar-invariant.m
Modified:
    cfe/trunk/lib/CodeGen/CGObjCMac.cpp

Modified: cfe/trunk/lib/CodeGen/CGObjCMac.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCMac.cpp?rev=175386&r1=175385&r2=175386&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCMac.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjCMac.cpp Sat Feb 16 22:03:34 2013
@@ -1432,6 +1432,25 @@ private:
   /// class implementation is "non-lazy".
   bool ImplementationIsNonLazy(const ObjCImplDecl *OD) const;
 
+  bool IsIvarOffsetKnownIdempotent(const CodeGen::CodeGenFunction &CGF,
+                                   const ObjCInterfaceDecl *ID,
+                                   const ObjCIvarDecl *IV) {
+    // Annotate the load as an invariant load iff the object type is the type,
+    // or a derived type, of the class containing the ivar within an ObjC
+    // method.  This check is needed because the ivar offset is a lazily
+    // initialised value that may depend on objc_msgSend to perform a fixup on
+    // the first message dispatch.
+    //
+    // An additional opportunity to mark the load as invariant arises when the
+    // base of the ivar access is a parameter to an Objective C method.
+    // However, because the parameters are not available in the current
+    // interface, we cannot perform this check.
+      if (dyn_cast<ObjCMethodDecl>(CGF.CurFuncDecl))
+        if (IV->getContainingInterface()->isSuperClassOf(ID))
+          return true;
+    return false;
+  }
+
 public:
   CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm);
   // FIXME. All stubs for now!
@@ -6449,10 +6468,12 @@ LValue CGObjCNonFragileABIMac::EmitObjCV
                                                unsigned CVRQualifiers) {
   ObjCInterfaceDecl *ID = ObjectTy->getAs<ObjCObjectType>()->getInterface();
   llvm::Value *Offset = EmitIvarOffset(CGF, ID, Ivar);
-  if (llvm::LoadInst *LI = dyn_cast<llvm::LoadInst>(Offset))
-    LI->setMetadata(CGM.getModule().getMDKindID("invariant.load"), 
-                   llvm::MDNode::get(VMContext,
-                   ArrayRef<llvm::Value*>()));
+
+  if (IsIvarOffsetKnownIdempotent(CGF, ID, Ivar))
+    if (llvm::LoadInst *LI = cast<llvm::LoadInst>(Offset))
+      LI->setMetadata(CGM.getModule().getMDKindID("invariant.load"),
+                      llvm::MDNode::get(VMContext, ArrayRef<llvm::Value*>()));
+
   return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
                                   Offset);
 }

Added: cfe/trunk/test/CodeGenObjC/ivar-invariant.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/ivar-invariant.m?rev=175386&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenObjC/ivar-invariant.m (added)
+++ cfe/trunk/test/CodeGenObjC/ivar-invariant.m Sat Feb 16 22:03:34 2013
@@ -0,0 +1,53 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -x objective-c %s -o - | FileCheck %s
+
+ at interface NSObject
++ (id) new;
+- (id) init;
+ at end
+
+ at interface Base : NSObject @end
+
+// @implementation Base
+// {
+//     int dummy;
+// }
+// @end
+
+ at interface Derived : Base
+{
+    @public int member;
+}
+ at end
+
+ at implementation Derived
+- (id) init
+{
+    self = [super init];
+    member = 42;
+    return self;
+}
+ at end
+
+// CHECK: [[IVAR:%.*]] = load i64* @"OBJC_IVAR_$_Derived.member", !invariant.load
+
+void * variant_load_1(int i) {
+    void *ptr;
+    while (i--) {
+        Derived *d = [Derived new];
+        ptr = &d->member;
+    }
+    return ptr;
+}
+
+// CHECK: [[IVAR:%.*]] = load i64* @"OBJC_IVAR_$_Derived.member"{{$}}
+
+ at interface Container : Derived @end
+ at implementation Container
+- (void *) invariant_load_1
+{
+    return &self->member;
+}
+ at end
+
+// CHECK: [[IVAR:%.*]] = load i64* @"OBJC_IVAR_$_Derived.member", !invariant.load
+





More information about the cfe-commits mailing list