mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 12:41:49 +01:00
[BasicAA] Teach BasicAA to handle the inaccessiblememonly and inaccessiblemem_or_argmemonly attributes
Differential Revision: https://reviews.llvm.org/D26382 llvm-svn: 286294
This commit is contained in:
parent
db0f0f6771
commit
c136ea50fc
@ -112,8 +112,10 @@ enum FunctionModRefLocation {
|
||||
FMRL_Nowhere = 0,
|
||||
/// Access to memory via argument pointers.
|
||||
FMRL_ArgumentPointees = 4,
|
||||
/// Memory that is inaccessible via LLVM IR.
|
||||
FMRL_InaccessibleMem = 8,
|
||||
/// Access to any memory.
|
||||
FMRL_Anywhere = 8 | FMRL_ArgumentPointees
|
||||
FMRL_Anywhere = 16 | FMRL_InaccessibleMem | FMRL_ArgumentPointees
|
||||
};
|
||||
|
||||
/// Summary of how a function affects memory in the program.
|
||||
@ -143,6 +145,22 @@ enum FunctionModRefBehavior {
|
||||
/// This property corresponds to the IntrArgMemOnly LLVM intrinsic flag.
|
||||
FMRB_OnlyAccessesArgumentPointees = FMRL_ArgumentPointees | MRI_ModRef,
|
||||
|
||||
/// The only memory references in this function (if it has any) are
|
||||
/// references of memory that is otherwise inaccessible via LLVM IR.
|
||||
///
|
||||
/// This property corresponds to the LLVM IR inaccessiblememonly attribute.
|
||||
FMRB_OnlyAccessesInaccessibleMem = FMRL_InaccessibleMem | MRI_ModRef,
|
||||
|
||||
/// The function may perform non-volatile loads and stores of objects
|
||||
/// pointed to by its pointer-typed arguments, with arbitrary offsets, and
|
||||
/// it may also perform loads and stores of memory that is otherwise
|
||||
/// inaccessible via LLVM IR.
|
||||
///
|
||||
/// This property corresponds to the LLVM IR
|
||||
/// inaccessiblemem_or_argmemonly attribute.
|
||||
FMRB_OnlyAccessesInaccessibleOrArgMem = FMRL_InaccessibleMem |
|
||||
FMRL_ArgumentPointees | MRI_ModRef,
|
||||
|
||||
/// This function does not perform any non-local stores or volatile loads,
|
||||
/// but may read from any memory location.
|
||||
///
|
||||
@ -339,6 +357,26 @@ public:
|
||||
return (MRB & MRI_ModRef) && (MRB & FMRL_ArgumentPointees);
|
||||
}
|
||||
|
||||
/// Checks if functions with the specified behavior are known to read and
|
||||
/// write at most from memory that is inaccessible from LLVM IR.
|
||||
static bool onlyAccessesInaccessibleMem(FunctionModRefBehavior MRB) {
|
||||
return !(MRB & FMRL_Anywhere & ~FMRL_InaccessibleMem);
|
||||
}
|
||||
|
||||
/// Checks if functions with the specified behavior are known to potentially
|
||||
/// read or write from memory that is inaccessible from LLVM IR.
|
||||
static bool doesAccessInaccessibleMem(FunctionModRefBehavior MRB) {
|
||||
return (MRB & MRI_ModRef) && (MRB & FMRL_InaccessibleMem);
|
||||
}
|
||||
|
||||
/// Checks if functions with the specified behavior are known to read and
|
||||
/// write at most from memory that is inaccessible from LLVM IR or objects
|
||||
/// pointed to by their pointer-typed arguments (with arbitrary offsets).
|
||||
static bool onlyAccessesInaccessibleOrArgMem(FunctionModRefBehavior MRB) {
|
||||
return !(MRB & FMRL_Anywhere &
|
||||
~(FMRL_InaccessibleMem | FMRL_ArgumentPointees));
|
||||
}
|
||||
|
||||
/// getModRefInfo (for call sites) - Return information about whether
|
||||
/// a particular call site modifies or reads the specified memory location.
|
||||
ModRefInfo getModRefInfo(ImmutableCallSite CS, const MemoryLocation &Loc);
|
||||
|
@ -141,7 +141,8 @@ ModRefInfo AAResults::getModRefInfo(ImmutableCallSite CS,
|
||||
// Try to refine the mod-ref info further using other API entry points to the
|
||||
// aggregate set of AA results.
|
||||
auto MRB = getModRefBehavior(CS);
|
||||
if (MRB == FMRB_DoesNotAccessMemory)
|
||||
if (MRB == FMRB_DoesNotAccessMemory ||
|
||||
MRB == FMRB_OnlyAccessesInaccessibleMem)
|
||||
return MRI_NoModRef;
|
||||
|
||||
if (onlyReadsMemory(MRB))
|
||||
@ -149,7 +150,7 @@ ModRefInfo AAResults::getModRefInfo(ImmutableCallSite CS,
|
||||
else if (doesNotReadMemory(MRB))
|
||||
Result = ModRefInfo(Result & MRI_Mod);
|
||||
|
||||
if (onlyAccessesArgPointees(MRB)) {
|
||||
if (onlyAccessesArgPointees(MRB) || onlyAccessesInaccessibleOrArgMem(MRB)) {
|
||||
bool DoesAlias = false;
|
||||
ModRefInfo AllArgsMask = MRI_NoModRef;
|
||||
if (doesAccessArgPointees(MRB)) {
|
||||
|
@ -609,6 +609,10 @@ FunctionModRefBehavior BasicAAResult::getModRefBehavior(const Function *F) {
|
||||
|
||||
if (F->onlyAccessesArgMemory())
|
||||
Min = FunctionModRefBehavior(Min & FMRB_OnlyAccessesArgumentPointees);
|
||||
else if (F->onlyAccessesInaccessibleMemory())
|
||||
Min = FunctionModRefBehavior(Min & FMRB_OnlyAccessesInaccessibleMem);
|
||||
else if (F->onlyAccessesInaccessibleMemOrArgMem())
|
||||
Min = FunctionModRefBehavior(Min & FMRB_OnlyAccessesInaccessibleOrArgMem);
|
||||
|
||||
return Min;
|
||||
}
|
||||
|
@ -23,18 +23,18 @@ entry:
|
||||
; CHECK-LABEL: Function: test1:
|
||||
|
||||
; CHECK: NoAlias: i8* %p, i8* %q
|
||||
; CHECK: Just Ref: Ptr: i8* %p <-> %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #5
|
||||
; CHECK: NoModRef: Ptr: i8* %q <-> %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #5
|
||||
; CHECK: Just Ref: Ptr: i8* %p <-> %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16)
|
||||
; CHECK: NoModRef: Ptr: i8* %q <-> %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16)
|
||||
; CHECK: NoModRef: Ptr: i8* %p <-> call void @llvm.arm.neon.vst1.p0i8.v8i16(i8* %q, <8 x i16> %y, i32 16)
|
||||
; CHECK: Both ModRef: Ptr: i8* %q <-> call void @llvm.arm.neon.vst1.p0i8.v8i16(i8* %q, <8 x i16> %y, i32 16)
|
||||
; CHECK: Just Ref: Ptr: i8* %p <-> %b = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #5
|
||||
; CHECK: NoModRef: Ptr: i8* %q <-> %b = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #5
|
||||
; 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)
|
||||
; 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
|
||||
; 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
|
||||
; 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
|
||||
; 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
|
||||
; 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)
|
||||
; CHECK: Just Ref: Ptr: i8* %p <-> %b = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16)
|
||||
; CHECK: NoModRef: Ptr: i8* %q <-> %b = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16)
|
||||
; 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)
|
||||
; 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)
|
||||
; 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)
|
||||
; 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)
|
||||
; 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)
|
||||
; 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)
|
||||
}
|
||||
|
||||
define void @test2(i8* %P, i8* %Q) nounwind ssp {
|
||||
@ -247,10 +247,45 @@ define void @test7(i8* %P) nounwind ssp {
|
||||
; CHECK: Just Ref: call void @a_readonly_func(i8* %P) <-> call void @a_writeonly_func(i8* %P)
|
||||
}
|
||||
|
||||
attributes #0 = { argmemonly nounwind readonly }
|
||||
attributes #1 = { argmemonly nounwind }
|
||||
attributes #2 = { noinline nounwind readonly }
|
||||
attributes #3 = { noinline nounwind writeonly }
|
||||
attributes #4 = { nounwind ssp }
|
||||
attributes #5 = { nounwind }
|
||||
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
|
||||
|
||||
define void @test8(i8* %p) {
|
||||
entry:
|
||||
%q = getelementptr i8, i8* %p, i64 16
|
||||
call void @a_readonly_func(i8* %p)
|
||||
call void @an_inaccessiblememonly_func()
|
||||
call void @a_writeonly_func(i8* %q)
|
||||
call void @an_inaccessiblememonly_func()
|
||||
call void @an_inaccessibleorargmemonly_func(i8* %q)
|
||||
call void @an_argmemonly_func(i8* %q)
|
||||
ret void
|
||||
|
||||
; CHECK-LABEL: Function: test8
|
||||
; CHECK: NoModRef: Ptr: i8* %p <-> call void @an_inaccessiblememonly_func()
|
||||
; CHECK: NoModRef: Ptr: i8* %q <-> call void @an_inaccessiblememonly_func()
|
||||
; CHECK: NoModRef: Ptr: i8* %p <-> call void @an_inaccessibleorargmemonly_func(i8* %q)
|
||||
; CHECK: Both ModRef: Ptr: i8* %q <-> call void @an_inaccessibleorargmemonly_func(i8* %q)
|
||||
; CHECK: NoModRef: Ptr: i8* %p <-> call void @an_argmemonly_func(i8* %q)
|
||||
; CHECK: Both ModRef: Ptr: i8* %q <-> call void @an_argmemonly_func(i8* %q)
|
||||
; CHECK: Just Ref: call void @a_readonly_func(i8* %p) <-> call void @an_inaccessiblememonly_func()
|
||||
; CHECK: Just Ref: call void @a_readonly_func(i8* %p) <-> call void @an_inaccessibleorargmemonly_func(i8* %q)
|
||||
; CHECK: Just Ref: call void @a_readonly_func(i8* %p) <-> call void @an_argmemonly_func(i8* %q)
|
||||
; CHECK: Both ModRef: call void @an_inaccessiblememonly_func() <-> call void @a_readonly_func(i8* %p)
|
||||
; CHECK: Both ModRef: call void @an_inaccessiblememonly_func() <-> call void @a_writeonly_func(i8* %q)
|
||||
; CHECK: Both ModRef: call void @an_inaccessiblememonly_func() <-> call void @an_inaccessiblememonly_func()
|
||||
; CHECK: Both ModRef: call void @an_inaccessiblememonly_func() <-> call void @an_inaccessibleorargmemonly_func(i8* %q)
|
||||
; CHECK: NoModRef: call void @an_inaccessiblememonly_func() <-> call void @an_argmemonly_func(i8* %q)
|
||||
; CHECK: Just Mod: call void @a_writeonly_func(i8* %q) <-> call void @an_inaccessiblememonly_func()
|
||||
; CHECK: Just Mod: call void @a_writeonly_func(i8* %q) <-> call void @an_inaccessibleorargmemonly_func(i8* %q)
|
||||
; CHECK: Just Mod: call void @a_writeonly_func(i8* %q) <-> call void @an_argmemonly_func(i8* %q)
|
||||
; CHECK: Both ModRef: call void @an_inaccessibleorargmemonly_func(i8* %q) <-> call void @a_readonly_func(i8* %p)
|
||||
; CHECK: Both ModRef: call void @an_inaccessibleorargmemonly_func(i8* %q) <-> call void @a_writeonly_func(i8* %q)
|
||||
; CHECK: Both ModRef: call void @an_inaccessibleorargmemonly_func(i8* %q) <-> call void @an_inaccessiblememonly_func()
|
||||
; CHECK: Both ModRef: call void @an_inaccessibleorargmemonly_func(i8* %q) <-> call void @an_argmemonly_func(i8* %q)
|
||||
; CHECK: Both ModRef: call void @an_argmemonly_func(i8* %q) <-> call void @a_readonly_func(i8* %p)
|
||||
; CHECK: Both ModRef: call void @an_argmemonly_func(i8* %q) <-> call void @a_writeonly_func(i8* %q)
|
||||
; 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)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user