[PATCH] [CodeGen] tighten objc ivar invariant.load attribution

Saleem Abdulrasool compnerd at compnerd.org
Thu Feb 14 15:14:45 PST 2013


On Thu, Feb 14, 2013 at 11:23 AM, John McCall <rjmccall at apple.com> wrote:
> On Feb 14, 2013, at 9:37 AM, Saleem Abdulrasool <compnerd at compnerd.org> wrote:
>> Add a few test cases and fix an inverted check.
>>
>> Hi rjmccall,
>>
>> http://llvm-reviews.chandlerc.com/D406
>>
>> CHANGE SINCE LAST DIFF
>>  http://llvm-reviews.chandlerc.com/D406?vs=976&id=982#toc
>>
>> Files:
>>  lib/CodeGen/CGObjCMac.cpp
>>  test/CodeGenObjC/ivar-invariant-unimplemented.m
>>  test/CodeGenObjC/ivar-invariant.m
>>
>> Index: lib/CodeGen/CGObjCMac.cpp
>> ===================================================================
>> --- lib/CodeGen/CGObjCMac.cpp
>> +++ lib/CodeGen/CGObjCMac.cpp
>> @@ -6449,10 +6449,23 @@
>>                                                unsigned CVRQualifiers) {
>>   ObjCInterfaceDecl *ID = ObjectTy->getAs<ObjCObjectType>()->getInterface();
>>   llvm::Value *Offset = EmitIvarOffset(CGF, ID, Ivar);
>> +
>> +  // 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.
>
> Go ahead and tweak the interface to propagate through an optional
> base expression and then implement your check based on that.

Do you mind if I were to do that as a follow on change?

>>   if (llvm::LoadInst *LI = dyn_cast<llvm::LoadInst>(Offset))
>
> I know this is old code, but you can just use cast<llvm::LoadInst> here;
> the dyn_cast is not necessary.

Done.

>> -    LI->setMetadata(CGM.getModule().getMDKindID("invariant.load"),
>> -                   llvm::MDNode::get(VMContext,
>> -                   ArrayRef<llvm::Value*>()));
>> +    if (dyn_cast<ObjCMethodDecl>(CGF.CurFuncDecl))
>> +      if (Ivar->getContainingInterface()->isSuperClassOf(ID))
>
> Please extract this condition out into a separate function.

Done.

>> +        LI->setMetadata(CGM.getModule().getMDKindID("invariant.load"),
>> +                        llvm::MDNode::get(VMContext, ArrayRef<llvm::Value*>()));
>> +
>>   return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
>>                                   Offset);
>> }
>> Index: test/CodeGenObjC/ivar-invariant-unimplemented.m
>> ===================================================================
>> --- /dev/null
>> +++ test/CodeGenObjC/ivar-invariant-unimplemented.m
>> @@ -0,0 +1,32 @@
>> +// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -x objective-c %s -o - | FileCheck %s
>> +// XFAIL: *
>
> We usually don't add xfailed tests for missing optimizations and features.
> The proper way to keep track of this is in the bug tracker, not the test suite.

Fair enough.  Removed.

>> Index: test/CodeGenObjC/ivar-invariant.m
>> ===================================================================
>> --- /dev/null
>> +++ test/CodeGenObjC/ivar-invariant.m
>> @@ -0,0 +1,55 @@
>> +// 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
>
> You can't test for LLVM IR names like this, because we strip names in non-asserts
> builds.  If you actually needed the name for later test lines, you would need to match
> a pattern against it, like so:
>   [[IVAR:%.*]] = load ...
> In this case, you don't, so you're fine.

Changed anyways.

>> +
>> +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"
>> +// CHECK-NOT: %ivar = load i64* @"OBJC_IVAR_$_Derived.member", !invariant.load
>
> This is not how CHECK-NOT works.  What you actually want to do is
>   //  CHECK: %ivar = load i64* @"OBJC_IVAR_$_Derived.member"{{$}}

Thanks, changed.

> John.



-- 
Saleem Abdulrasool
compnerd (at) compnerd (dot) org



More information about the cfe-commits mailing list