1; RUN: opt < %s -aa-pipeline=basic-aa -passes=aa-eval -print-all-alias-modref-info -S 2>&1 | FileCheck %s
2target 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"
3target triple = "arm-apple-ios"
4
5declare void @llvm.memset.p0i8.i64(i8* nocapture writeonly, i8, i64, i1) #0
6declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture readonly, i64, i1) #0
7declare void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture readonly, i64, i32) #0
8
9declare void @a_readonly_func(i8*) #1
10declare void @a_writeonly_func(i8*) #2
11
12define void @test2(i8* %P, i8* %Q) #3 {
13  load i8, i8* %P
14  load i8, i8* %Q
15  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
16  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
17  ret void
18
19; CHECK-LABEL: Function: test2:
20
21; CHECK:   MayAlias:     i8* %P, i8* %Q
22; CHECK:   Both ModRef:  Ptr: i8* %P     <->  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
23; CHECK:   Both ModRef:  Ptr: i8* %Q     <->  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
24; CHECK:   Both ModRef:  Ptr: i8* %P     <->  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
25; CHECK:   Both ModRef:  Ptr: i8* %Q     <->  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
26; CHECK:   Both ModRef:   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false) <->   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
27; CHECK:   Both ModRef:   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false) <->   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
28}
29
30define void @test2_atomic(i8* %P, i8* %Q) #3 {
31  load i8, i8* %P
32  load i8, i8* %Q
33  tail call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 %P, i8* align 1 %Q, i64 12, i32 1)
34  tail call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 %P, i8* align 1 %Q, i64 12, i32 1)
35  ret void
36
37; CHECK-LABEL: Function: test2_atomic:
38
39; CHECK:   MayAlias:     i8* %P, i8* %Q
40; CHECK:   Both ModRef:  Ptr: i8* %P     <->  tail call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 %P, i8* align 1 %Q, i64 12, i32 1)
41; CHECK:   Both ModRef:  Ptr: i8* %Q     <->  tail call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 %P, i8* align 1 %Q, i64 12, i32 1)
42; CHECK:   Both ModRef:  Ptr: i8* %P     <->  tail call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 %P, i8* align 1 %Q, i64 12, i32 1)
43; CHECK:   Both ModRef:  Ptr: i8* %Q     <->  tail call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 %P, i8* align 1 %Q, i64 12, i32 1)
44; CHECK:   Both ModRef:   tail call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 %P, i8* align 1 %Q, i64 12, i32 1) <->   tail call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 %P, i8* align 1 %Q, i64 12, i32 1)
45; CHECK:   Both ModRef:   tail call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 %P, i8* align 1 %Q, i64 12, i32 1) <->   tail call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 %P, i8* align 1 %Q, i64 12, i32 1)
46}
47
48define void @test2a(i8* noalias %P, i8* noalias %Q) #3 {
49  load i8, i8* %P
50  load i8, i8* %Q
51  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
52  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
53  ret void
54
55; CHECK-LABEL: Function: test2a:
56
57; CHECK: NoAlias:      i8* %P, i8* %Q
58; CHECK: Just Mod:  Ptr: i8* %P        <->  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
59; CHECK: Just Ref:  Ptr: i8* %Q        <->  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
60; CHECK: Just Mod:  Ptr: i8* %P        <->  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
61; CHECK: Just Ref:  Ptr: i8* %Q        <->  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
62; CHECK: Just Mod:   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false) <->   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
63; CHECK: Just Mod:   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false) <->   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
64}
65
66define void @test2b(i8* noalias %P, i8* noalias %Q) #3 {
67  load i8, i8* %P
68  load i8, i8* %Q
69  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
70  %R = getelementptr i8, i8* %P, i64 12
71  load i8, i8* %R
72  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %R, i8* %Q, i64 12, i1 false)
73  ret void
74
75; CHECK-LABEL: Function: test2b:
76
77; CHECK: NoAlias:      i8* %P, i8* %Q
78; CHECK: NoAlias:      i8* %P, i8* %R
79; CHECK: NoAlias:      i8* %Q, i8* %R
80; CHECK: Just Mod:  Ptr: i8* %P        <->  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
81; CHECK: Just Ref:  Ptr: i8* %Q        <->  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
82; CHECK: NoModRef:  Ptr: i8* %R        <->  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
83; CHECK: NoModRef:  Ptr: i8* %P        <->  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %R, i8* %Q, i64 12, i1 false)
84; CHECK: Just Ref:  Ptr: i8* %Q        <->  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %R, i8* %Q, i64 12, i1 false)
85; CHECK: Just Mod:  Ptr: i8* %R        <->  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %R, i8* %Q, i64 12, i1 false)
86; CHECK: NoModRef:   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false) <->   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %R, i8* %Q, i64 12, i1 false)
87; CHECK: NoModRef:   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %R, i8* %Q, i64 12, i1 false) <->   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
88}
89
90define void @test2c(i8* noalias %P, i8* noalias %Q) #3 {
91  load i8, i8* %P
92  load i8, i8* %Q
93  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
94  %R = getelementptr i8, i8* %P, i64 11
95  load i8, i8* %R
96  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %R, i8* %Q, i64 12, i1 false)
97  ret void
98
99; CHECK-LABEL: Function: test2c:
100
101; CHECK: NoAlias:      i8* %P, i8* %Q
102; CHECK: NoAlias:      i8* %P, i8* %R
103; CHECK: NoAlias:      i8* %Q, i8* %R
104; CHECK: Just Mod:  Ptr: i8* %P        <->  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
105; CHECK: Just Ref:  Ptr: i8* %Q        <->  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
106; CHECK: Just Mod:  Ptr: i8* %R        <->  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
107; CHECK: NoModRef:  Ptr: i8* %P        <->  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %R, i8* %Q, i64 12, i1 false)
108; CHECK: Just Ref:  Ptr: i8* %Q        <->  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %R, i8* %Q, i64 12, i1 false)
109; CHECK: Just Mod:  Ptr: i8* %R        <->  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %R, i8* %Q, i64 12, i1 false)
110; CHECK: Just Mod:   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false) <->   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %R, i8* %Q, i64 12, i1 false)
111; CHECK: Just Mod:   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %R, i8* %Q, i64 12, i1 false) <->   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
112}
113
114define void @test2d(i8* noalias %P, i8* noalias %Q) #3 {
115  load i8, i8* %P
116  load i8, i8* %Q
117  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
118  %R = getelementptr i8, i8* %P, i64 -12
119  load i8, i8* %R
120  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %R, i8* %Q, i64 12, i1 false)
121  ret void
122
123; CHECK-LABEL: Function: test2d:
124
125; CHECK: NoAlias:      i8* %P, i8* %Q
126; CHECK: NoAlias:      i8* %P, i8* %R
127; CHECK: NoAlias:      i8* %Q, i8* %R
128; CHECK: Just Mod:  Ptr: i8* %P        <->  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
129; CHECK: Just Ref:  Ptr: i8* %Q        <->  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
130; CHECK: NoModRef:  Ptr: i8* %R        <->  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
131; CHECK: NoModRef:  Ptr: i8* %P        <->  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %R, i8* %Q, i64 12, i1 false)
132; CHECK: Just Ref:  Ptr: i8* %Q        <->  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %R, i8* %Q, i64 12, i1 false)
133; CHECK: Just Mod:  Ptr: i8* %R        <->  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %R, i8* %Q, i64 12, i1 false)
134; CHECK: NoModRef:   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false) <->   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %R, i8* %Q, i64 12, i1 false)
135; CHECK: NoModRef:   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %R, i8* %Q, i64 12, i1 false) <->   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
136}
137
138define void @test2e(i8* noalias %P, i8* noalias %Q) #3 {
139  load i8, i8* %P
140  load i8, i8* %Q
141  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
142  %R = getelementptr i8, i8* %P, i64 -11
143  load i8, i8* %R
144  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %R, i8* %Q, i64 12, i1 false)
145  ret void
146
147; CHECK-LABEL: Function: test2e:
148
149; CHECK: NoAlias:      i8* %P, i8* %Q
150; CHECK: NoAlias:      i8* %P, i8* %R
151; CHECK: NoAlias:      i8* %Q, i8* %R
152; CHECK: Just Mod:  Ptr: i8* %P        <->  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
153; CHECK: Just Ref:  Ptr: i8* %Q        <->  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
154; CHECK: NoModRef:  Ptr: i8* %R        <->  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
155; CHECK: Just Mod:  Ptr: i8* %P        <->  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %R, i8* %Q, i64 12, i1 false)
156; CHECK: Just Ref:  Ptr: i8* %Q        <->  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %R, i8* %Q, i64 12, i1 false)
157; CHECK: Just Mod:  Ptr: i8* %R        <->  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %R, i8* %Q, i64 12, i1 false)
158; CHECK: Just Mod:   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false) <->   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %R, i8* %Q, i64 12, i1 false)
159; CHECK: Just Mod:   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %R, i8* %Q, i64 12, i1 false) <->   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
160}
161
162define void @test3(i8* %P, i8* %Q) #3 {
163  load i8, i8* %P
164  load i8, i8* %Q
165  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 8, i1 false)
166  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
167  ret void
168
169; CHECK-LABEL: Function: test3:
170
171; CHECK: MayAlias:     i8* %P, i8* %Q
172; CHECK: Both ModRef:  Ptr: i8* %P     <->  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 8, i1 false)
173; CHECK: Both ModRef:  Ptr: i8* %Q     <->  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 8, i1 false)
174; CHECK: Both ModRef:  Ptr: i8* %P     <->  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
175; CHECK: Both ModRef:  Ptr: i8* %Q     <->  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
176; CHECK: Both ModRef:   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 8, i1 false) <->   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
177; CHECK: Both ModRef:   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false) <->   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 8, i1 false)
178}
179
180define void @test3a(i8* noalias %P, i8* noalias %Q) #3 {
181  load i8, i8* %P
182  load i8, i8* %Q
183  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 8, i1 false)
184  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
185  ret void
186
187; CHECK-LABEL: Function: test3a:
188
189; CHECK: NoAlias:      i8* %P, i8* %Q
190; CHECK: Just Mod:  Ptr: i8* %P        <->  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 8, i1 false)
191; CHECK: Just Ref:  Ptr: i8* %Q        <->  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 8, i1 false)
192; CHECK: Just Mod:  Ptr: i8* %P        <->  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
193; CHECK: Just Ref:  Ptr: i8* %Q        <->  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
194; CHECK: Just Mod:   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 8, i1 false) <->   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
195; CHECK: Just Mod:   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false) <->   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 8, i1 false)
196}
197
198define void @test4(i8* %P, i8* noalias %Q) #3 {
199  load i8, i8* %P
200  load i8, i8* %Q
201  tail call void @llvm.memset.p0i8.i64(i8* %P, i8 42, i64 8, i1 false)
202  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
203  ret void
204
205; CHECK-LABEL: Function: test4:
206
207; CHECK: NoAlias:      i8* %P, i8* %Q
208; CHECK: Just Mod (MustAlias):  Ptr: i8* %P        <->  tail call void @llvm.memset.p0i8.i64(i8* %P, i8 42, i64 8, i1 false)
209; CHECK: NoModRef:  Ptr: i8* %Q        <->  tail call void @llvm.memset.p0i8.i64(i8* %P, i8 42, i64 8, i1 false)
210; CHECK: Just Mod:  Ptr: i8* %P        <->  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
211; CHECK: Just Ref:  Ptr: i8* %Q        <->  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
212; CHECK: Just Mod:   tail call void @llvm.memset.p0i8.i64(i8* %P, i8 42, i64 8, i1 false) <->   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
213; CHECK: Just Mod:   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false) <->   tail call void @llvm.memset.p0i8.i64(i8* %P, i8 42, i64 8, i1 false)
214}
215
216define void @test5(i8* %P, i8* %Q, i8* %R) #3 {
217  load i8, i8* %P
218  load i8, i8* %Q
219  load i8, i8* %R
220  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
221  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %R, i64 12, i1 false)
222  ret void
223
224; CHECK-LABEL: Function: test5:
225
226; CHECK: MayAlias:     i8* %P, i8* %Q
227; CHECK: MayAlias:     i8* %P, i8* %R
228; CHECK: MayAlias:     i8* %Q, i8* %R
229; CHECK: Both ModRef:  Ptr: i8* %P     <->  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
230; CHECK: Both ModRef:  Ptr: i8* %Q     <->  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
231; CHECK: Both ModRef:  Ptr: i8* %R     <->  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
232; CHECK: Both ModRef:  Ptr: i8* %P     <->  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %R, i64 12, i1 false)
233; CHECK: Both ModRef:  Ptr: i8* %Q     <->  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %R, i64 12, i1 false)
234; CHECK: Both ModRef:  Ptr: i8* %R     <->  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %R, i64 12, i1 false)
235; CHECK: Both ModRef:   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false) <->   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %R, i64 12, i1 false)
236; CHECK: Both ModRef:   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %R, i64 12, i1 false) <->   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
237}
238
239define void @test5a(i8* noalias %P, i8* noalias %Q, i8* noalias %R) nounwind ssp {
240  load i8, i8* %P
241  load i8, i8* %Q
242  load i8, i8* %R
243  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
244  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %R, i64 12, i1 false)
245  ret void
246
247; CHECK-LABEL: Function: test5a:
248
249; CHECK: NoAlias:     i8* %P, i8* %Q
250; CHECK: NoAlias:     i8* %P, i8* %R
251; CHECK: NoAlias:     i8* %Q, i8* %R
252; CHECK: Just Mod:  Ptr: i8* %P     <->  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
253; CHECK: Just Ref:  Ptr: i8* %Q     <->  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
254; CHECK: NoModRef:  Ptr: i8* %R     <->  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
255; CHECK: Just Mod:  Ptr: i8* %P     <->  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %R, i64 12, i1 false)
256; CHECK: NoModRef:  Ptr: i8* %Q     <->  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %R, i64 12, i1 false)
257; CHECK: Just Ref:  Ptr: i8* %R     <->  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %R, i64 12, i1 false)
258; CHECK: Just Mod:   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false) <->   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %R, i64 12, i1 false)
259; CHECK: Just Mod:   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %R, i64 12, i1 false) <->   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
260}
261
262define void @test6(i8* %P) #3 {
263  load i8, i8* %P
264  call void @llvm.memset.p0i8.i64(i8* align 8 %P, i8 -51, i64 32, i1 false)
265  call void @a_readonly_func(i8* %P)
266  ret void
267
268; CHECK-LABEL: Function: test6:
269
270; CHECK: Just Mod (MustAlias):  Ptr: i8* %P        <->  call void @llvm.memset.p0i8.i64(i8* align 8 %P, i8 -51, i64 32, i1 false)
271; CHECK: Just Ref:  Ptr: i8* %P        <->  call void @a_readonly_func(i8* %P)
272; CHECK: Just Mod:   call void @llvm.memset.p0i8.i64(i8* align 8 %P, i8 -51, i64 32, i1 false) <->   call void @a_readonly_func(i8* %P)
273; CHECK: Just Ref:   call void @a_readonly_func(i8* %P) <->   call void @llvm.memset.p0i8.i64(i8* align 8 %P, i8 -51, i64 32, i1 false)
274}
275
276define void @test7(i8* %P) #3 {
277  load i8, i8* %P
278  call void @a_writeonly_func(i8* %P)
279  call void @a_readonly_func(i8* %P)
280  ret void
281
282; CHECK-LABEL: Function: test7:
283
284; CHECK: Just Mod:  Ptr: i8* %P        <->  call void @a_writeonly_func(i8* %P)
285; CHECK: Just Ref:  Ptr: i8* %P        <->  call void @a_readonly_func(i8* %P)
286; CHECK: Just Mod:   call void @a_writeonly_func(i8* %P) <->   call void @a_readonly_func(i8* %P)
287; CHECK: Just Ref:   call void @a_readonly_func(i8* %P) <->   call void @a_writeonly_func(i8* %P)
288}
289
290declare void @an_inaccessiblememonly_func() #4
291declare void @an_inaccessibleorargmemonly_func(i8*) #5
292declare void @an_argmemonly_func(i8*) #0
293
294define void @test8(i8* %p) {
295entry:
296  %q = getelementptr i8, i8* %p, i64 16
297  load i8, i8* %p
298  load i8, i8* %q
299  call void @a_readonly_func(i8* %p)
300  call void @an_inaccessiblememonly_func()
301  call void @a_writeonly_func(i8* %q)
302  call void @an_inaccessiblememonly_func()
303  call void @an_inaccessibleorargmemonly_func(i8* %q)
304  call void @an_argmemonly_func(i8* %q)
305  ret void
306
307; CHECK-LABEL: Function: test8
308; CHECK: NoModRef:  Ptr: i8* %p <->  call void @an_inaccessiblememonly_func()
309; CHECK: NoModRef:  Ptr: i8* %q <->  call void @an_inaccessiblememonly_func()
310; CHECK: Both ModRef:  Ptr: i8* %p <->  call void @an_inaccessibleorargmemonly_func(i8* %q)
311; CHECK: Both ModRef (MustAlias):  Ptr: i8* %q <->  call void @an_inaccessibleorargmemonly_func(i8* %q)
312; CHECK: Both ModRef:  Ptr: i8* %p <->  call void @an_argmemonly_func(i8* %q)
313; CHECK: Both ModRef (MustAlias):  Ptr: i8* %q <->  call void @an_argmemonly_func(i8* %q)
314; CHECK: Just Ref: call void @a_readonly_func(i8* %p) <-> call void @an_inaccessiblememonly_func()
315; CHECK: Just Ref: call void @a_readonly_func(i8* %p) <-> call void @an_inaccessibleorargmemonly_func(i8* %q)
316; CHECK: Just Ref: call void @a_readonly_func(i8* %p) <-> call void @an_argmemonly_func(i8* %q)
317; CHECK: Both ModRef: call void @an_inaccessiblememonly_func() <-> call void @a_readonly_func(i8* %p)
318; CHECK: Both ModRef: call void @an_inaccessiblememonly_func() <-> call void @a_writeonly_func(i8* %q)
319; CHECK: Both ModRef: call void @an_inaccessiblememonly_func() <-> call void @an_inaccessiblememonly_func()
320; CHECK: Both ModRef: call void @an_inaccessiblememonly_func() <-> call void @an_inaccessibleorargmemonly_func(i8* %q)
321; CHECK: NoModRef: call void @an_inaccessiblememonly_func() <-> call void @an_argmemonly_func(i8* %q)
322; CHECK: Just Mod: call void @a_writeonly_func(i8* %q) <-> call void @an_inaccessiblememonly_func()
323; CHECK: Just Mod: call void @a_writeonly_func(i8* %q) <-> call void @an_inaccessibleorargmemonly_func(i8* %q)
324; CHECK: Just Mod: call void @a_writeonly_func(i8* %q) <-> call void @an_argmemonly_func(i8* %q)
325; CHECK: Both ModRef: call void @an_inaccessibleorargmemonly_func(i8* %q) <-> call void @a_readonly_func(i8* %p)
326; CHECK: Both ModRef: call void @an_inaccessibleorargmemonly_func(i8* %q) <-> call void @a_writeonly_func(i8* %q)
327; CHECK: Both ModRef: call void @an_inaccessibleorargmemonly_func(i8* %q) <-> call void @an_inaccessiblememonly_func()
328; CHECK: Both ModRef (MustAlias): call void @an_inaccessibleorargmemonly_func(i8* %q) <-> call void @an_argmemonly_func(i8* %q)
329; CHECK: Both ModRef: call void @an_argmemonly_func(i8* %q) <-> call void @a_readonly_func(i8* %p)
330; CHECK: Both ModRef: call void @an_argmemonly_func(i8* %q) <-> call void @a_writeonly_func(i8* %q)
331; CHECK: NoModRef: call void @an_argmemonly_func(i8* %q) <-> call void @an_inaccessiblememonly_func()
332; CHECK: Both ModRef (MustAlias): call void @an_argmemonly_func(i8* %q) <-> call void @an_inaccessibleorargmemonly_func(i8* %q)
333}
334
335;; test that MustAlias is set for calls when no MayAlias is found.
336declare void @another_argmemonly_func(i8*, i8*) #0
337define void @test8a(i8* noalias %p, i8* noalias %q) {
338entry:
339  load i8, i8* %p
340  load i8, i8* %q
341  call void @another_argmemonly_func(i8* %p, i8* %q)
342  ret void
343
344; CHECK-LABEL: Function: test8a
345; CHECK: Both ModRef:  Ptr: i8* %p <->  call void @another_argmemonly_func(i8* %p, i8* %q)
346; CHECK: Both ModRef:  Ptr: i8* %q <->  call void @another_argmemonly_func(i8* %p, i8* %q)
347}
348define void @test8b(i8* %p, i8* %q) {
349entry:
350  load i8, i8* %p
351  load i8, i8* %q
352  call void @another_argmemonly_func(i8* %p, i8* %q)
353  ret void
354
355; CHECK-LABEL: Function: test8b
356; CHECK: Both ModRef:  Ptr: i8* %p <->  call void @another_argmemonly_func(i8* %p, i8* %q)
357; CHECK: Both ModRef:  Ptr: i8* %q <->  call void @another_argmemonly_func(i8* %p, i8* %q)
358}
359
360
361;; test that unknown operand bundle has unknown effect to the heap
362define void @test9(i8* %p) {
363; CHECK-LABEL: Function: test9
364entry:
365  %q = getelementptr i8, i8* %p, i64 16
366  load i8, i8* %p
367  load i8, i8* %q
368  call void @a_readonly_func(i8* %p) [ "unknown"() ]
369  call void @an_inaccessiblememonly_func() [ "unknown"() ]
370  call void @an_inaccessibleorargmemonly_func(i8* %q) [ "unknown"() ]
371  call void @an_argmemonly_func(i8* %q) [ "unknown"() ]
372  ret void
373
374; CHECK: Both ModRef:  Ptr: i8* %p     <->  call void @a_readonly_func(i8* %p) [ "unknown"() ]
375; CHECK: Both ModRef:  Ptr: i8* %q     <->  call void @a_readonly_func(i8* %p) [ "unknown"() ]
376; CHECK: Both ModRef:  Ptr: i8* %p     <->  call void @an_inaccessiblememonly_func() [ "unknown"() ]
377; CHECK: Both ModRef:  Ptr: i8* %q     <->  call void @an_inaccessiblememonly_func() [ "unknown"() ]
378; CHECK: Both ModRef:  Ptr: i8* %p     <->  call void @an_inaccessibleorargmemonly_func(i8* %q) [ "unknown"() ]
379; CHECK: Both ModRef:  Ptr: i8* %q     <->  call void @an_inaccessibleorargmemonly_func(i8* %q) [ "unknown"() ]
380; CHECK: Both ModRef:  Ptr: i8* %p     <->  call void @an_argmemonly_func(i8* %q) [ "unknown"() ]
381; CHECK: Both ModRef:  Ptr: i8* %q     <->  call void @an_argmemonly_func(i8* %q) [ "unknown"() ]
382; CHECK: Both ModRef:   call void @a_readonly_func(i8* %p) [ "unknown"() ] <->   call void @an_inaccessiblememonly_func() [ "unknown"() ]
383; CHECK: Both ModRef:   call void @a_readonly_func(i8* %p) [ "unknown"() ] <->   call void @an_inaccessibleorargmemonly_func(i8* %q) [ "unknown"() ]
384; CHECK: Both ModRef:   call void @a_readonly_func(i8* %p) [ "unknown"() ] <->   call void @an_argmemonly_func(i8* %q) [ "unknown"() ]
385; CHECK: Both ModRef:   call void @an_inaccessiblememonly_func() [ "unknown"() ] <->   call void @a_readonly_func(i8* %p) [ "unknown"() ]
386; CHECK: Both ModRef:   call void @an_inaccessiblememonly_func() [ "unknown"() ] <->   call void @an_inaccessibleorargmemonly_func(i8* %q) [ "unknown"() ]
387; CHECK: Both ModRef:   call void @an_inaccessiblememonly_func() [ "unknown"() ] <->   call void @an_argmemonly_func(i8* %q) [ "unknown"() ]
388; CHECK: Both ModRef:   call void @an_inaccessibleorargmemonly_func(i8* %q) [ "unknown"() ] <->   call void @a_readonly_func(i8* %p) [ "unknown"() ]
389; CHECK: Both ModRef:   call void @an_inaccessibleorargmemonly_func(i8* %q) [ "unknown"() ] <->   call void @an_inaccessiblememonly_func() [ "unknown"() ]
390; CHECK: Both ModRef:   call void @an_inaccessibleorargmemonly_func(i8* %q) [ "unknown"() ] <->   call void @an_argmemonly_func(i8* %q) [ "unknown"() ]
391; CHECK: Both ModRef:   call void @an_argmemonly_func(i8* %q) [ "unknown"() ] <->   call void @a_readonly_func(i8* %p) [ "unknown"() ]
392; CHECK: Both ModRef:   call void @an_argmemonly_func(i8* %q) [ "unknown"() ] <->   call void @an_inaccessiblememonly_func() [ "unknown"() ]
393; CHECK: Both ModRef:   call void @an_argmemonly_func(i8* %q) [ "unknown"() ] <->   call void @an_inaccessibleorargmemonly_func(i8* %q) [ "unknown"() ]
394}
395
396;; test callsite overwrite of unknown operand bundle
397define void @test10(i8* %p) {
398; CHECK-LABEL: Function: test10
399entry:
400  %q = getelementptr i8, i8* %p, i64 16
401  load i8, i8* %p
402  load i8, i8* %q
403  call void @a_readonly_func(i8* %p) #6 [ "unknown"() ]
404  call void @an_inaccessiblememonly_func() #7 [ "unknown"() ]
405  call void @an_inaccessibleorargmemonly_func(i8* %q) #8 [ "unknown"() ]
406  call void @an_argmemonly_func(i8* %q) #9 [ "unknown"() ]
407  ret void
408
409; CHECK: Just Ref:  Ptr: i8* %p        <->  call void @a_readonly_func(i8* %p) #9 [ "unknown"() ]
410; CHECK: Just Ref:  Ptr: i8* %q        <->  call void @a_readonly_func(i8* %p) #9 [ "unknown"() ]
411; CHECK: NoModRef:  Ptr: i8* %p        <->  call void @an_inaccessiblememonly_func() #10 [ "unknown"() ]
412; CHECK: NoModRef:  Ptr: i8* %q        <->  call void @an_inaccessiblememonly_func() #10 [ "unknown"() ]
413; CHECK: Both ModRef:  Ptr: i8* %p        <->  call void @an_inaccessibleorargmemonly_func(i8* %q) #11 [ "unknown"() ]
414; CHECK: Both ModRef (MustAlias):  Ptr: i8* %q     <->  call void @an_inaccessibleorargmemonly_func(i8* %q) #11 [ "unknown"() ]
415; CHECK: Both ModRef:  Ptr: i8* %p        <->  call void @an_argmemonly_func(i8* %q) #12 [ "unknown"() ]
416; CHECK: Both ModRef (MustAlias):  Ptr: i8* %q     <->  call void @an_argmemonly_func(i8* %q) #12 [ "unknown"() ]
417; CHECK: Just Ref:   call void @a_readonly_func(i8* %p) #9 [ "unknown"() ] <->   call void @an_inaccessiblememonly_func() #10 [ "unknown"() ]
418; CHECK: Just Ref:   call void @a_readonly_func(i8* %p) #9 [ "unknown"() ] <->   call void @an_inaccessibleorargmemonly_func(i8* %q) #11 [ "unknown"() ]
419; CHECK: Just Ref:   call void @a_readonly_func(i8* %p) #9 [ "unknown"() ] <->   call void @an_argmemonly_func(i8* %q) #12 [ "unknown"() ]
420; CHECK: Both ModRef:   call void @an_inaccessiblememonly_func() #10 [ "unknown"() ] <->   call void @a_readonly_func(i8* %p) #9 [ "unknown"() ]
421; CHECK: Both ModRef:   call void @an_inaccessiblememonly_func() #10 [ "unknown"() ] <->   call void @an_inaccessibleorargmemonly_func(i8* %q) #11 [ "unknown"() ]
422; CHECK: NoModRef:   call void @an_inaccessiblememonly_func() #10 [ "unknown"() ] <->   call void @an_argmemonly_func(i8* %q) #12 [ "unknown"() ]
423; CHECK: Both ModRef:   call void @an_inaccessibleorargmemonly_func(i8* %q) #11 [ "unknown"() ] <->   call void @a_readonly_func(i8* %p) #9 [ "unknown"() ]
424; CHECK: Both ModRef:   call void @an_inaccessibleorargmemonly_func(i8* %q) #11 [ "unknown"() ] <->   call void @an_inaccessiblememonly_func() #10 [ "unknown"() ]
425; CHECK: Both ModRef (MustAlias):   call void @an_inaccessibleorargmemonly_func(i8* %q) #11 [ "unknown"() ] <->   call void @an_argmemonly_func(i8* %q) #12 [ "unknown"() ]
426; CHECK: Both ModRef:   call void @an_argmemonly_func(i8* %q) #12 [ "unknown"() ] <->   call void @a_readonly_func(i8* %p) #9 [ "unknown"() ]
427; CHECK: NoModRef:   call void @an_argmemonly_func(i8* %q) #12 [ "unknown"() ] <->   call void @an_inaccessiblememonly_func() #10 [ "unknown"() ]
428; CHECK: Both ModRef (MustAlias):   call void @an_argmemonly_func(i8* %q) #12 [ "unknown"() ] <->   call void @an_inaccessibleorargmemonly_func(i8* %q) #11 [ "unknown"() ]
429}
430
431
432; CHECK:      attributes #0 = { argmemonly nocallback nofree nounwind willreturn writeonly }
433; CHECK-NEXT: attributes #1 = { argmemonly nocallback nofree nounwind willreturn }
434; CHECK-NEXT: attributes #2 = { argmemonly nosync nounwind willreturn }
435; CHECK-NEXT: attributes #3 = { noinline nounwind readonly }
436; CHECK-NEXT: attributes #4 = { noinline nounwind writeonly }
437; CHECK-NEXT: attributes #5 = { nounwind ssp }
438; CHECK-NEXT: attributes #6 = { inaccessiblememonly nounwind }
439; CHECK-NEXT: attributes #7 = { inaccessiblemem_or_argmemonly nounwind }
440; CHECK-NEXT: attributes #8 = { argmemonly nounwind }
441; CHECK-NEXT: attributes #9 = { readonly }
442; CHECK-NEXT: attributes #10 = { inaccessiblememonly }
443; CHECK-NEXT: attributes #11 = { inaccessiblemem_or_argmemonly }
444; CHECK-NEXT: attributes #12 = { argmemonly }
445
446attributes #0 = { argmemonly nounwind }
447attributes #1 = { noinline nounwind readonly }
448attributes #2 = { noinline nounwind writeonly }
449attributes #3 = { nounwind ssp }
450attributes #4 = { inaccessiblememonly nounwind }
451attributes #5 = { inaccessiblemem_or_argmemonly nounwind }
452attributes #6 = { readonly }
453attributes #7 = { inaccessiblememonly }
454attributes #8 = { inaccessiblemem_or_argmemonly }
455attributes #9 = { argmemonly }
456