Skip to content

Commit 52f6f2c

Browse files
committed
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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@317201 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 4352a04 commit 52f6f2c

File tree

5 files changed

+160
-19
lines changed

5 files changed

+160
-19
lines changed

include/llvm/IR/CallSite.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,24 @@ class CallSiteBase {
475475
CALLSITE_DELEGATE_SETTER(setOnlyAccessesArgMemory());
476476
}
477477

478+
/// Determine if the function may only access memory that is
479+
/// inaccessible from the IR.
480+
bool onlyAccessesInaccessibleMemory() const {
481+
CALLSITE_DELEGATE_GETTER(onlyAccessesInaccessibleMemory());
482+
}
483+
void setOnlyAccessesInaccessibleMemory() {
484+
CALLSITE_DELEGATE_SETTER(setOnlyAccessesInaccessibleMemory());
485+
}
486+
487+
/// Determine if the function may only access memory that is
488+
/// either inaccessible from the IR or pointed to by its arguments.
489+
bool onlyAccessesInaccessibleMemOrArgMem() const {
490+
CALLSITE_DELEGATE_GETTER(onlyAccessesInaccessibleMemOrArgMem());
491+
}
492+
void setOnlyAccessesInaccessibleMemOrArgMem() {
493+
CALLSITE_DELEGATE_SETTER(setOnlyAccessesInaccessibleMemOrArgMem());
494+
}
495+
478496
/// Determine if the call cannot return.
479497
bool doesNotReturn() const {
480498
CALLSITE_DELEGATE_GETTER(doesNotReturn());

include/llvm/IR/InstrTypes.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1480,6 +1480,12 @@ template <typename InstrTy, typename OpIteratorTy> class OperandBundleUser {
14801480
default:
14811481
return false;
14821482

1483+
case Attribute::InaccessibleMemOrArgMemOnly:
1484+
return hasReadingOperandBundles();
1485+
1486+
case Attribute::InaccessibleMemOnly:
1487+
return hasReadingOperandBundles();
1488+
14831489
case Attribute::ArgMemOnly:
14841490
return hasReadingOperandBundles();
14851491

include/llvm/IR/Instructions.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1807,6 +1807,24 @@ class CallInst : public Instruction,
18071807
addAttribute(AttributeList::FunctionIndex, Attribute::ArgMemOnly);
18081808
}
18091809

1810+
/// @brief Determine if the function may only access memory that is
1811+
/// inaccessible from the IR.
1812+
bool onlyAccessesInaccessibleMemory() const {
1813+
return hasFnAttr(Attribute::InaccessibleMemOnly);
1814+
}
1815+
void setOnlyAccessesInaccessibleMemory() {
1816+
addAttribute(AttributeList::FunctionIndex, Attribute::InaccessibleMemOnly);
1817+
}
1818+
1819+
/// @brief Determine if the function may only access memory that is
1820+
/// either inaccessible from the IR or pointed to by its arguments.
1821+
bool onlyAccessesInaccessibleMemOrArgMem() const {
1822+
return hasFnAttr(Attribute::InaccessibleMemOrArgMemOnly);
1823+
}
1824+
void setOnlyAccessesInaccessibleMemOrArgMem() {
1825+
addAttribute(AttributeList::FunctionIndex, Attribute::InaccessibleMemOrArgMemOnly);
1826+
}
1827+
18101828
/// Determine if the call cannot return.
18111829
bool doesNotReturn() const { return hasFnAttr(Attribute::NoReturn); }
18121830
void setDoesNotReturn() {
@@ -3889,6 +3907,24 @@ class InvokeInst : public TerminatorInst,
38893907
addAttribute(AttributeList::FunctionIndex, Attribute::ArgMemOnly);
38903908
}
38913909

3910+
/// @brief Determine if the function may only access memory that is
3911+
/// inaccessible from the IR.
3912+
bool onlyAccessesInaccessibleMemory() const {
3913+
return hasFnAttr(Attribute::InaccessibleMemOnly);
3914+
}
3915+
void setOnlyAccessesInaccessibleMemory() {
3916+
addAttribute(AttributeList::FunctionIndex, Attribute::InaccessibleMemOnly);
3917+
}
3918+
3919+
/// @brief Determine if the function may only access memory that is
3920+
/// either inaccessible from the IR or pointed to by its arguments.
3921+
bool onlyAccessesInaccessibleMemOrArgMem() const {
3922+
return hasFnAttr(Attribute::InaccessibleMemOrArgMemOnly);
3923+
}
3924+
void setOnlyAccessesInaccessibleMemOrArgMem() {
3925+
addAttribute(AttributeList::FunctionIndex, Attribute::InaccessibleMemOrArgMemOnly);
3926+
}
3927+
38923928
/// Determine if the call cannot return.
38933929
bool doesNotReturn() const { return hasFnAttr(Attribute::NoReturn); }
38943930
void setDoesNotReturn() {

lib/Analysis/BasicAliasAnalysis.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -617,6 +617,10 @@ FunctionModRefBehavior BasicAAResult::getModRefBehavior(ImmutableCallSite CS) {
617617

618618
if (CS.onlyAccessesArgMemory())
619619
Min = FunctionModRefBehavior(Min & FMRB_OnlyAccessesArgumentPointees);
620+
else if (CS.onlyAccessesInaccessibleMemory())
621+
Min = FunctionModRefBehavior(Min & FMRB_OnlyAccessesInaccessibleMem);
622+
else if (CS.onlyAccessesInaccessibleMemOrArgMem())
623+
Min = FunctionModRefBehavior(Min & FMRB_OnlyAccessesInaccessibleOrArgMem);
620624

621625
// If CS has operand bundles then aliasing attributes from the function it
622626
// calls do not directly apply to the CallSite. This can be made more

test/Analysis/BasicAA/cs-cs.ll

Lines changed: 96 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22
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"
33
target triple = "arm-apple-ios"
44

5-
declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i32, i1) nounwind
6-
declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i32, i1) nounwind
5+
declare void @llvm.memset.p0i8.i64(i8* nocapture writeonly, i8, i64, i32, i1) #0
6+
declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture readonly, i64, i32, i1) #0
77

8-
declare void @a_readonly_func(i8 *) noinline nounwind readonly
9-
declare void @a_writeonly_func(i8 *) noinline nounwind writeonly
8+
declare void @a_readonly_func(i8*) #1
9+
declare void @a_writeonly_func(i8*) #2
1010

11-
define void @test2(i8* %P, i8* %Q) nounwind ssp {
11+
define void @test2(i8* %P, i8* %Q) #3 {
1212
tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i32 1, i1 false)
1313
tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i32 1, i1 false)
1414
ret void
@@ -24,7 +24,7 @@ define void @test2(i8* %P, i8* %Q) nounwind ssp {
2424
; 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)
2525
}
2626

27-
define void @test2a(i8* noalias %P, i8* noalias %Q) nounwind ssp {
27+
define void @test2a(i8* noalias %P, i8* noalias %Q) #3 {
2828
tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i32 1, i1 false)
2929
tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i32 1, i1 false)
3030
ret void
@@ -40,7 +40,7 @@ define void @test2a(i8* noalias %P, i8* noalias %Q) nounwind ssp {
4040
; 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)
4141
}
4242

43-
define void @test2b(i8* noalias %P, i8* noalias %Q) nounwind ssp {
43+
define void @test2b(i8* noalias %P, i8* noalias %Q) #3 {
4444
tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i32 1, i1 false)
4545
%R = getelementptr i8, i8* %P, i64 12
4646
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* noalias %Q) nounwind ssp {
6161
; 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)
6262
}
6363

64-
define void @test2c(i8* noalias %P, i8* noalias %Q) nounwind ssp {
64+
define void @test2c(i8* noalias %P, i8* noalias %Q) #3 {
6565
tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i32 1, i1 false)
6666
%R = getelementptr i8, i8* %P, i64 11
6767
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* noalias %Q) nounwind ssp {
8282
; 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)
8383
}
8484

85-
define void @test2d(i8* noalias %P, i8* noalias %Q) nounwind ssp {
85+
define void @test2d(i8* noalias %P, i8* noalias %Q) #3 {
8686
tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i32 1, i1 false)
8787
%R = getelementptr i8, i8* %P, i64 -12
8888
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* noalias %Q) nounwind ssp {
103103
; 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)
104104
}
105105

106-
define void @test2e(i8* noalias %P, i8* noalias %Q) nounwind ssp {
106+
define void @test2e(i8* noalias %P, i8* noalias %Q) #3 {
107107
tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i32 1, i1 false)
108108
%R = getelementptr i8, i8* %P, i64 -11
109109
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* noalias %Q) nounwind ssp {
124124
; 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)
125125
}
126126

127-
define void @test3(i8* %P, i8* %Q) nounwind ssp {
127+
define void @test3(i8* %P, i8* %Q) #3 {
128128
tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 8, i32 1, i1 false)
129129
tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i32 1, i1 false)
130130
ret void
@@ -140,7 +140,7 @@ define void @test3(i8* %P, i8* %Q) nounwind ssp {
140140
; 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)
141141
}
142142

143-
define void @test3a(i8* noalias %P, i8* noalias %Q) nounwind ssp {
143+
define void @test3a(i8* noalias %P, i8* noalias %Q) #3 {
144144
tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 8, i32 1, i1 false)
145145
tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i32 1, i1 false)
146146
ret void
@@ -156,7 +156,7 @@ define void @test3a(i8* noalias %P, i8* noalias %Q) nounwind ssp {
156156
; 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)
157157
}
158158

159-
define void @test4(i8* %P, i8* noalias %Q) nounwind ssp {
159+
define void @test4(i8* %P, i8* noalias %Q) #3 {
160160
tail call void @llvm.memset.p0i8.i64(i8* %P, i8 42, i64 8, i32 1, i1 false)
161161
tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i32 1, i1 false)
162162
ret void
@@ -172,7 +172,7 @@ define void @test4(i8* %P, i8* noalias %Q) nounwind ssp {
172172
; 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)
173173
}
174174

175-
define void @test5(i8* %P, i8* %Q, i8* %R) nounwind ssp {
175+
define void @test5(i8* %P, i8* %Q, i8* %R) #3 {
176176
tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i32 1, i1 false)
177177
tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %R, i64 12, i32 1, i1 false)
178178
ret void
@@ -192,7 +192,7 @@ define void @test5(i8* %P, i8* %Q, i8* %R) nounwind ssp {
192192
; 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)
193193
}
194194

195-
define void @test6(i8* %P) nounwind ssp {
195+
define void @test6(i8* %P) #3 {
196196
call void @llvm.memset.p0i8.i64(i8* %P, i8 -51, i64 32, i32 8, i1 false)
197197
call void @a_readonly_func(i8* %P)
198198
ret void
@@ -205,7 +205,7 @@ define void @test6(i8* %P) nounwind ssp {
205205
; 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)
206206
}
207207

208-
define void @test7(i8* %P) nounwind ssp {
208+
define void @test7(i8* %P) #3 {
209209
call void @a_writeonly_func(i8* %P)
210210
call void @a_readonly_func(i8* %P)
211211
ret void
@@ -218,9 +218,9 @@ define void @test7(i8* %P) nounwind ssp {
218218
; CHECK: Just Ref: call void @a_readonly_func(i8* %P) <-> call void @a_writeonly_func(i8* %P)
219219
}
220220

221-
declare void @an_inaccessiblememonly_func() nounwind inaccessiblememonly
222-
declare void @an_inaccessibleorargmemonly_func(i8 *) nounwind inaccessiblemem_or_argmemonly
223-
declare void @an_argmemonly_func(i8 *) nounwind argmemonly
221+
declare void @an_inaccessiblememonly_func() #4
222+
declare void @an_inaccessibleorargmemonly_func(i8*) #5
223+
declare void @an_argmemonly_func(i8*) #0
224224

225225
define void @test8(i8* %p) {
226226
entry:
@@ -260,3 +260,80 @@ entry:
260260
; CHECK: NoModRef: call void @an_argmemonly_func(i8* %q) <-> call void @an_inaccessiblememonly_func()
261261
; CHECK: Both ModRef: call void @an_argmemonly_func(i8* %q) <-> call void @an_inaccessibleorargmemonly_func(i8* %q)
262262
}
263+
264+
;; test that unknown operand bundle has unknown effect to the heap
265+
define void @test9(i8* %p) {
266+
; CHECK-LABEL: Function: test9
267+
entry:
268+
%q = getelementptr i8, i8* %p, i64 16
269+
call void @a_readonly_func(i8* %p) [ "unknown"() ]
270+
call void @an_inaccessiblememonly_func() [ "unknown"() ]
271+
call void @an_inaccessibleorargmemonly_func(i8* %q) [ "unknown"() ]
272+
call void @an_argmemonly_func(i8* %q) [ "unknown"() ]
273+
ret void
274+
275+
; CHECK: Both ModRef: Ptr: i8* %p <-> call void @a_readonly_func(i8* %p) [ "unknown"() ]
276+
; CHECK: Both ModRef: Ptr: i8* %q <-> call void @a_readonly_func(i8* %p) [ "unknown"() ]
277+
; CHECK: Both ModRef: Ptr: i8* %p <-> call void @an_inaccessiblememonly_func() [ "unknown"() ]
278+
; CHECK: Both ModRef: Ptr: i8* %q <-> call void @an_inaccessiblememonly_func() [ "unknown"() ]
279+
; CHECK: Both ModRef: Ptr: i8* %p <-> call void @an_inaccessibleorargmemonly_func(i8* %q) [ "unknown"() ]
280+
; CHECK: Both ModRef: Ptr: i8* %q <-> call void @an_inaccessibleorargmemonly_func(i8* %q) [ "unknown"() ]
281+
; CHECK: Both ModRef: Ptr: i8* %p <-> call void @an_argmemonly_func(i8* %q) [ "unknown"() ]
282+
; CHECK: Both ModRef: Ptr: i8* %q <-> call void @an_argmemonly_func(i8* %q) [ "unknown"() ]
283+
; CHECK: Both ModRef: call void @a_readonly_func(i8* %p) [ "unknown"() ] <-> call void @an_inaccessiblememonly_func() [ "unknown"() ]
284+
; CHECK: Both ModRef: call void @a_readonly_func(i8* %p) [ "unknown"() ] <-> call void @an_inaccessibleorargmemonly_func(i8* %q) [ "unknown"() ]
285+
; CHECK: Both ModRef: call void @a_readonly_func(i8* %p) [ "unknown"() ] <-> call void @an_argmemonly_func(i8* %q) [ "unknown"() ]
286+
; CHECK: Both ModRef: call void @an_inaccessiblememonly_func() [ "unknown"() ] <-> call void @a_readonly_func(i8* %p) [ "unknown"() ]
287+
; CHECK: Both ModRef: call void @an_inaccessiblememonly_func() [ "unknown"() ] <-> call void @an_inaccessibleorargmemonly_func(i8* %q) [ "unknown"() ]
288+
; CHECK: Both ModRef: call void @an_inaccessiblememonly_func() [ "unknown"() ] <-> call void @an_argmemonly_func(i8* %q) [ "unknown"() ]
289+
; CHECK: Both ModRef: call void @an_inaccessibleorargmemonly_func(i8* %q) [ "unknown"() ] <-> call void @a_readonly_func(i8* %p) [ "unknown"() ]
290+
; CHECK: Both ModRef: call void @an_inaccessibleorargmemonly_func(i8* %q) [ "unknown"() ] <-> call void @an_inaccessiblememonly_func() [ "unknown"() ]
291+
; CHECK: Both ModRef: call void @an_inaccessibleorargmemonly_func(i8* %q) [ "unknown"() ] <-> call void @an_argmemonly_func(i8* %q) [ "unknown"() ]
292+
; CHECK: Both ModRef: call void @an_argmemonly_func(i8* %q) [ "unknown"() ] <-> call void @a_readonly_func(i8* %p) [ "unknown"() ]
293+
; CHECK: Both ModRef: call void @an_argmemonly_func(i8* %q) [ "unknown"() ] <-> call void @an_inaccessiblememonly_func() [ "unknown"() ]
294+
; CHECK: Both ModRef: call void @an_argmemonly_func(i8* %q) [ "unknown"() ] <-> call void @an_inaccessibleorargmemonly_func(i8* %q) [ "unknown"() ]
295+
}
296+
297+
;; test callsite overwrite of unknown operand bundle
298+
define void @test10(i8* %p) {
299+
; CHECK-LABEL: Function: test10
300+
entry:
301+
%q = getelementptr i8, i8* %p, i64 16
302+
call void @a_readonly_func(i8* %p) #6 [ "unknown"() ]
303+
call void @an_inaccessiblememonly_func() #7 [ "unknown"() ]
304+
call void @an_inaccessibleorargmemonly_func(i8* %q) #8 [ "unknown"() ]
305+
call void @an_argmemonly_func(i8* %q) #9 [ "unknown"() ]
306+
ret void
307+
308+
; CHECK: Just Ref: Ptr: i8* %p <-> call void @a_readonly_func(i8* %p) #6 [ "unknown"() ]
309+
; CHECK: Just Ref: Ptr: i8* %q <-> call void @a_readonly_func(i8* %p) #6 [ "unknown"() ]
310+
; CHECK: NoModRef: Ptr: i8* %p <-> call void @an_inaccessiblememonly_func() #7 [ "unknown"() ]
311+
; CHECK: NoModRef: Ptr: i8* %q <-> call void @an_inaccessiblememonly_func() #7 [ "unknown"() ]
312+
; CHECK: NoModRef: Ptr: i8* %p <-> call void @an_inaccessibleorargmemonly_func(i8* %q) #8 [ "unknown"() ]
313+
; CHECK: Both ModRef: Ptr: i8* %q <-> call void @an_inaccessibleorargmemonly_func(i8* %q) #8 [ "unknown"() ]
314+
; CHECK: NoModRef: Ptr: i8* %p <-> call void @an_argmemonly_func(i8* %q) #9 [ "unknown"() ]
315+
; CHECK: Both ModRef: Ptr: i8* %q <-> call void @an_argmemonly_func(i8* %q) #9 [ "unknown"() ]
316+
; CHECK: Just Ref: call void @a_readonly_func(i8* %p) #6 [ "unknown"() ] <-> call void @an_inaccessiblememonly_func() #7 [ "unknown"() ]
317+
; CHECK: Just Ref: call void @a_readonly_func(i8* %p) #6 [ "unknown"() ] <-> call void @an_inaccessibleorargmemonly_func(i8* %q) #8 [ "unknown"() ]
318+
; CHECK: Just Ref: call void @a_readonly_func(i8* %p) #6 [ "unknown"() ] <-> call void @an_argmemonly_func(i8* %q) #9 [ "unknown"() ]
319+
; CHECK: Both ModRef: call void @an_inaccessiblememonly_func() #7 [ "unknown"() ] <-> call void @a_readonly_func(i8* %p) #6 [ "unknown"() ]
320+
; CHECK: Both ModRef: call void @an_inaccessiblememonly_func() #7 [ "unknown"() ] <-> call void @an_inaccessibleorargmemonly_func(i8* %q) #8 [ "unknown"() ]
321+
; CHECK: NoModRef: call void @an_inaccessiblememonly_func() #7 [ "unknown"() ] <-> call void @an_argmemonly_func(i8* %q) #9 [ "unknown"() ]
322+
; CHECK: Both ModRef: call void @an_inaccessibleorargmemonly_func(i8* %q) #8 [ "unknown"() ] <-> call void @a_readonly_func(i8* %p) #6 [ "unknown"() ]
323+
; CHECK: Both ModRef: call void @an_inaccessibleorargmemonly_func(i8* %q) #8 [ "unknown"() ] <-> call void @an_inaccessiblememonly_func() #7 [ "unknown"() ]
324+
; CHECK: Both ModRef: call void @an_inaccessibleorargmemonly_func(i8* %q) #8 [ "unknown"() ] <-> call void @an_argmemonly_func(i8* %q) #9 [ "unknown"() ]
325+
; CHECK: Both ModRef: call void @an_argmemonly_func(i8* %q) #9 [ "unknown"() ] <-> call void @a_readonly_func(i8* %p) #6 [ "unknown"() ]
326+
; CHECK: NoModRef: call void @an_argmemonly_func(i8* %q) #9 [ "unknown"() ] <-> call void @an_inaccessiblememonly_func() #7 [ "unknown"() ]
327+
; CHECK: Both ModRef: call void @an_argmemonly_func(i8* %q) #9 [ "unknown"() ] <-> call void @an_inaccessibleorargmemonly_func(i8* %q) #8 [ "unknown"() ]
328+
}
329+
330+
attributes #0 = { argmemonly nounwind }
331+
attributes #1 = { noinline nounwind readonly }
332+
attributes #2 = { noinline nounwind writeonly }
333+
attributes #3 = { nounwind ssp }
334+
attributes #4 = { inaccessiblememonly nounwind }
335+
attributes #5 = { inaccessiblemem_or_argmemonly nounwind }
336+
attributes #6 = { readonly }
337+
attributes #7 = { inaccessiblememonly }
338+
attributes #8 = { inaccessiblemem_or_argmemonly }
339+
attributes #9 = { argmemonly }

0 commit comments

Comments
 (0)