[llvm] r317201 - Allow inaccessiblememonly and inaccessiblemem_or_argmemonly to be overwriten on call site with operand bundle

Yichao Yu via llvm-commits llvm-commits at lists.llvm.org
Thu Nov 2 05:18:33 PDT 2017


Author: yuyichao
Date: Thu Nov  2 05:18:33 2017
New Revision: 317201

URL: http://llvm.org/viewvc/llvm-project?rev=317201&view=rev
Log:
Allow inaccessiblememonly and inaccessiblemem_or_argmemonly to be overwriten on call site with operand bundle

Summary:
Similar to argmemonly, readonly and readnone.

Fix PR35128

Reviewers: andrew.w.kaylor, chandlerc, hfinkel

Reviewed By: hfinkel

Subscribers: hfinkel, llvm-commits

Differential Revision: https://reviews.llvm.org/D39434

Modified:
    llvm/trunk/include/llvm/IR/CallSite.h
    llvm/trunk/include/llvm/IR/InstrTypes.h
    llvm/trunk/include/llvm/IR/Instructions.h
    llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp
    llvm/trunk/test/Analysis/BasicAA/cs-cs.ll

Modified: llvm/trunk/include/llvm/IR/CallSite.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/CallSite.h?rev=317201&r1=317200&r2=317201&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/CallSite.h (original)
+++ llvm/trunk/include/llvm/IR/CallSite.h Thu Nov  2 05:18:33 2017
@@ -475,6 +475,24 @@ public:
     CALLSITE_DELEGATE_SETTER(setOnlyAccessesArgMemory());
   }
 
+  /// Determine if the function may only access memory that is
+  /// inaccessible from the IR.
+  bool onlyAccessesInaccessibleMemory() const {
+    CALLSITE_DELEGATE_GETTER(onlyAccessesInaccessibleMemory());
+  }
+  void setOnlyAccessesInaccessibleMemory() {
+    CALLSITE_DELEGATE_SETTER(setOnlyAccessesInaccessibleMemory());
+  }
+
+  /// Determine if the function may only access memory that is
+  /// either inaccessible from the IR or pointed to by its arguments.
+  bool onlyAccessesInaccessibleMemOrArgMem() const {
+    CALLSITE_DELEGATE_GETTER(onlyAccessesInaccessibleMemOrArgMem());
+  }
+  void setOnlyAccessesInaccessibleMemOrArgMem() {
+    CALLSITE_DELEGATE_SETTER(setOnlyAccessesInaccessibleMemOrArgMem());
+  }
+
   /// Determine if the call cannot return.
   bool doesNotReturn() const {
     CALLSITE_DELEGATE_GETTER(doesNotReturn());

Modified: llvm/trunk/include/llvm/IR/InstrTypes.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/InstrTypes.h?rev=317201&r1=317200&r2=317201&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/InstrTypes.h (original)
+++ llvm/trunk/include/llvm/IR/InstrTypes.h Thu Nov  2 05:18:33 2017
@@ -1480,6 +1480,12 @@ protected:
     default:
       return false;
 
+    case Attribute::InaccessibleMemOrArgMemOnly:
+      return hasReadingOperandBundles();
+
+    case Attribute::InaccessibleMemOnly:
+      return hasReadingOperandBundles();
+
     case Attribute::ArgMemOnly:
       return hasReadingOperandBundles();
 

Modified: llvm/trunk/include/llvm/IR/Instructions.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Instructions.h?rev=317201&r1=317200&r2=317201&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/Instructions.h (original)
+++ llvm/trunk/include/llvm/IR/Instructions.h Thu Nov  2 05:18:33 2017
@@ -1807,6 +1807,24 @@ public:
     addAttribute(AttributeList::FunctionIndex, Attribute::ArgMemOnly);
   }
 
+  /// @brief Determine if the function may only access memory that is
+  /// inaccessible from the IR.
+  bool onlyAccessesInaccessibleMemory() const {
+    return hasFnAttr(Attribute::InaccessibleMemOnly);
+  }
+  void setOnlyAccessesInaccessibleMemory() {
+    addAttribute(AttributeList::FunctionIndex, Attribute::InaccessibleMemOnly);
+  }
+
+  /// @brief Determine if the function may only access memory that is
+  /// either inaccessible from the IR or pointed to by its arguments.
+  bool onlyAccessesInaccessibleMemOrArgMem() const {
+    return hasFnAttr(Attribute::InaccessibleMemOrArgMemOnly);
+  }
+  void setOnlyAccessesInaccessibleMemOrArgMem() {
+    addAttribute(AttributeList::FunctionIndex, Attribute::InaccessibleMemOrArgMemOnly);
+  }
+
   /// Determine if the call cannot return.
   bool doesNotReturn() const { return hasFnAttr(Attribute::NoReturn); }
   void setDoesNotReturn() {
@@ -3889,6 +3907,24 @@ public:
     addAttribute(AttributeList::FunctionIndex, Attribute::ArgMemOnly);
   }
 
+  /// @brief Determine if the function may only access memory that is
+  /// inaccessible from the IR.
+  bool onlyAccessesInaccessibleMemory() const {
+    return hasFnAttr(Attribute::InaccessibleMemOnly);
+  }
+  void setOnlyAccessesInaccessibleMemory() {
+    addAttribute(AttributeList::FunctionIndex, Attribute::InaccessibleMemOnly);
+  }
+
+  /// @brief Determine if the function may only access memory that is
+  /// either inaccessible from the IR or pointed to by its arguments.
+  bool onlyAccessesInaccessibleMemOrArgMem() const {
+    return hasFnAttr(Attribute::InaccessibleMemOrArgMemOnly);
+  }
+  void setOnlyAccessesInaccessibleMemOrArgMem() {
+    addAttribute(AttributeList::FunctionIndex, Attribute::InaccessibleMemOrArgMemOnly);
+  }
+
   /// Determine if the call cannot return.
   bool doesNotReturn() const { return hasFnAttr(Attribute::NoReturn); }
   void setDoesNotReturn() {

Modified: llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp?rev=317201&r1=317200&r2=317201&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp (original)
+++ llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp Thu Nov  2 05:18:33 2017
@@ -617,6 +617,10 @@ FunctionModRefBehavior BasicAAResult::ge
 
   if (CS.onlyAccessesArgMemory())
     Min = FunctionModRefBehavior(Min & FMRB_OnlyAccessesArgumentPointees);
+  else if (CS.onlyAccessesInaccessibleMemory())
+    Min = FunctionModRefBehavior(Min & FMRB_OnlyAccessesInaccessibleMem);
+  else if (CS.onlyAccessesInaccessibleMemOrArgMem())
+    Min = FunctionModRefBehavior(Min & FMRB_OnlyAccessesInaccessibleOrArgMem);
 
   // If CS has operand bundles then aliasing attributes from the function it
   // calls do not directly apply to the CallSite.  This can be made more

Modified: llvm/trunk/test/Analysis/BasicAA/cs-cs.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/BasicAA/cs-cs.ll?rev=317201&r1=317200&r2=317201&view=diff
==============================================================================
--- llvm/trunk/test/Analysis/BasicAA/cs-cs.ll (original)
+++ llvm/trunk/test/Analysis/BasicAA/cs-cs.ll Thu Nov  2 05:18:33 2017
@@ -2,13 +2,13 @@
 target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:32:64-v128:32:128-a0:0:32-n32"
 target triple = "arm-apple-ios"
 
-declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i32, i1) nounwind
-declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i32, i1) nounwind
+declare void @llvm.memset.p0i8.i64(i8* nocapture writeonly, i8, i64, i32, i1) #0
+declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture readonly, i64, i32, i1) #0
 
-declare void @a_readonly_func(i8 *) noinline nounwind readonly
-declare void @a_writeonly_func(i8 *) noinline nounwind writeonly
+declare void @a_readonly_func(i8*) #1
+declare void @a_writeonly_func(i8*) #2
 
-define void @test2(i8* %P, i8* %Q) nounwind ssp {
+define void @test2(i8* %P, i8* %Q) #3 {
   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i32 1, i1 false)
   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i32 1, i1 false)
   ret void
@@ -24,7 +24,7 @@ define void @test2(i8* %P, i8* %Q) nounw
 ; CHECK:   Just Mod:   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i32 1, i1 false) <->   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i32 1, i1 false)
 }
 
-define void @test2a(i8* noalias %P, i8* noalias %Q) nounwind ssp {
+define void @test2a(i8* noalias %P, i8* noalias %Q) #3 {
   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i32 1, i1 false)
   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i32 1, i1 false)
   ret void
@@ -40,7 +40,7 @@ define void @test2a(i8* noalias %P, i8*
 ; CHECK: Just Mod:   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i32 1, i1 false) <->   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i32 1, i1 false)
 }
 
-define void @test2b(i8* noalias %P, i8* noalias %Q) nounwind ssp {
+define void @test2b(i8* noalias %P, i8* noalias %Q) #3 {
   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i32 1, i1 false)
   %R = getelementptr i8, i8* %P, i64 12
   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %R, i8* %Q, i64 12, i32 1, i1 false)
@@ -61,7 +61,7 @@ define void @test2b(i8* noalias %P, i8*
 ; CHECK: NoModRef:   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %R, i8* %Q, i64 12, i32 1, i1 false) <->   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i32 1, i1 false)
 }
 
-define void @test2c(i8* noalias %P, i8* noalias %Q) nounwind ssp {
+define void @test2c(i8* noalias %P, i8* noalias %Q) #3 {
   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i32 1, i1 false)
   %R = getelementptr i8, i8* %P, i64 11
   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %R, i8* %Q, i64 12, i32 1, i1 false)
@@ -82,7 +82,7 @@ define void @test2c(i8* noalias %P, i8*
 ; CHECK: Just Mod:   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %R, i8* %Q, i64 12, i32 1, i1 false) <->   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i32 1, i1 false)
 }
 
-define void @test2d(i8* noalias %P, i8* noalias %Q) nounwind ssp {
+define void @test2d(i8* noalias %P, i8* noalias %Q) #3 {
   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i32 1, i1 false)
   %R = getelementptr i8, i8* %P, i64 -12
   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %R, i8* %Q, i64 12, i32 1, i1 false)
@@ -103,7 +103,7 @@ define void @test2d(i8* noalias %P, i8*
 ; CHECK: NoModRef:   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %R, i8* %Q, i64 12, i32 1, i1 false) <->   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i32 1, i1 false)
 }
 
-define void @test2e(i8* noalias %P, i8* noalias %Q) nounwind ssp {
+define void @test2e(i8* noalias %P, i8* noalias %Q) #3 {
   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i32 1, i1 false)
   %R = getelementptr i8, i8* %P, i64 -11
   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %R, i8* %Q, i64 12, i32 1, i1 false)
@@ -124,7 +124,7 @@ define void @test2e(i8* noalias %P, i8*
 ; CHECK: Just Mod:   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %R, i8* %Q, i64 12, i32 1, i1 false) <->   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i32 1, i1 false)
 }
 
-define void @test3(i8* %P, i8* %Q) nounwind ssp {
+define void @test3(i8* %P, i8* %Q) #3 {
   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 8, i32 1, i1 false)
   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i32 1, i1 false)
   ret void
@@ -140,7 +140,7 @@ define void @test3(i8* %P, i8* %Q) nounw
 ; CHECK: Just Mod:   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i32 1, i1 false) <->   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 8, i32 1, i1 false)
 }
 
-define void @test3a(i8* noalias %P, i8* noalias %Q) nounwind ssp {
+define void @test3a(i8* noalias %P, i8* noalias %Q) #3 {
   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 8, i32 1, i1 false)
   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i32 1, i1 false)
   ret void
@@ -156,7 +156,7 @@ define void @test3a(i8* noalias %P, i8*
 ; CHECK: Just Mod:   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i32 1, i1 false) <->   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 8, i32 1, i1 false)
 }
 
-define void @test4(i8* %P, i8* noalias %Q) nounwind ssp {
+define void @test4(i8* %P, i8* noalias %Q) #3 {
   tail call void @llvm.memset.p0i8.i64(i8* %P, i8 42, i64 8, i32 1, i1 false)
   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i32 1, i1 false)
   ret void
@@ -172,7 +172,7 @@ define void @test4(i8* %P, i8* noalias %
 ; CHECK: Just Mod:   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i32 1, i1 false) <->   tail call void @llvm.memset.p0i8.i64(i8* %P, i8 42, i64 8, i32 1, i1 false)
 }
 
-define void @test5(i8* %P, i8* %Q, i8* %R) nounwind ssp {
+define void @test5(i8* %P, i8* %Q, i8* %R) #3 {
   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i32 1, i1 false)
   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %R, i64 12, i32 1, i1 false)
   ret void
@@ -192,7 +192,7 @@ define void @test5(i8* %P, i8* %Q, i8* %
 ; CHECK: Just Mod:   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %R, i64 12, i32 1, i1 false) <->   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i32 1, i1 false)
 }
 
-define void @test6(i8* %P) nounwind ssp {
+define void @test6(i8* %P) #3 {
   call void @llvm.memset.p0i8.i64(i8* %P, i8 -51, i64 32, i32 8, i1 false)
   call void @a_readonly_func(i8* %P)
   ret void
@@ -205,7 +205,7 @@ define void @test6(i8* %P) nounwind ssp
 ; CHECK: Just Ref:   call void @a_readonly_func(i8* %P) <->   call void @llvm.memset.p0i8.i64(i8* %P, i8 -51, i64 32, i32 8, i1 false)
 }
 
-define void @test7(i8* %P) nounwind ssp {
+define void @test7(i8* %P) #3 {
   call void @a_writeonly_func(i8* %P)
   call void @a_readonly_func(i8* %P)
   ret void
@@ -218,9 +218,9 @@ define void @test7(i8* %P) nounwind ssp
 ; CHECK: Just Ref:   call void @a_readonly_func(i8* %P) <->   call void @a_writeonly_func(i8* %P)
 }
 
-declare void @an_inaccessiblememonly_func() nounwind inaccessiblememonly
-declare void @an_inaccessibleorargmemonly_func(i8 *) nounwind inaccessiblemem_or_argmemonly
-declare void @an_argmemonly_func(i8 *) nounwind argmemonly
+declare void @an_inaccessiblememonly_func() #4
+declare void @an_inaccessibleorargmemonly_func(i8*) #5
+declare void @an_argmemonly_func(i8*) #0
 
 define void @test8(i8* %p) {
 entry:
@@ -260,3 +260,80 @@ entry:
 ; CHECK: NoModRef: call void @an_argmemonly_func(i8* %q) <-> call void @an_inaccessiblememonly_func()
 ; CHECK: Both ModRef: call void @an_argmemonly_func(i8* %q) <-> call void @an_inaccessibleorargmemonly_func(i8* %q)
 }
+
+;; test that unknown operand bundle has unknown effect to the heap
+define void @test9(i8* %p) {
+; CHECK-LABEL: Function: test9
+entry:
+  %q = getelementptr i8, i8* %p, i64 16
+  call void @a_readonly_func(i8* %p) [ "unknown"() ]
+  call void @an_inaccessiblememonly_func() [ "unknown"() ]
+  call void @an_inaccessibleorargmemonly_func(i8* %q) [ "unknown"() ]
+  call void @an_argmemonly_func(i8* %q) [ "unknown"() ]
+  ret void
+
+; CHECK: Both ModRef:  Ptr: i8* %p     <->  call void @a_readonly_func(i8* %p) [ "unknown"() ]
+; CHECK: Both ModRef:  Ptr: i8* %q     <->  call void @a_readonly_func(i8* %p) [ "unknown"() ]
+; CHECK: Both ModRef:  Ptr: i8* %p     <->  call void @an_inaccessiblememonly_func() [ "unknown"() ]
+; CHECK: Both ModRef:  Ptr: i8* %q     <->  call void @an_inaccessiblememonly_func() [ "unknown"() ]
+; CHECK: Both ModRef:  Ptr: i8* %p     <->  call void @an_inaccessibleorargmemonly_func(i8* %q) [ "unknown"() ]
+; CHECK: Both ModRef:  Ptr: i8* %q     <->  call void @an_inaccessibleorargmemonly_func(i8* %q) [ "unknown"() ]
+; CHECK: Both ModRef:  Ptr: i8* %p     <->  call void @an_argmemonly_func(i8* %q) [ "unknown"() ]
+; CHECK: Both ModRef:  Ptr: i8* %q     <->  call void @an_argmemonly_func(i8* %q) [ "unknown"() ]
+; CHECK: Both ModRef:   call void @a_readonly_func(i8* %p) [ "unknown"() ] <->   call void @an_inaccessiblememonly_func() [ "unknown"() ]
+; CHECK: Both ModRef:   call void @a_readonly_func(i8* %p) [ "unknown"() ] <->   call void @an_inaccessibleorargmemonly_func(i8* %q) [ "unknown"() ]
+; CHECK: Both ModRef:   call void @a_readonly_func(i8* %p) [ "unknown"() ] <->   call void @an_argmemonly_func(i8* %q) [ "unknown"() ]
+; CHECK: Both ModRef:   call void @an_inaccessiblememonly_func() [ "unknown"() ] <->   call void @a_readonly_func(i8* %p) [ "unknown"() ]
+; CHECK: Both ModRef:   call void @an_inaccessiblememonly_func() [ "unknown"() ] <->   call void @an_inaccessibleorargmemonly_func(i8* %q) [ "unknown"() ]
+; CHECK: Both ModRef:   call void @an_inaccessiblememonly_func() [ "unknown"() ] <->   call void @an_argmemonly_func(i8* %q) [ "unknown"() ]
+; CHECK: Both ModRef:   call void @an_inaccessibleorargmemonly_func(i8* %q) [ "unknown"() ] <->   call void @a_readonly_func(i8* %p) [ "unknown"() ]
+; CHECK: Both ModRef:   call void @an_inaccessibleorargmemonly_func(i8* %q) [ "unknown"() ] <->   call void @an_inaccessiblememonly_func() [ "unknown"() ]
+; CHECK: Both ModRef:   call void @an_inaccessibleorargmemonly_func(i8* %q) [ "unknown"() ] <->   call void @an_argmemonly_func(i8* %q) [ "unknown"() ]
+; CHECK: Both ModRef:   call void @an_argmemonly_func(i8* %q) [ "unknown"() ] <->   call void @a_readonly_func(i8* %p) [ "unknown"() ]
+; CHECK: Both ModRef:   call void @an_argmemonly_func(i8* %q) [ "unknown"() ] <->   call void @an_inaccessiblememonly_func() [ "unknown"() ]
+; CHECK: Both ModRef:   call void @an_argmemonly_func(i8* %q) [ "unknown"() ] <->   call void @an_inaccessibleorargmemonly_func(i8* %q) [ "unknown"() ]
+}
+
+;; test callsite overwrite of unknown operand bundle
+define void @test10(i8* %p) {
+; CHECK-LABEL: Function: test10
+entry:
+  %q = getelementptr i8, i8* %p, i64 16
+  call void @a_readonly_func(i8* %p) #6 [ "unknown"() ]
+  call void @an_inaccessiblememonly_func() #7 [ "unknown"() ]
+  call void @an_inaccessibleorargmemonly_func(i8* %q) #8 [ "unknown"() ]
+  call void @an_argmemonly_func(i8* %q) #9 [ "unknown"() ]
+  ret void
+
+; CHECK: Just Ref:  Ptr: i8* %p        <->  call void @a_readonly_func(i8* %p) #6 [ "unknown"() ]
+; CHECK: Just Ref:  Ptr: i8* %q        <->  call void @a_readonly_func(i8* %p) #6 [ "unknown"() ]
+; CHECK: NoModRef:  Ptr: i8* %p        <->  call void @an_inaccessiblememonly_func() #7 [ "unknown"() ]
+; CHECK: NoModRef:  Ptr: i8* %q        <->  call void @an_inaccessiblememonly_func() #7 [ "unknown"() ]
+; CHECK: NoModRef:  Ptr: i8* %p        <->  call void @an_inaccessibleorargmemonly_func(i8* %q) #8 [ "unknown"() ]
+; CHECK: Both ModRef:  Ptr: i8* %q     <->  call void @an_inaccessibleorargmemonly_func(i8* %q) #8 [ "unknown"() ]
+; CHECK: NoModRef:  Ptr: i8* %p        <->  call void @an_argmemonly_func(i8* %q) #9 [ "unknown"() ]
+; CHECK: Both ModRef:  Ptr: i8* %q     <->  call void @an_argmemonly_func(i8* %q) #9 [ "unknown"() ]
+; CHECK: Just Ref:   call void @a_readonly_func(i8* %p) #6 [ "unknown"() ] <->   call void @an_inaccessiblememonly_func() #7 [ "unknown"() ]
+; CHECK: Just Ref:   call void @a_readonly_func(i8* %p) #6 [ "unknown"() ] <->   call void @an_inaccessibleorargmemonly_func(i8* %q) #8 [ "unknown"() ]
+; CHECK: Just Ref:   call void @a_readonly_func(i8* %p) #6 [ "unknown"() ] <->   call void @an_argmemonly_func(i8* %q) #9 [ "unknown"() ]
+; CHECK: Both ModRef:   call void @an_inaccessiblememonly_func() #7 [ "unknown"() ] <->   call void @a_readonly_func(i8* %p) #6 [ "unknown"() ]
+; CHECK: Both ModRef:   call void @an_inaccessiblememonly_func() #7 [ "unknown"() ] <->   call void @an_inaccessibleorargmemonly_func(i8* %q) #8 [ "unknown"() ]
+; CHECK: NoModRef:   call void @an_inaccessiblememonly_func() #7 [ "unknown"() ] <->   call void @an_argmemonly_func(i8* %q) #9 [ "unknown"() ]
+; CHECK: Both ModRef:   call void @an_inaccessibleorargmemonly_func(i8* %q) #8 [ "unknown"() ] <->   call void @a_readonly_func(i8* %p) #6 [ "unknown"() ]
+; CHECK: Both ModRef:   call void @an_inaccessibleorargmemonly_func(i8* %q) #8 [ "unknown"() ] <->   call void @an_inaccessiblememonly_func() #7 [ "unknown"() ]
+; CHECK: Both ModRef:   call void @an_inaccessibleorargmemonly_func(i8* %q) #8 [ "unknown"() ] <->   call void @an_argmemonly_func(i8* %q) #9 [ "unknown"() ]
+; CHECK: Both ModRef:   call void @an_argmemonly_func(i8* %q) #9 [ "unknown"() ] <->   call void @a_readonly_func(i8* %p) #6 [ "unknown"() ]
+; CHECK: NoModRef:   call void @an_argmemonly_func(i8* %q) #9 [ "unknown"() ] <->   call void @an_inaccessiblememonly_func() #7 [ "unknown"() ]
+; CHECK: Both ModRef:   call void @an_argmemonly_func(i8* %q) #9 [ "unknown"() ] <->   call void @an_inaccessibleorargmemonly_func(i8* %q) #8 [ "unknown"() ]
+}
+
+attributes #0 = { argmemonly nounwind }
+attributes #1 = { noinline nounwind readonly }
+attributes #2 = { noinline nounwind writeonly }
+attributes #3 = { nounwind ssp }
+attributes #4 = { inaccessiblememonly nounwind }
+attributes #5 = { inaccessiblemem_or_argmemonly nounwind }
+attributes #6 = { readonly }
+attributes #7 = { inaccessiblememonly }
+attributes #8 = { inaccessiblemem_or_argmemonly }
+attributes #9 = { argmemonly }




More information about the llvm-commits mailing list