r362521 - [CodeGen][ObjC] Convert '[self alloc]' in a class method to a call to
Akira Hatanaka via cfe-commits
cfe-commits at lists.llvm.org
Tue Jun 4 09:29:58 PDT 2019
Author: ahatanak
Date: Tue Jun 4 09:29:58 2019
New Revision: 362521
URL: http://llvm.org/viewvc/llvm-project?rev=362521&view=rev
Log:
[CodeGen][ObjC] Convert '[self alloc]' in a class method to a call to
'objc_alloc(self)'
Also convert '[[self alloc] init]' in a class method to a call to
'objc_alloc_init(self)'.
rdar://problem/50855121
Differential Revision: https://reviews.llvm.org/D62643
Modified:
cfe/trunk/lib/CodeGen/CGObjC.cpp
cfe/trunk/test/CodeGenObjC/convert-messages-to-runtime-calls.m
cfe/trunk/test/CodeGenObjC/objc-alloc-init.m
Modified: cfe/trunk/lib/CodeGen/CGObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjC.cpp?rev=362521&r1=362520&r2=362521&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjC.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjC.cpp Tue Jun 4 09:29:58 2019
@@ -383,10 +383,12 @@ tryGenerateSpecializedMessageSend(CodeGe
if (isClassMessage &&
Runtime.shouldUseRuntimeFunctionsForAlloc() &&
ResultType->isObjCObjectPointerType()) {
- // [Foo alloc] -> objc_alloc(Foo)
+ // [Foo alloc] -> objc_alloc(Foo) or
+ // [self alloc] -> objc_alloc(self)
if (Sel.isUnarySelector() && Sel.getNameForSlot(0) == "alloc")
return CGF.EmitObjCAlloc(Receiver, CGF.ConvertType(ResultType));
- // [Foo allocWithZone:nil] -> objc_allocWithZone(Foo)
+ // [Foo allocWithZone:nil] -> objc_allocWithZone(Foo) or
+ // [self allocWithZone:nil] -> objc_allocWithZone(self)
if (Sel.isKeywordSelector() && Sel.getNumArgs() == 1 &&
Args.size() == 1 && Args.front().getType()->isPointerType() &&
Sel.getNameForSlot(0) == "allocWithZone") {
@@ -444,22 +446,38 @@ tryEmitSpecializedAllocInit(CodeGenFunct
Sel.getNameForSlot(0) != "init")
return None;
- // Okay, this is '[receiver init]', check if 'receiver' is '[cls alloc]'.
+ // Okay, this is '[receiver init]', check if 'receiver' is '[cls alloc]' or
+ // we are in an ObjC class method and 'receiver' is '[self alloc]'.
auto *SubOME =
- dyn_cast<ObjCMessageExpr>(OME->getInstanceReceiver()->IgnoreParens());
+ dyn_cast<ObjCMessageExpr>(OME->getInstanceReceiver()->IgnoreParenCasts());
if (!SubOME)
return None;
Selector SubSel = SubOME->getSelector();
- if (SubOME->getReceiverKind() != ObjCMessageExpr::Class ||
- !SubOME->getType()->isObjCObjectPointerType() ||
+
+ // Check if we are in an ObjC class method and the receiver expression is
+ // 'self'.
+ const Expr *SelfInClassMethod = nullptr;
+ if (const auto *CurMD = dyn_cast_or_null<ObjCMethodDecl>(CGF.CurFuncDecl))
+ if (CurMD->isClassMethod())
+ if ((SelfInClassMethod = SubOME->getInstanceReceiver()))
+ if (!SelfInClassMethod->isObjCSelfExpr())
+ SelfInClassMethod = nullptr;
+
+ if ((SubOME->getReceiverKind() != ObjCMessageExpr::Class &&
+ !SelfInClassMethod) || !SubOME->getType()->isObjCObjectPointerType() ||
!SubSel.isUnarySelector() || SubSel.getNameForSlot(0) != "alloc")
return None;
- QualType ReceiverType = SubOME->getClassReceiver();
- const ObjCObjectType *ObjTy = ReceiverType->getAs<ObjCObjectType>();
- const ObjCInterfaceDecl *ID = ObjTy->getInterface();
- assert(ID && "null interface should be impossible here");
- llvm::Value *Receiver = CGF.CGM.getObjCRuntime().GetClass(CGF, ID);
+ llvm::Value *Receiver;
+ if (SelfInClassMethod) {
+ Receiver = CGF.EmitScalarExpr(SelfInClassMethod);
+ } else {
+ QualType ReceiverType = SubOME->getClassReceiver();
+ const ObjCObjectType *ObjTy = ReceiverType->getAs<ObjCObjectType>();
+ const ObjCInterfaceDecl *ID = ObjTy->getInterface();
+ assert(ID && "null interface should be impossible here");
+ Receiver = CGF.CGM.getObjCRuntime().GetClass(CGF, ID);
+ }
return CGF.EmitObjCAllocInit(Receiver, CGF.ConvertType(OME->getType()));
}
@@ -507,6 +525,10 @@ RValue CodeGenFunction::EmitObjCMessageE
switch (E->getReceiverKind()) {
case ObjCMessageExpr::Instance:
ReceiverType = E->getInstanceReceiver()->getType();
+ if (auto *OMD = dyn_cast_or_null<ObjCMethodDecl>(CurFuncDecl))
+ if (OMD->isClassMethod())
+ if (E->getInstanceReceiver()->isObjCSelfExpr())
+ isClassMessage = true;
if (retainSelf) {
TryEmitResult ter = tryEmitARCRetainScalarExpr(*this,
E->getInstanceReceiver());
Modified: cfe/trunk/test/CodeGenObjC/convert-messages-to-runtime-calls.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/convert-messages-to-runtime-calls.m?rev=362521&r1=362520&r2=362521&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenObjC/convert-messages-to-runtime-calls.m (original)
+++ cfe/trunk/test/CodeGenObjC/convert-messages-to-runtime-calls.m Tue Jun 4 09:29:58 2019
@@ -150,6 +150,34 @@ float test_cannot_message_return_float(C
return [c retain];
}
+ at interface TestSelf
++ (instancetype)alloc;
++ (instancetype)allocWithZone:(void*)zone;
++ (id)classMeth;
+- (id)instanceMeth;
+ at end
+
+ at implementation TestSelf
+// CHECK-LABEL: define internal i8* @"\01+[TestSelf classMeth]"(
++ (id)classMeth {
+ // MSGS: {{call.*@objc_msgSend}}
+ // MSGS: {{call.*@objc_msgSend}}
+ // CALLS: {{call.*@objc_allocWithZone\(}}
+ // CALLS: {{call.*@objc_alloc\(}}
+ [self allocWithZone:nil];
+ return [self alloc];
+}
+// CHECK-LABEL: define internal i8* @"\01-[TestSelf instanceMeth]"(
+- (id)instanceMeth {
+ // MSGS: {{call.*@objc_msgSend}}
+ // MSGS: {{call.*@objc_msgSend}}
+ // CALLS: {{call.*@objc_msgSend}}
+ // CALLS: {{call.*@objc_msgSend}}
+ [self allocWithZone:nil];
+ return [self alloc];
+}
+ at end
+
@interface NSString : NSObject
+ (void)retain_self;
- (void)retain_super;
Modified: cfe/trunk/test/CodeGenObjC/objc-alloc-init.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/objc-alloc-init.m?rev=362521&r1=362520&r2=362521&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenObjC/objc-alloc-init.m (original)
+++ cfe/trunk/test/CodeGenObjC/objc-alloc-init.m Tue Jun 4 09:29:58 2019
@@ -23,14 +23,20 @@ void f() {
@interface Y : X
+(void)meth;
+-(void)instanceMeth;
@end
@implementation Y
+(void)meth {
[[self alloc] init];
+ // OPTIMIZED: call i8* @objc_alloc_init(
+ // NOT_OPTIMIZED: call i8* @objc_alloc(
+}
+-(void)instanceMeth {
// EITHER-NOT: call i8* @objc_alloc
// EITHER: call {{.*}} @objc_msgSend
// EITHER: call {{.*}} @objc_msgSend
+ [[self alloc] init];
}
@end
More information about the cfe-commits
mailing list