]> granicus.if.org Git - clang/commitdiff
Objective-C IRGen. Fix up the hueristics for determining
authorFariborz Jahanian <fjahanian@apple.com>
Tue, 4 Mar 2014 18:34:52 +0000 (18:34 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Tue, 4 Mar 2014 18:34:52 +0000 (18:34 +0000)
if an ivar offset load is invariant iff inside an instance method
and ivar belongs to instance method's class and one of its super class.
// rdar://16095748

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@202872 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGObjCMac.cpp
test/CodeGenObjC/optimize-ivar-offset-load.m [new file with mode: 0644]

index f558412f716777be5f58a827f3fa8c5f8a65699f..ebbd7007c14c0824f53cad4b06adefe2d5579bc0 100644 (file)
@@ -1442,11 +1442,10 @@ private:
   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
+    // Annotate the load as an invariant load iff inside an instance method
+    // and ivar belongs to instance method's class and one of its super class.
+    // 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.
     //
@@ -1454,9 +1453,12 @@ private:
     // 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 (CGF.CurFuncDecl && isa<ObjCMethodDecl>(CGF.CurFuncDecl))
-      if (IV->getContainingInterface()->isSuperClassOf(ID))
-        return true;
+    if (const ObjCMethodDecl *MD =
+          dyn_cast_or_null<ObjCMethodDecl>(CGF.CurFuncDecl))
+      if (MD->isInstanceMethod() &&
+          !isa<ObjCProtocolDecl>(MD->getDeclContext()))
+        if (const ObjCInterfaceDecl *ID = MD->getClassInterface())
+          return IV->getContainingInterface()->isSuperClassOf(ID);
     return false;
   }
 
@@ -6479,7 +6481,7 @@ LValue CGObjCNonFragileABIMac::EmitObjCValueForIvar(
   ObjCInterfaceDecl *ID = ObjectTy->getAs<ObjCObjectType>()->getInterface();
   llvm::Value *Offset = EmitIvarOffset(CGF, ID, Ivar);
 
-  if (IsIvarOffsetKnownIdempotent(CGF, ID, Ivar))
+  if (IsIvarOffsetKnownIdempotent(CGF, Ivar))
     if (llvm::LoadInst *LI = cast<llvm::LoadInst>(Offset))
       LI->setMetadata(CGM.getModule().getMDKindID("invariant.load"),
                       llvm::MDNode::get(VMContext, ArrayRef<llvm::Value*>()));
diff --git a/test/CodeGenObjC/optimize-ivar-offset-load.m b/test/CodeGenObjC/optimize-ivar-offset-load.m
new file mode 100644 (file)
index 0000000..d34ac13
--- /dev/null
@@ -0,0 +1,64 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10  -Os -emit-llvm %s -o -  | FileCheck %s
+// rdar://16095748
+
+@interface NSObject 
+@end
+
+@interface SampleClass : NSObject {
+    @public
+    int _value;
+}
++ (SampleClass*) new;
+@end
+
+@interface AppDelegate  : NSObject
+@end
+
+extern void foo(int);
+
+@implementation AppDelegate
+- (void)application
+{
+    // Create set of objects in loop
+    for(int i = 0; i < 2; i++) {
+        SampleClass *sample = [SampleClass new];
+        foo (sample->_value);
+    }
+}
+@end
+// CHECK: [[IVAR:%.*]]  = load i64* @"OBJC_IVAR_$_SampleClass._value", align 8
+// CHECK: [[THREE:%.*]] = bitcast [[ONE:%.*]]* [[CALL:%.*]] to i8*
+// CHECK: [[ADDPTR:%.*]] = getelementptr inbounds i8* [[THREE]], i64 [[IVAR]]
+// CHECK: [[FOUR:%.*]] = bitcast i8* [[ADDPTR]] to i32*
+// CHECK: [[FIVE:%.*]] = load i32* [[FOUR]], align 4
+// CHECK:   tail call void @foo(i32 [[FIVE]])
+
+@implementation SampleClass
++ (SampleClass*) new { return 0; }
+- (void) SampleClassApplication
+{
+    // Create set of objects in loop
+    for(int i = 0; i < 2; i++) {
+        SampleClass *sample = [SampleClass new];
+        foo (sample->_value);
+    }
+}
+@end
+// CHECK: [[ZERO:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8, !invariant.load
+// CHECK: [[IVAR:%.*]] = load i64* @"OBJC_IVAR_$_SampleClass._value", align 8, !invariant.load
+
+@interface Sample : SampleClass @end
+
+@implementation Sample
+- (void) SampleApplication
+{
+    // Create set of objects in loop
+    for(int i = 0; i < 2; i++) {
+        SampleClass *sample = [SampleClass new];
+        foo (sample->_value);
+    }
+}
+@end
+// CHECK: [[ZERO:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8, !invariant.load 
+// CHECK: [[IVAR:%.*]] = load i64* @"OBJC_IVAR_$_SampleClass._value", align 8, !invariant.load
+