@@ -1060,15 +1060,6 @@ class CGObjCCommonMac : public CodeGen::CGObjCRuntime {
10601060 void GenerateDirectMethodPrologue (CodeGenFunction &CGF, llvm::Function *Fn,
10611061 const ObjCMethodDecl *OMD,
10621062 const ObjCContainerDecl *CD) override ;
1063- // / We split `GenerateDirectMethodPrologue` into the following two functions.
1064- // / The motivation is that nil check thunk function does the nil check, it
1065- // / definitely doesn't need _cmd.
1066- void GenerateObjCDirectNilCheck (CodeGenFunction &CGF,
1067- const ObjCMethodDecl *OMD,
1068- const ObjCContainerDecl *CD) override ;
1069- // / The inner function can decide if it needs `_cmd` for itself.
1070- void GenerateCmdIfNecessary (CodeGenFunction &CGF,
1071- const ObjCMethodDecl *OMD) override ;
10721063
10731064 void GenerateProtocol (const ObjCProtocolDecl *PD) override ;
10741065
@@ -3929,99 +3920,16 @@ llvm::Function *CGObjCCommonMac::GenerateDirectMethod(
39293920 return Fn;
39303921}
39313922
3932- void CGObjCCommonMac::GenerateObjCDirectNilCheck (CodeGenFunction &CGF,
3933- const ObjCMethodDecl *OMD,
3934- const ObjCContainerDecl *CD) {
3935- auto &Builder = CGF.Builder ;
3936- bool ReceiverCanBeNull = true ;
3937- auto selfAddr = CGF.GetAddrOfLocalVar (OMD->getSelfDecl ());
3938- auto selfValue = Builder.CreateLoad (selfAddr);
3939-
3940- // Generate:
3941- //
3942- // /* for class methods only to force class lazy initialization */
3943- // self = [self self];
3944- //
3945- // /* unless the receiver is never NULL */
3946- // if (self == nil) {
3947- // return (ReturnType){ };
3948- // }
3949-
3950- if (OMD->isClassMethod ()) {
3951- const ObjCInterfaceDecl *OID = cast<ObjCInterfaceDecl>(CD);
3952- assert (OID &&
3953- " GenerateDirectMethod() should be called with the Class Interface" );
3954- Selector SelfSel = GetNullarySelector (" self" , CGM.getContext ());
3955- auto ResultType = CGF.getContext ().getObjCIdType ();
3956- RValue result;
3957- CallArgList Args;
3958-
3959- // TODO: If this method is inlined, the caller might know that `self` is
3960- // already initialized; for example, it might be an ordinary Objective-C
3961- // method which always receives an initialized `self`, or it might have just
3962- // forced initialization on its own.
3963- //
3964- // We should find a way to eliminate this unnecessary initialization in such
3965- // cases in LLVM.
3966- result = GeneratePossiblySpecializedMessageSend (
3967- CGF, ReturnValueSlot (), ResultType, SelfSel, selfValue, Args, OID,
3968- nullptr , true );
3969- Builder.CreateStore (result.getScalarVal (), selfAddr);
3970-
3971- // Nullable `Class` expressions cannot be messaged with a direct method
3972- // so the only reason why the receive can be null would be because
3973- // of weak linking.
3974- ReceiverCanBeNull = isWeakLinkedClass (OID);
3975- }
3976-
3977- if (ReceiverCanBeNull) {
3978- llvm::BasicBlock *SelfIsNilBlock =
3979- CGF.createBasicBlock (" objc_direct_method.self_is_nil" );
3980- llvm::BasicBlock *ContBlock =
3981- CGF.createBasicBlock (" objc_direct_method.cont" );
3982-
3983- // if (self == nil) {
3984- auto selfTy = cast<llvm::PointerType>(selfValue->getType ());
3985- auto Zero = llvm::ConstantPointerNull::get (selfTy);
3986-
3987- llvm::MDBuilder MDHelper (CGM.getLLVMContext ());
3988- Builder.CreateCondBr (Builder.CreateICmpEQ (selfValue, Zero), SelfIsNilBlock,
3989- ContBlock, MDHelper.createBranchWeights (1 , 1 << 20 ));
3990-
3991- CGF.EmitBlock (SelfIsNilBlock);
3992-
3993- // return (ReturnType){ };
3994- auto retTy = OMD->getReturnType ();
3995- Builder.SetInsertPoint (SelfIsNilBlock);
3996- if (!retTy->isVoidType ()) {
3997- CGF.EmitNullInitialization (CGF.ReturnValue , retTy);
3998- }
3999- CGF.EmitBranchThroughCleanup (CGF.ReturnBlock );
4000- // }
4001-
4002- CGF.EmitBlock (ContBlock);
4003- Builder.SetInsertPoint (ContBlock);
4004- }
4005- }
4006- void CGObjCCommonMac::GenerateCmdIfNecessary (CodeGenFunction &CGF,
4007- const ObjCMethodDecl *OMD) {
4008- // only synthesize _cmd if it's referenced
4009- if (OMD->getCmdDecl ()->isUsed ()) {
4010- // `_cmd` is not a parameter to direct methods, so storage must be
4011- // explicitly declared for it.
4012- CGF.EmitVarDecl (*OMD->getCmdDecl ());
4013- CGF.Builder .CreateStore (GetSelector (CGF, OMD),
4014- CGF.GetAddrOfLocalVar (OMD->getCmdDecl ()));
4015- }
4016- }
4017-
40183923void CGObjCCommonMac::GenerateDirectMethodPrologue (
40193924 CodeGenFunction &CGF, llvm::Function *Fn, const ObjCMethodDecl *OMD,
40203925 const ObjCContainerDecl *CD) {
40213926 auto &Builder = CGF.Builder ;
40223927 bool ReceiverCanBeNull = true ;
40233928 auto selfAddr = CGF.GetAddrOfLocalVar (OMD->getSelfDecl ());
40243929 auto selfValue = Builder.CreateLoad (selfAddr);
3930+ bool shouldHaveNilCheckThunk =
3931+ CGF.CGM .shouldHaveNilCheckThunk (OMD) bool isNilCheckThunk =
3932+ shouldHaveNilCheckThunk && CGF.InnerFn ;
40253933
40263934 // Generate:
40273935 //
@@ -4063,7 +3971,10 @@ void CGObjCCommonMac::GenerateDirectMethodPrologue(
40633971 ReceiverCanBeNull = isWeakLinkedClass (OID);
40643972 }
40653973
4066- if (ReceiverCanBeNull) {
3974+ // Only emit nil check if this is a nil check thunk or the method
3975+ // decides that its receiver can be null
3976+ if (isNilCheckThunk ||
3977+ (!CGF.CGM .shouldHaveNilCheckThunk (OMD) && ReceiverCanBeNull)) {
40673978 llvm::BasicBlock *SelfIsNilBlock =
40683979 CGF.createBasicBlock (" objc_direct_method.self_is_nil" );
40693980 llvm::BasicBlock *ContBlock =
@@ -4093,14 +4004,19 @@ void CGObjCCommonMac::GenerateDirectMethodPrologue(
40934004 Builder.SetInsertPoint (ContBlock);
40944005 }
40954006
4096- // only synthesize _cmd if it's referenced
4097- if (OMD->getCmdDecl ()->isUsed ()) {
4007+ // Only synthesize _cmd if it's referenced
4008+ // However, a nil check thunk doesn't need _cmd even if it's referenced
4009+ if (!isNilCheckThunk && OMD->getCmdDecl ()->isUsed ()) {
40984010 // `_cmd` is not a parameter to direct methods, so storage must be
40994011 // explicitly declared for it.
41004012 CGF.EmitVarDecl (*OMD->getCmdDecl ());
41014013 Builder.CreateStore (GetSelector (CGF, OMD),
41024014 CGF.GetAddrOfLocalVar (OMD->getCmdDecl ()));
41034015 }
4016+
4017+ // It's possible that selfValue is never used.
4018+ if (selfValue->use_empty ())
4019+ selfValue->eraseFromParent ();
41044020}
41054021
41064022llvm::GlobalVariable *
0 commit comments