llvm.org GIT mirror llvm / 665c3d9
[BasicAA] Teach BasicAA to handle the inaccessiblememonly and inaccessiblemem_or_argmemonly attributes Differential Revision: https://reviews.llvm.org/D26382 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@286294 91177308-0d34-0410-b5e6-96231b3b80d8 Andrew Kaylor 3 years ago
4 changed file(s) with 98 addition(s) and 20 deletion(s). Raw diff Collapse all Expand all
111111 FMRL_Nowhere = 0,
112112 /// Access to memory via argument pointers.
113113 FMRL_ArgumentPointees = 4,
114 /// Memory that is inaccessible via LLVM IR.
115 FMRL_InaccessibleMem = 8,
114116 /// Access to any memory.
115 FMRL_Anywhere = 8 | FMRL_ArgumentPointees
117 FMRL_Anywhere = 16 | FMRL_InaccessibleMem | FMRL_ArgumentPointees
116118 };
117119
118120 /// Summary of how a function affects memory in the program.
141143 ///
142144 /// This property corresponds to the IntrArgMemOnly LLVM intrinsic flag.
143145 FMRB_OnlyAccessesArgumentPointees = FMRL_ArgumentPointees | MRI_ModRef,
146
147 /// The only memory references in this function (if it has any) are
148 /// references of memory that is otherwise inaccessible via LLVM IR.
149 ///
150 /// This property corresponds to the LLVM IR inaccessiblememonly attribute.
151 FMRB_OnlyAccessesInaccessibleMem = FMRL_InaccessibleMem | MRI_ModRef,
152
153 /// The function may perform non-volatile loads and stores of objects
154 /// pointed to by its pointer-typed arguments, with arbitrary offsets, and
155 /// it may also perform loads and stores of memory that is otherwise
156 /// inaccessible via LLVM IR.
157 ///
158 /// This property corresponds to the LLVM IR
159 /// inaccessiblemem_or_argmemonly attribute.
160 FMRB_OnlyAccessesInaccessibleOrArgMem = FMRL_InaccessibleMem |
161 FMRL_ArgumentPointees | MRI_ModRef,
144162
145163 /// This function does not perform any non-local stores or volatile loads,
146164 /// but may read from any memory location.
336354 /// (with arbitrary offsets).
337355 static bool doesAccessArgPointees(FunctionModRefBehavior MRB) {
338356 return (MRB & MRI_ModRef) && (MRB & FMRL_ArgumentPointees);
357 }
358
359 /// Checks if functions with the specified behavior are known to read and
360 /// write at most from memory that is inaccessible from LLVM IR.
361 static bool onlyAccessesInaccessibleMem(FunctionModRefBehavior MRB) {
362 return !(MRB & FMRL_Anywhere & ~FMRL_InaccessibleMem);
363 }
364
365 /// Checks if functions with the specified behavior are known to potentially
366 /// read or write from memory that is inaccessible from LLVM IR.
367 static bool doesAccessInaccessibleMem(FunctionModRefBehavior MRB) {
368 return (MRB & MRI_ModRef) && (MRB & FMRL_InaccessibleMem);
369 }
370
371 /// Checks if functions with the specified behavior are known to read and
372 /// write at most from memory that is inaccessible from LLVM IR or objects
373 /// pointed to by their pointer-typed arguments (with arbitrary offsets).
374 static bool onlyAccessesInaccessibleOrArgMem(FunctionModRefBehavior MRB) {
375 return !(MRB & FMRL_Anywhere &
376 ~(FMRL_InaccessibleMem | FMRL_ArgumentPointees));
339377 }
340378
341379 /// getModRefInfo (for call sites) - Return information about whether
140140 // Try to refine the mod-ref info further using other API entry points to the
141141 // aggregate set of AA results.
142142 auto MRB = getModRefBehavior(CS);
143 if (MRB == FMRB_DoesNotAccessMemory)
143 if (MRB == FMRB_DoesNotAccessMemory ||
144 MRB == FMRB_OnlyAccessesInaccessibleMem)
144145 return MRI_NoModRef;
145146
146147 if (onlyReadsMemory(MRB))
148149 else if (doesNotReadMemory(MRB))
149150 Result = ModRefInfo(Result & MRI_Mod);
150151
151 if (onlyAccessesArgPointees(MRB)) {
152 if (onlyAccessesArgPointees(MRB) || onlyAccessesInaccessibleOrArgMem(MRB)) {
152153 bool DoesAlias = false;
153154 ModRefInfo AllArgsMask = MRI_NoModRef;
154155 if (doesAccessArgPointees(MRB)) {
608608
609609 if (F->onlyAccessesArgMemory())
610610 Min = FunctionModRefBehavior(Min & FMRB_OnlyAccessesArgumentPointees);
611 else if (F->onlyAccessesInaccessibleMemory())
612 Min = FunctionModRefBehavior(Min & FMRB_OnlyAccessesInaccessibleMem);
613 else if (F->onlyAccessesInaccessibleMemOrArgMem())
614 Min = FunctionModRefBehavior(Min & FMRB_OnlyAccessesInaccessibleOrArgMem);
611615
612616 return Min;
613617 }
2222 ; CHECK-LABEL: Function: test1:
2323
2424 ; CHECK: NoAlias: i8* %p, i8* %q
25 ; CHECK: Just Ref: Ptr: i8* %p <-> %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #5
26 ; CHECK: NoModRef: Ptr: i8* %q <-> %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #5
25 ; CHECK: Just Ref: Ptr: i8* %p <-> %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16)
26 ; CHECK: NoModRef: Ptr: i8* %q <-> %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16)
2727 ; CHECK: NoModRef: Ptr: i8* %p <-> call void @llvm.arm.neon.vst1.p0i8.v8i16(i8* %q, <8 x i16> %y, i32 16)
2828 ; CHECK: Both ModRef: Ptr: i8* %q <-> call void @llvm.arm.neon.vst1.p0i8.v8i16(i8* %q, <8 x i16> %y, i32 16)
29 ; CHECK: Just Ref: Ptr: i8* %p <-> %b = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #5
30 ; CHECK: NoModRef: Ptr: i8* %q <-> %b = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #5
31 ; CHECK: NoModRef: %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #5 <-> call void @llvm.arm.neon.vst1.p0i8.v8i16(i8* %q, <8 x i16> %y, i32 16)
32 ; CHECK: NoModRef: %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #5 <-> %b = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #5
33 ; CHECK: NoModRef: call void @llvm.arm.neon.vst1.p0i8.v8i16(i8* %q, <8 x i16> %y, i32 16) <-> %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #5
34 ; CHECK: NoModRef: call void @llvm.arm.neon.vst1.p0i8.v8i16(i8* %q, <8 x i16> %y, i32 16) <-> %b = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #5
35 ; CHECK: NoModRef: %b = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #5 <-> %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #5
36 ; CHECK: NoModRef: %b = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #5 <-> call void @llvm.arm.neon.vst1.p0i8.v8i16(i8* %q, <8 x i16> %y, i32 16)
29 ; CHECK: Just Ref: Ptr: i8* %p <-> %b = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16)
30 ; CHECK: NoModRef: Ptr: i8* %q <-> %b = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16)
31 ; CHECK: NoModRef: %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #{{[0-9]+}} <-> call void @llvm.arm.neon.vst1.p0i8.v8i16(i8* %q, <8 x i16> %y, i32 16)
32 ; CHECK: NoModRef: %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #{{[0-9]+}} <-> %b = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16)
33 ; CHECK: NoModRef: call void @llvm.arm.neon.vst1.p0i8.v8i16(i8* %q, <8 x i16> %y, i32 16) <-> %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16)
34 ; CHECK: NoModRef: call void @llvm.arm.neon.vst1.p0i8.v8i16(i8* %q, <8 x i16> %y, i32 16) <-> %b = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16)
35 ; CHECK: NoModRef: %b = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #{{[0-9]+}} <-> %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16)
36 ; CHECK: NoModRef: %b = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #{{[0-9]+}} <-> call void @llvm.arm.neon.vst1.p0i8.v8i16(i8* %q, <8 x i16> %y, i32 16)
3737 }
3838
3939 define void @test2(i8* %P, i8* %Q) nounwind ssp {
246246 ; CHECK: Just Ref: call void @a_readonly_func(i8* %P) <-> call void @a_writeonly_func(i8* %P)
247247 }
248248
249 attributes #0 = { argmemonly nounwind readonly }
250 attributes #1 = { argmemonly nounwind }
251 attributes #2 = { noinline nounwind readonly }
252 attributes #3 = { noinline nounwind writeonly }
253 attributes #4 = { nounwind ssp }
254 attributes #5 = { nounwind }
255
249 declare void @an_inaccessiblememonly_func() nounwind inaccessiblememonly
250 declare void @an_inaccessibleorargmemonly_func(i8 *) nounwind inaccessiblemem_or_argmemonly
251 declare void @an_argmemonly_func(i8 *) nounwind argmemonly
252
253 define void @test8(i8* %p) {
254 entry:
255 %q = getelementptr i8, i8* %p, i64 16
256 call void @a_readonly_func(i8* %p)
257 call void @an_inaccessiblememonly_func()
258 call void @a_writeonly_func(i8* %q)
259 call void @an_inaccessiblememonly_func()
260 call void @an_inaccessibleorargmemonly_func(i8* %q)
261 call void @an_argmemonly_func(i8* %q)
262 ret void
263
264 ; CHECK-LABEL: Function: test8
265 ; CHECK: NoModRef: Ptr: i8* %p <-> call void @an_inaccessiblememonly_func()
266 ; CHECK: NoModRef: Ptr: i8* %q <-> call void @an_inaccessiblememonly_func()
267 ; CHECK: NoModRef: Ptr: i8* %p <-> call void @an_inaccessibleorargmemonly_func(i8* %q)
268 ; CHECK: Both ModRef: Ptr: i8* %q <-> call void @an_inaccessibleorargmemonly_func(i8* %q)
269 ; CHECK: NoModRef: Ptr: i8* %p <-> call void @an_argmemonly_func(i8* %q)
270 ; CHECK: Both ModRef: Ptr: i8* %q <-> call void @an_argmemonly_func(i8* %q)
271 ; CHECK: Just Ref: call void @a_readonly_func(i8* %p) <-> call void @an_inaccessiblememonly_func()
272 ; CHECK: Just Ref: call void @a_readonly_func(i8* %p) <-> call void @an_inaccessibleorargmemonly_func(i8* %q)
273 ; CHECK: Just Ref: call void @a_readonly_func(i8* %p) <-> call void @an_argmemonly_func(i8* %q)
274 ; CHECK: Both ModRef: call void @an_inaccessiblememonly_func() <-> call void @a_readonly_func(i8* %p)
275 ; CHECK: Both ModRef: call void @an_inaccessiblememonly_func() <-> call void @a_writeonly_func(i8* %q)
276 ; CHECK: Both ModRef: call void @an_inaccessiblememonly_func() <-> call void @an_inaccessiblememonly_func()
277 ; CHECK: Both ModRef: call void @an_inaccessiblememonly_func() <-> call void @an_inaccessibleorargmemonly_func(i8* %q)
278 ; CHECK: NoModRef: call void @an_inaccessiblememonly_func() <-> call void @an_argmemonly_func(i8* %q)
279 ; CHECK: Just Mod: call void @a_writeonly_func(i8* %q) <-> call void @an_inaccessiblememonly_func()
280 ; CHECK: Just Mod: call void @a_writeonly_func(i8* %q) <-> call void @an_inaccessibleorargmemonly_func(i8* %q)
281 ; CHECK: Just Mod: call void @a_writeonly_func(i8* %q) <-> call void @an_argmemonly_func(i8* %q)
282 ; CHECK: Both ModRef: call void @an_inaccessibleorargmemonly_func(i8* %q) <-> call void @a_readonly_func(i8* %p)
283 ; CHECK: Both ModRef: call void @an_inaccessibleorargmemonly_func(i8* %q) <-> call void @a_writeonly_func(i8* %q)
284 ; CHECK: Both ModRef: call void @an_inaccessibleorargmemonly_func(i8* %q) <-> call void @an_inaccessiblememonly_func()
285 ; CHECK: Both ModRef: call void @an_inaccessibleorargmemonly_func(i8* %q) <-> call void @an_argmemonly_func(i8* %q)
286 ; CHECK: Both ModRef: call void @an_argmemonly_func(i8* %q) <-> call void @a_readonly_func(i8* %p)
287 ; CHECK: Both ModRef: call void @an_argmemonly_func(i8* %q) <-> call void @a_writeonly_func(i8* %q)
288 ; CHECK: NoModRef: call void @an_argmemonly_func(i8* %q) <-> call void @an_inaccessiblememonly_func()
289 ; CHECK: Both ModRef: call void @an_argmemonly_func(i8* %q) <-> call void @an_inaccessibleorargmemonly_func(i8* %q)
290 }