Author: epilk Date: Thu Jan 17 10:18:53 2019 New Revision: 351461 URL: http://llvm.org/viewvc/llvm-project?rev=351461&view=rev Log: [CodeGenObjC] Use a constant value for non-fragile ivar offsets when possible
If a class inherits from NSObject and has an implementation, then we can assume that ivar offsets won't need to be updated by the runtime. This allows us to index into the object using a constant value and avoid loading from the ivar offset variable. This patch was adapted from one written by Pete Cooper. rdar://problem/10132568 Differential revision: https://reviews.llvm.org/D56802 Added: cfe/trunk/test/CodeGenObjC/constant-non-fragile-ivar-offset.m Modified: cfe/trunk/lib/CodeGen/CGObjCMac.cpp cfe/trunk/test/CodeGenObjC/optimize-ivar-offset-load.m cfe/trunk/test/CodeGenObjC/reorder-synthesized-ivars.m Modified: cfe/trunk/lib/CodeGen/CGObjCMac.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCMac.cpp?rev=351461&r1=351460&r2=351461&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGObjCMac.cpp (original) +++ cfe/trunk/lib/CodeGen/CGObjCMac.cpp Thu Jan 17 10:18:53 2019 @@ -1550,6 +1550,15 @@ private: return false; } + bool isClassLayoutKnownStatically(const ObjCInterfaceDecl *ID) { + // NSObject is a fixed size. If we can see the @implementation of a class + // which inherits from NSObject then we know that all it's offsets also must + // be fixed. FIXME: Can we do this if see a chain of super classes with + // implementations leading to NSObject? + return ID->getImplementation() && ID->getSuperClass() && + ID->getSuperClass()->getName() == "NSObject"; + } + public: CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm); @@ -6702,6 +6711,12 @@ CGObjCNonFragileABIMac::EmitIvarOffsetVa IvarOffsetGV->setVisibility(llvm::GlobalValue::DefaultVisibility); } + // If ID's layout is known, then make the global constant. This serves as a + // useful assertion: we'll never use this variable to calculate ivar offsets, + // so if the runtime tries to patch it then we should crash. + if (isClassLayoutKnownStatically(ID)) + IvarOffsetGV->setConstant(true); + if (CGM.getTriple().isOSBinFormatMachO()) IvarOffsetGV->setSection("__DATA, __objc_ivar"); return IvarOffsetGV; @@ -6990,17 +7005,24 @@ LValue CGObjCNonFragileABIMac::EmitObjCV Offset); } -llvm::Value *CGObjCNonFragileABIMac::EmitIvarOffset( - CodeGen::CodeGenFunction &CGF, - const ObjCInterfaceDecl *Interface, - const ObjCIvarDecl *Ivar) { - llvm::Value *IvarOffsetValue = ObjCIvarOffsetVariable(Interface, Ivar); - IvarOffsetValue = CGF.Builder.CreateAlignedLoad(IvarOffsetValue, - CGF.getSizeAlign(), "ivar"); - if (IsIvarOffsetKnownIdempotent(CGF, Ivar)) - cast<llvm::LoadInst>(IvarOffsetValue) - ->setMetadata(CGM.getModule().getMDKindID("invariant.load"), - llvm::MDNode::get(VMContext, None)); +llvm::Value * +CGObjCNonFragileABIMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF, + const ObjCInterfaceDecl *Interface, + const ObjCIvarDecl *Ivar) { + llvm::Value *IvarOffsetValue; + if (isClassLayoutKnownStatically(Interface)) { + IvarOffsetValue = llvm::ConstantInt::get( + ObjCTypes.IvarOffsetVarTy, + ComputeIvarBaseOffset(CGM, Interface->getImplementation(), Ivar)); + } else { + llvm::GlobalVariable *GV = ObjCIvarOffsetVariable(Interface, Ivar); + IvarOffsetValue = + CGF.Builder.CreateAlignedLoad(GV, CGF.getSizeAlign(), "ivar"); + if (IsIvarOffsetKnownIdempotent(CGF, Ivar)) + cast<llvm::LoadInst>(IvarOffsetValue) + ->setMetadata(CGM.getModule().getMDKindID("invariant.load"), + llvm::MDNode::get(VMContext, None)); + } // This could be 32bit int or 64bit integer depending on the architecture. // Cast it to 64bit integer value, if it is a 32bit integer ivar offset value Added: cfe/trunk/test/CodeGenObjC/constant-non-fragile-ivar-offset.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/constant-non-fragile-ivar-offset.m?rev=351461&view=auto ============================================================================== --- cfe/trunk/test/CodeGenObjC/constant-non-fragile-ivar-offset.m (added) +++ cfe/trunk/test/CodeGenObjC/constant-non-fragile-ivar-offset.m Thu Jan 17 10:18:53 2019 @@ -0,0 +1,38 @@ +// RUN: %clang_cc1 -triple x86_64-apple-macosx10.14.0 -emit-llvm %s -o - | FileCheck %s + +// CHECK: @"OBJC_IVAR_$_StaticLayout.static_layout_ivar" = hidden constant i64 20 +// CHECK: @"OBJC_IVAR_$_NotStaticLayout.not_static_layout_ivar" = hidden global i64 12 + +@interface NSObject { + int these, will, never, change, ever; +} +@end + +@interface StaticLayout : NSObject +@end + +@implementation StaticLayout { + int static_layout_ivar; +} +-(void)meth { + static_layout_ivar = 0; + // CHECK-NOT: load i64, i64* @"OBJC_IVAR_$_StaticLayout +} +@end + +@interface NotNSObject { + int these, might, change; +} +@end + +@interface NotStaticLayout : NotNSObject +@end + +@implementation NotStaticLayout { + int not_static_layout_ivar; +} +-(void)meth { + not_static_layout_ivar = 0; + // CHECK: load i64, i64* @"OBJC_IVAR_$_NotStaticLayout.not_static_layout_ivar +} +@end Modified: cfe/trunk/test/CodeGenObjC/optimize-ivar-offset-load.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/optimize-ivar-offset-load.m?rev=351461&r1=351460&r2=351461&view=diff ============================================================================== --- cfe/trunk/test/CodeGenObjC/optimize-ivar-offset-load.m (original) +++ cfe/trunk/test/CodeGenObjC/optimize-ivar-offset-load.m Thu Jan 17 10:18:53 2019 @@ -1,17 +1,17 @@ // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -O0 -emit-llvm %s -o - | FileCheck %s // rdar://16095748 -@interface NSObject +@interface MyNSObject @end -@interface SampleClass : NSObject { +@interface SampleClass : MyNSObject { @public int _value; } + (SampleClass*) new; @end -@interface AppDelegate : NSObject +@interface AppDelegate : MyNSObject @end extern void foo(int); Modified: cfe/trunk/test/CodeGenObjC/reorder-synthesized-ivars.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/reorder-synthesized-ivars.m?rev=351461&r1=351460&r2=351461&view=diff ============================================================================== --- cfe/trunk/test/CodeGenObjC/reorder-synthesized-ivars.m (original) +++ cfe/trunk/test/CodeGenObjC/reorder-synthesized-ivars.m Thu Jan 17 10:18:53 2019 @@ -39,20 +39,20 @@ typedef signed char BOOL; @end // CHECK: @{{.*}} = private unnamed_addr constant [10 x i8] c"_boolean1 -// CHECK-NEXT: @{{.*}} = private unnamed_addr constant [10 x i8] c"_boolean2 -// CHECK-NEXT: @{{.*}} = private unnamed_addr constant [10 x i8] c"_boolean3 -// CHECK-NEXT: @{{.*}} = private unnamed_addr constant [10 x i8] c"_boolean4 -// CHECK-NEXT: @{{.*}} = private unnamed_addr constant [10 x i8] c"_boolean5 -// CHECK-NEXT: @{{.*}} = private unnamed_addr constant [10 x i8] c"_boolean6 -// CHECK-NEXT: @{{.*}} = private unnamed_addr constant [10 x i8] c"_boolean7 -// CHECK-NEXT: @{{.*}} = private unnamed_addr constant [10 x i8] c"_boolean8 -// CHECK-NEXT: @{{.*}} = private unnamed_addr constant [10 x i8] c"_boolean9 -// CHECK-NEXT: @{{.*}} = private unnamed_addr constant [9 x i8] c"_object1 -// CHECK-NEXT: @{{.*}} = private unnamed_addr constant [9 x i8] c"_object2 -// CHECK-NEXT: @{{.*}} = private unnamed_addr constant [9 x i8] c"_object3 -// CHECK-NEXT: @{{.*}} = private unnamed_addr constant [9 x i8] c"_object4 -// CHECK-NEXT: @{{.*}} = private unnamed_addr constant [9 x i8] c"_object5 -// CHECK-NEXT: @{{.*}} = private unnamed_addr constant [9 x i8] c"_object6 -// CHECK-NEXT: @{{.*}} = private unnamed_addr constant [9 x i8] c"_object7 -// CHECK-NEXT: @{{.*}} = private unnamed_addr constant [9 x i8] c"_object8 -// CHECK-NEXT: @{{.*}} = private unnamed_addr constant [9 x i8] c"_object9 +// CHECK: @{{.*}} = private unnamed_addr constant [10 x i8] c"_boolean2 +// CHECK: @{{.*}} = private unnamed_addr constant [10 x i8] c"_boolean3 +// CHECK: @{{.*}} = private unnamed_addr constant [10 x i8] c"_boolean4 +// CHECK: @{{.*}} = private unnamed_addr constant [10 x i8] c"_boolean5 +// CHECK: @{{.*}} = private unnamed_addr constant [10 x i8] c"_boolean6 +// CHECK: @{{.*}} = private unnamed_addr constant [10 x i8] c"_boolean7 +// CHECK: @{{.*}} = private unnamed_addr constant [10 x i8] c"_boolean8 +// CHECK: @{{.*}} = private unnamed_addr constant [10 x i8] c"_boolean9 +// CHECK: @{{.*}} = private unnamed_addr constant [9 x i8] c"_object1 +// CHECK: @{{.*}} = private unnamed_addr constant [9 x i8] c"_object2 +// CHECK: @{{.*}} = private unnamed_addr constant [9 x i8] c"_object3 +// CHECK: @{{.*}} = private unnamed_addr constant [9 x i8] c"_object4 +// CHECK: @{{.*}} = private unnamed_addr constant [9 x i8] c"_object5 +// CHECK: @{{.*}} = private unnamed_addr constant [9 x i8] c"_object6 +// CHECK: @{{.*}} = private unnamed_addr constant [9 x i8] c"_object7 +// CHECK: @{{.*}} = private unnamed_addr constant [9 x i8] c"_object8 +// CHECK: @{{.*}} = private unnamed_addr constant [9 x i8] c"_object9 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits