[llvm] [ObjCARC] Delete empty autoreleasepools with no autoreleases in them (PR #144788)
Jon Roelofs via llvm-commits
llvm-commits at lists.llvm.org
Wed Jun 18 15:09:03 PDT 2025
================
@@ -2485,6 +2489,107 @@ bool ObjCARCOpt::run(Function &F, AAResults &AA) {
return Changed;
}
+/// Optimize autorelease pools by eliminating empty push/pop pairs.
+void ObjCARCOpt::OptimizeAutoreleasePools(Function &F) {
+ LLVM_DEBUG(dbgs() << "\n== ObjCARCOpt::OptimizeAutoreleasePools ==\n");
+
+ // Track empty autorelease pool push/pop pairs
+ SmallVector<std::pair<CallInst *, CallInst *>, 4> EmptyPoolPairs;
+
+ // Process each basic block independently.
+ // TODO: Can we optimize inter-block autorelease pool pairs?
+ // This would involve tracking autorelease pool state across blocks.
+ for (BasicBlock &BB : F) {
+ CallInst *PendingPush = nullptr;
+ bool HasAutoreleaseInScope = false;
+
+ for (Instruction &Inst : BB) {
+ ARCInstKind Class = GetBasicARCInstKind(&Inst);
+
+ switch (Class) {
+ case ARCInstKind::AutoreleasepoolPush: {
+ // Start tracking a new autorelease pool scope
+ PendingPush = cast<CallInst>(&Inst);
+ HasAutoreleaseInScope = false;
+ LLVM_DEBUG(dbgs() << "Found autorelease pool push: " << *PendingPush
+ << "\n");
+ break;
+ }
+
+ case ARCInstKind::AutoreleasepoolPop: {
+ CallInst *Pop = cast<CallInst>(&Inst);
+
+ if (PendingPush) {
+ // Check if this pop matches the pending push by comparing the token
+ Value *PopArg = Pop->getArgOperand(0);
+ bool IsMatchingPop = (PopArg == PendingPush);
+
+ // Also handle bitcast case
+ if (!IsMatchingPop && isa<BitCastInst>(PopArg)) {
+ Value *BitcastSrc = cast<BitCastInst>(PopArg)->getOperand(0);
+ IsMatchingPop = (BitcastSrc == PendingPush);
+ }
+
+ if (IsMatchingPop && !HasAutoreleaseInScope) {
+ LLVM_DEBUG(dbgs() << "Eliminating empty autorelease pool pair: "
+ << *PendingPush << " and " << *Pop << "\n");
+
+ // Store the pair for careful deletion later
+ EmptyPoolPairs.push_back({PendingPush, Pop});
+
+ Changed = true;
+ ++NumNoops;
+ }
+ }
+
+ PendingPush = nullptr;
+ HasAutoreleaseInScope = false;
+ break;
+ }
+ case ARCInstKind::CallOrUser:
+ case ARCInstKind::Call:
+ case ARCInstKind::Autorelease:
+ case ARCInstKind::AutoreleaseRV: {
+ // Track that we have autorelease calls in the current pool scope
+ if (PendingPush) {
+ HasAutoreleaseInScope = true;
+ LLVM_DEBUG(
+ dbgs()
+ << "Found autorelease or potiential autorelease in pool scope: "
+ << Inst << "\n");
+ }
+ break;
+ }
+
+ default:
+ break;
+ }
+ }
+ }
+
+ // Handle empty pool pairs carefully to avoid use-after-delete
+ SmallVector<CallInst *, 8> DeadInsts;
+ for (auto &Pair : EmptyPoolPairs) {
+ CallInst *Push = Pair.first;
+ CallInst *Pop = Pair.second;
+
+ // Replace the pop's argument with poison to break dependencies
+ Value *PoisonToken = PoisonValue::get(Push->getType());
+ Pop->setArgOperand(0, PoisonToken);
+
+ LLVM_DEBUG(dbgs() << "Erasing empty pool pair: " << *Push << " and " << *Pop
----------------
jroelofs wrote:
It would be great to have a remark for this.
https://github.com/llvm/llvm-project/pull/144788
More information about the llvm-commits
mailing list