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

Reply via email to