[llvm] 4dcc029 - [ObjC][ARC] Keep track of phis that have been discovered to avoid an

Akira Hatanaka via llvm-commits llvm-commits at lists.llvm.org
Fri Feb 7 20:33:44 PST 2020


Author: Akira Hatanaka
Date: 2020-02-07T20:33:11-08:00
New Revision: 4dcc029edbe4bd5e30d4f0cdcf123ea4ed2b6418

URL: https://github.com/llvm/llvm-project/commit/4dcc029edbe4bd5e30d4f0cdcf123ea4ed2b6418
DIFF: https://github.com/llvm/llvm-project/commit/4dcc029edbe4bd5e30d4f0cdcf123ea4ed2b6418.diff

LOG: [ObjC][ARC] Keep track of phis that have been discovered to avoid an
infinite loop

This fixes a bug introduced in 6770fbb31450db15d8d4a2ac7f0ce70eaf2acc5f.

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 7dbb95faaf85..adab7491d27a 100644
--- a/llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp
+++ b/llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp
@@ -879,7 +879,7 @@ void ObjCARCOpt::OptimizeIndividualCalls(Function &F) {
 
 /// 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) {
+static bool isInertARCValue(Value *V, SmallPtrSet<Value *, 1> &VisitedPhis) {
   V = V->stripPointerCasts();
 
   if (IsNullOrUndef(V))
@@ -891,9 +891,12 @@ static bool isInertARCValue(Value *V) {
       return true;
 
   if (auto PN = dyn_cast<PHINode>(V)) {
+    // Ignore this phi if it has already been discovered.
+    if (!VisitedPhis.insert(PN).second)
+      return true;
     // Look through phis's operands.
     for (Value *Opnd : PN->incoming_values())
-      if (!isInertARCValue(Opnd))
+      if (!isInertARCValue(Opnd, VisitedPhis))
         return false;
     return true;
   }
@@ -907,8 +910,10 @@ void ObjCARCOpt::OptimizeIndividualCallImpl(
   LLVM_DEBUG(dbgs() << "Visiting: Class: " << Class << "; " << *Inst << "\n");
 
   // We can delete this call if it takes an inert value.
+  SmallPtrSet<Value *, 1> VisitedPhis;
+
   if (IsNoopOnGlobal(Class))
-    if (isInertARCValue(Inst->getOperand(0))) {
+    if (isInertARCValue(Inst->getOperand(0), VisitedPhis)) {
       if (!Inst->getType()->isVoidTy())
         Inst->replaceAllUsesWith(Inst->getOperand(0));
       Inst->eraseFromParent();

diff  --git a/llvm/test/Transforms/ObjCARC/inert-global.ll b/llvm/test/Transforms/ObjCARC/inert-global.ll
index c23d2f98b949..464d78b715e5 100644
--- a/llvm/test/Transforms/ObjCARC/inert-global.ll
+++ b/llvm/test/Transforms/ObjCARC/inert-global.ll
@@ -8,6 +8,7 @@
 @.str = private unnamed_addr constant [4 x i8] c"abc\00", section "__TEXT,__cstring,cstring_literals", align 1
 @.str1 = private unnamed_addr constant [4 x i8] c"def\00", section "__TEXT,__cstring,cstring_literals", align 1
 @_unnamed_cfstring_ = private global %struct.__NSConstantString_tag { i32* getelementptr inbounds ([0 x i32], [0 x i32]* @__CFConstantStringClassReference, i32 0, i32 0), i32 1992, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i64 3 }, section "__DATA,__cfstring", align 8 #0
+ at _unnamed_cfstring_.1 = private global %struct.__NSConstantString_tag { i32* getelementptr inbounds ([0 x i32], [0 x i32]* @__CFConstantStringClassReference, i32 0, i32 0), i32 1992, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str1, i32 0, i32 0), i64 3 }, section "__DATA,__cfstring", align 8 #0
 @_unnamed_cfstring_wo_attr = private global %struct.__NSConstantString_tag { i32* getelementptr inbounds ([0 x i32], [0 x i32]* @__CFConstantStringClassReference, i32 0, i32 0), i32 1992, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str1, i32 0, i32 0), i64 3 }, section "__DATA,__cfstring", align 8
 @_NSConcreteGlobalBlock = external global i8*
 @.str.1 = private unnamed_addr constant [6 x i8] c"v8@?0\00", align 1
@@ -87,6 +88,40 @@ return:
   ret %0* %phi2
 }
 
+; CHECK-LABEL: define void @test_conditional1(
+; CHECK-NOT: @llvm.objc
+; CHECK: ret void
+
+define void @test_conditional1(i32 %i) {
+entry:
+  %v0 = add nsw i32 %i, -1
+  %c1 = icmp eq i32 %v0, 0
+  br i1 %c1, label %while.end, label %while.body
+
+while.body:
+  %v1 = phi i32 [ %v5, %if.end ], [ %v0, %entry ]
+  %v2 = phi i8* [ %v4, %if.end ], [ bitcast (%struct.__NSConstantString_tag* @_unnamed_cfstring_.1 to i8*), %entry ]
+  %v3 = tail call i8* @llvm.objc.retain(i8* %v2)
+  %cmp = icmp eq i32 %v1, 2
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  call void @llvm.objc.release(i8* %v2)
+  br label %if.end
+
+if.end:
+  %v4 = phi i8* [ bitcast (%struct.__NSConstantString_tag* @_unnamed_cfstring_ to i8*), %if.then ], [ %v2, %while.body ]
+  call void @llvm.objc.release(i8* %v2)
+  %v5 = add nsw i32 %v1, -1
+  %tobool = icmp eq i32 %v5, 0
+  br i1 %tobool, label %while.end, label %while.body
+
+while.end:
+  %v6 = phi i8* [ null, %entry ], [ %v4, %if.end ]
+  call void @llvm.objc.release(i8* %v6)
+  ret void
+}
+
 declare void @foo()
 
 declare i8* @llvm.objc.retain(i8*) local_unnamed_addr


        


More information about the llvm-commits mailing list