[llvm] 6770fbb - [ObjC][ARC] Delete ARC runtime calls that take inert phi values

Akira Hatanaka via llvm-commits llvm-commits at lists.llvm.org
Fri Feb 7 16:31:54 PST 2020


Author: Akira Hatanaka
Date: 2020-02-07T16:31:36-08:00
New Revision: 6770fbb31450db15d8d4a2ac7f0ce70eaf2acc5f

URL: https://github.com/llvm/llvm-project/commit/6770fbb31450db15d8d4a2ac7f0ce70eaf2acc5f
DIFF: https://github.com/llvm/llvm-project/commit/6770fbb31450db15d8d4a2ac7f0ce70eaf2acc5f.diff

LOG: [ObjC][ARC] Delete ARC runtime calls that take inert phi values

This improves on the following patch, which removed ARC runtime calls
taking inert global variables:

https://reviews.llvm.org/D62433

rdar://problem/59137105

Added: 
    

Modified: 
    llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp
    llvm/test/Transforms/ObjCARC/inert-global.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp b/llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp
index b80c1675050b..7dbb95faaf85 100644
--- a/llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp
+++ b/llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp
@@ -877,23 +877,43 @@ void ObjCARCOpt::OptimizeIndividualCalls(Function &F) {
   optimizeDelayedAutoreleaseRV();
 }
 
+/// This function returns true if the value is inert. An ObjC ARC runtime call
+/// taking an inert operand can be safely deleted.
+static bool isInertARCValue(Value *V) {
+  V = V->stripPointerCasts();
+
+  if (IsNullOrUndef(V))
+    return true;
+
+  // See if this is a global attribute annotated with an 'objc_arc_inert'.
+  if (auto *GV = dyn_cast<GlobalVariable>(V))
+    if (GV->hasAttribute("objc_arc_inert"))
+      return true;
+
+  if (auto PN = dyn_cast<PHINode>(V)) {
+    // Look through phis's operands.
+    for (Value *Opnd : PN->incoming_values())
+      if (!isInertARCValue(Opnd))
+        return false;
+    return true;
+  }
+
+  return false;
+}
+
 void ObjCARCOpt::OptimizeIndividualCallImpl(
     Function &F, DenseMap<BasicBlock *, ColorVector> &BlockColors,
     Instruction *Inst, ARCInstKind Class, const Value *Arg) {
   LLVM_DEBUG(dbgs() << "Visiting: Class: " << Class << "; " << *Inst << "\n");
 
-  // Some of the ARC calls can be deleted if their arguments are global
-  // variables that are inert in ARC.
-  if (IsNoopOnGlobal(Class)) {
-    Value *Opnd = Inst->getOperand(0);
-    if (auto *GV = dyn_cast<GlobalVariable>(Opnd->stripPointerCasts()))
-      if (GV->hasAttribute("objc_arc_inert")) {
-        if (!Inst->getType()->isVoidTy())
-          Inst->replaceAllUsesWith(Opnd);
-        Inst->eraseFromParent();
-        return;
-      }
-  }
+  // We can delete this call if it takes an inert value.
+  if (IsNoopOnGlobal(Class))
+    if (isInertARCValue(Inst->getOperand(0))) {
+      if (!Inst->getType()->isVoidTy())
+        Inst->replaceAllUsesWith(Inst->getOperand(0));
+      Inst->eraseFromParent();
+      return;
+    }
 
   switch (Class) {
   default:

diff  --git a/llvm/test/Transforms/ObjCARC/inert-global.ll b/llvm/test/Transforms/ObjCARC/inert-global.ll
index 4bb9a809a0f2..c23d2f98b949 100644
--- a/llvm/test/Transforms/ObjCARC/inert-global.ll
+++ b/llvm/test/Transforms/ObjCARC/inert-global.ll
@@ -54,6 +54,39 @@ define internal void @__globalBlock_block_invoke(i8* nocapture readnone) {
   ret void
 }
 
+; CHECK: define %[[V0:.*]]* @test_conditional0(
+; CHECK: %[[PHI0:.*]] = phi %[[V0]]* [ bitcast (%struct.__NSConstantString_tag* @_unnamed_cfstring_ to %[[V0]]*), %{{.*}} ], [ null, %{{.*}} ]
+
+; CHECK: %[[PHI1:.*]] = phi %[[V0]]* [ bitcast (%struct.__NSConstantString_tag* @_unnamed_cfstring_ to %[[V0]]*), %{{.*}} ], [ %[[PHI0]], %{{.*}} ]
+; CHECK-NEXT: %[[PHI2:.*]] = phi %[[V0]]* [ bitcast (%struct.__NSConstantString_tag* @_unnamed_cfstring_ to %[[V0]]*), %{{.*}} ], [ %{{.*}}, %{{.*}} ]
+; CHECK-NEXT: %[[V2:.*]] = bitcast %[[V0]]* %[[PHI1]] to i8*
+; CHECK-NEXT: %[[V4:.*]] = bitcast %[[V0]]* %[[PHI2]] to i8*
+; CHECK-NEXT: %[[V5:.*]] = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %[[V4]])
+; CHECK-NEXT: ret %[[V0]]* %[[PHI2]]
+
+define %0* @test_conditional0(i32 %i, %0* %b) {
+entry:
+  %v0 = icmp eq i32 %i, 1
+  br i1 %v0, label %bb2, label %bb1
+
+bb1:
+  %v1 = icmp eq i32 %i, 2
+  br i1 %v1, label %bb2, label %return
+
+bb2:
+  %phi0 = phi %0* [ bitcast (%struct.__NSConstantString_tag* @_unnamed_cfstring_ to %0*), %entry ], [ null, %bb1 ]
+  br label %return
+
+return:
+  %phi1 = phi %0* [ bitcast (%struct.__NSConstantString_tag* @_unnamed_cfstring_ to %0*), %bb1 ], [ %phi0, %bb2 ]
+  %phi2 = phi %0* [ bitcast (%struct.__NSConstantString_tag* @_unnamed_cfstring_ to %0*), %bb1 ], [ %b, %bb2 ]
+  %v2 = bitcast %0* %phi1 to i8*
+  %v3 = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %v2)
+  %v4 = bitcast %0* %phi2 to i8*
+  %v5 = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %v4)
+  ret %0* %phi2
+}
+
 declare void @foo()
 
 declare i8* @llvm.objc.retain(i8*) local_unnamed_addr


        


More information about the llvm-commits mailing list