[llvm] 2958615 - [ObjC][ARC] Fix non-deterministic behavior in ProvenanceAnalysis

Akira Hatanaka via llvm-commits llvm-commits at lists.llvm.org
Tue Nov 8 15:06:56 PST 2022


Author: Akira Hatanaka
Date: 2022-11-08T15:05:25-08:00
New Revision: 295861514e0d1e48df2918b630dd692ac27ee0de

URL: https://github.com/llvm/llvm-project/commit/295861514e0d1e48df2918b630dd692ac27ee0de
DIFF: https://github.com/llvm/llvm-project/commit/295861514e0d1e48df2918b630dd692ac27ee0de.diff

LOG: [ObjC][ARC] Fix non-deterministic behavior in ProvenanceAnalysis

ProvenanceAnalysis::relatedCheck was giving different answers depending
on the order in which the pointers were passed.

Specifically, it was returning different values when A and B were both
loads and were both referring to identifiable objects, but only one was
used by a store instruction.

Added: 
    

Modified: 
    llvm/lib/Transforms/ObjCARC/ProvenanceAnalysis.cpp
    llvm/test/Transforms/ObjCARC/related-check.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/ObjCARC/ProvenanceAnalysis.cpp b/llvm/lib/Transforms/ObjCARC/ProvenanceAnalysis.cpp
index f447c2a23f0d..845038b8b82e 100644
--- a/llvm/lib/Transforms/ObjCARC/ProvenanceAnalysis.cpp
+++ b/llvm/lib/Transforms/ObjCARC/ProvenanceAnalysis.cpp
@@ -134,22 +134,19 @@ bool ProvenanceAnalysis::relatedCheck(const Value *A, const Value *B) {
   bool BIsIdentified = IsObjCIdentifiedObject(B);
 
   // An ObjC-Identified object can't alias a load if it is never locally stored.
-  if (AIsIdentified) {
-    // Check for an obvious escape.
-    if (isa<LoadInst>(B))
-      return IsStoredObjCPointer(A);
-    if (BIsIdentified) {
-      // Check for an obvious escape.
-      if (isa<LoadInst>(A))
-        return IsStoredObjCPointer(B);
-      // Both pointers are identified and escapes aren't an evident problem.
-      return false;
-    }
-  } else if (BIsIdentified) {
-    // Check for an obvious escape.
-    if (isa<LoadInst>(A))
-      return IsStoredObjCPointer(B);
-  }
+
+  // Check for an obvious escape.
+  if ((AIsIdentified && isa<LoadInst>(B) && !IsStoredObjCPointer(A)) ||
+      (BIsIdentified && isa<LoadInst>(A) && !IsStoredObjCPointer(B)))
+    return false;
+
+  if ((AIsIdentified && isa<LoadInst>(B)) ||
+      (BIsIdentified && isa<LoadInst>(A)))
+    return true;
+
+  // Both pointers are identified and escapes aren't an evident problem.
+  if (AIsIdentified && BIsIdentified && !isa<LoadInst>(A) && !isa<LoadInst>(B))
+    return false;
 
    // Special handling for PHI and Select.
   if (const PHINode *PN = dyn_cast<PHINode>(A))

diff  --git a/llvm/test/Transforms/ObjCARC/related-check.ll b/llvm/test/Transforms/ObjCARC/related-check.ll
index 293297d5f202..91814b9fcf1c 100644
--- a/llvm/test/Transforms/ObjCARC/related-check.ll
+++ b/llvm/test/Transforms/ObjCARC/related-check.ll
@@ -28,6 +28,7 @@
 @_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 ([3 x i8], [3 x i8]* @.str.1, i32 0, i32 0), i64 2 }, section "__DATA,__cfstring", align 8 #0
 @OBJC_METH_VAR_NAME_.2 = private unnamed_addr constant [18 x i8] c"stringWithFormat:\00", section "__TEXT,__objc_methname,cstring_literals", align 1
 @OBJC_SELECTOR_REFERENCES_.3 = internal externally_initialized global i8* getelementptr inbounds ([18 x i8], [18 x i8]* @OBJC_METH_VAR_NAME_.2, i32 0, i32 0), section "__DATA,__objc_selrefs,literal_pointers,no_dead_strip", align 8
+ at global1 = external local_unnamed_addr constant i8*, align 8
 @llvm.compiler.used = appending global [5 x i8*] [i8* getelementptr inbounds ([25 x i8], [25 x i8]* @OBJC_METH_VAR_NAME_, i32 0, i32 0), i8* bitcast (i8** @OBJC_SELECTOR_REFERENCES_ to i8*), i8* bitcast (%struct._class_t** @"OBJC_CLASSLIST_REFERENCES_$_" to i8*), i8* getelementptr inbounds ([18 x i8], [18 x i8]* @OBJC_METH_VAR_NAME_.2, i32 0, i32 0), i8* bitcast (i8** @OBJC_SELECTOR_REFERENCES_.3 to i8*)], section "llvm.metadata"
 
 ; Function Attrs: optsize ssp uwtable(sync)
@@ -121,6 +122,25 @@ if.end19:                                         ; preds = %if.end18, %for.body
   br i1 %exitcond.not, label %for.cond.cleanup.loopexit, label %for.body
 }
 
+; CHECK-LABEL: define i8* @foo() {
+; CHECK-NOT: @llvm.objc
+; CHECK: ret i8* %
+
+define i8* @foo() {
+  %t = alloca i8*, align 8
+  %v4 = load i8*, i8** @global1, align 8
+  %v5 = tail call i8* @llvm.objc.retain(i8* %v4)
+  store i8* %v4, i8** %t, align 8
+  %v13 = load i8*, i8** bitcast (%struct._class_t** @"OBJC_CLASSLIST_REFERENCES_$_" to i8**), align 8
+  %call78 = call i8* @bar(i8* %v13)
+  call void @llvm.objc.release(i8* %v4)
+  ret i8* %call78
+}
+
+declare i8* @bar(i8*)
+
+declare i8* @llvm.objc.retain(i8*)
+
 ; Function Attrs: argmemonly mustprogress nocallback nofree nosync nounwind willreturn
 declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) #2
 


        


More information about the llvm-commits mailing list