https://github.com/DataCorrupted created https://github.com/llvm/llvm-project/pull/170619
In many cases we can infer that class object has been realized >From 110198ae0bd837972d4d9ff013494fbf3206b7a4 Mon Sep 17 00:00:00 2001 From: Peter Rong <[email protected]> Date: Wed, 3 Dec 2025 22:45:04 -0800 Subject: [PATCH] [ExposeObjCDirect] Optimizations In many cases we can infer that class object has been realized --- clang/lib/CodeGen/CGObjCRuntime.cpp | 63 +++++++++++++++++++++++++++++ clang/lib/CodeGen/CGObjCRuntime.h | 6 +-- 2 files changed, 66 insertions(+), 3 deletions(-) diff --git a/clang/lib/CodeGen/CGObjCRuntime.cpp b/clang/lib/CodeGen/CGObjCRuntime.cpp index 38efd4d865284..fd227d9645ac1 100644 --- a/clang/lib/CodeGen/CGObjCRuntime.cpp +++ b/clang/lib/CodeGen/CGObjCRuntime.cpp @@ -415,6 +415,69 @@ bool CGObjCRuntime::canMessageReceiverBeNull( bool CGObjCRuntime::canClassObjectBeUnrealized( const ObjCInterfaceDecl *CalleeClassDecl, CodeGenFunction &CGF) const { + if (!CalleeClassDecl) + return true; + + // Heuristic 1: +load method on this class + // If the class has a +load method, it's realized when the binary is loaded. + ASTContext &Ctx = CGM.getContext(); + const IdentifierInfo *LoadII = &Ctx.Idents.get("load"); + Selector LoadSel = Ctx.Selectors.getSelector(0, &LoadII); + + // TODO: if one if the child had +load, this class is guaranteed to be + // realized as well. We should have a translation unit specific map that + // precomputes all classes that are realized, and just do a lookup here. + // But we need to measure how expensive it is to create a map like that. + if (CalleeClassDecl->lookupClassMethod(LoadSel)) + return false; // This class has +load, so it's already realized + + // Heuristic 2: using Self / Super + // If we're currently executing a method of ClassDecl (or a subclass), + // then ClassDecl must already be realized. + if (const auto *CurMethod = + dyn_cast_or_null<ObjCMethodDecl>(CGF.CurCodeDecl)) { + const ObjCInterfaceDecl *CallerCalssDecl = CurMethod->getClassInterface(); + if (CallerCalssDecl && CalleeClassDecl->isSuperClassOf(CallerCalssDecl)) + return false; + } + + // Heuristic 3: previously realized + // Heuristic 3.1: Walk through the current BasicBlock looking for calls that + // realize the class. All heuristics in this cluster share the same + // implementation pattern. + auto *BB = CGF.Builder.GetInsertBlock(); + if (!BB) + return true; // No current block, assume unrealized + + llvm::StringRef CalleeClassName = CalleeClassDecl->getName(); + + // Heuristic 3.2 / TODO: If realization happened in a dominating block, the + // class is realized Requires Dominator tree analysis. There should be an + // outer loop `for (BB: DominatingBasicBlocks)` + for (const auto &Inst : *BB) { + // Check if this is a call instruction + const auto *Call = llvm::dyn_cast<llvm::CallInst>(&Inst); + if (!Call) + continue; + llvm::Function *CalledFunc = Call->getCalledFunction(); + if (!CalledFunc) + continue; + + llvm::StringRef FuncNamePtr = CalledFunc->getName(); + // Skip the \01 prefix if present + if (FuncNamePtr.starts_with("\01")) + FuncNamePtr = FuncNamePtr.drop_front(1); + // Check for instance method calls: "-[ClassName methodName]" + // or class method calls: "+[ClassName methodName]" + // Also check for thunks: "-[ClassName methodName]_thunk" + if ((FuncNamePtr.starts_with("-[") || FuncNamePtr.starts_with("+["))) { + FuncNamePtr = FuncNamePtr.drop_front(2); + // TODO: if the current class is the super class of the function that's + // used, it should've been realized as well + if (FuncNamePtr.starts_with(CalleeClassName)) + return false; + } + } // Otherwise, assume it can be unrealized. return true; diff --git a/clang/lib/CodeGen/CGObjCRuntime.h b/clang/lib/CodeGen/CGObjCRuntime.h index 8d5ee1310e51f..c49eef3ad30c1 100644 --- a/clang/lib/CodeGen/CGObjCRuntime.h +++ b/clang/lib/CodeGen/CGObjCRuntime.h @@ -226,7 +226,7 @@ class CGObjCRuntime { virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD, const ObjCContainerDecl *CD) = 0; -/// Generates precondition checks for direct Objective-C Methods. + /// Generates precondition checks for direct Objective-C Methods. /// This includes [self self] for class methods and nil checks. virtual void GenerateDirectMethodsPreconditionCheck( CodeGenFunction &CGF, llvm::Function *Fn, const ObjCMethodDecl *OMD, @@ -345,8 +345,8 @@ class CGObjCRuntime { virtual bool canMessageReceiverBeNull(CodeGenFunction &CGF, const ObjCMethodDecl *method, bool isSuper, - const ObjCInterfaceDecl *classReceiver, - llvm::Value *receiver); + const ObjCInterfaceDecl *classReceiver, + llvm::Value *receiver); /// Check if a class object can be unrealized (not yet initialized). /// Returns true if the class may be unrealized, false if provably realized. _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
