forked from OSchip/llvm-project
[BasicAA] Take attributes into account when requesting modref info for a call site
Differential Revision: https://reviews.llvm.org/D29989 llvm-svn: 296617
This commit is contained in:
parent
9e745b7292
commit
37cba43604
|
@ -583,6 +583,11 @@ public:
|
|||
dataOperandHasImpliedAttr(OpNo + 1, Attribute::ReadNone);
|
||||
}
|
||||
|
||||
bool doesNotReadMemory(unsigned OpNo) const {
|
||||
return dataOperandHasImpliedAttr(OpNo + 1, Attribute::WriteOnly) ||
|
||||
dataOperandHasImpliedAttr(OpNo + 1, Attribute::ReadNone);
|
||||
}
|
||||
|
||||
/// Return true if the return value is known to be not null.
|
||||
/// This may be because it has the nonnull attribute, or because at least
|
||||
/// one byte is dereferenceable and the pointer is in addrspace(0).
|
||||
|
|
|
@ -749,7 +749,11 @@ ModRefInfo BasicAAResult::getModRefInfo(ImmutableCallSite CS,
|
|||
// as an argument, and itself doesn't capture it.
|
||||
if (!isa<Constant>(Object) && CS.getInstruction() != Object &&
|
||||
isNonEscapingLocalObject(Object)) {
|
||||
bool PassedAsArg = false;
|
||||
|
||||
// Optimistically assume that call doesn't touch Object and check this
|
||||
// assumption in the following loop.
|
||||
ModRefInfo Result = MRI_NoModRef;
|
||||
|
||||
unsigned OperandNo = 0;
|
||||
for (auto CI = CS.data_operands_begin(), CE = CS.data_operands_end();
|
||||
CI != CE; ++CI, ++OperandNo) {
|
||||
|
@ -761,20 +765,38 @@ ModRefInfo BasicAAResult::getModRefInfo(ImmutableCallSite CS,
|
|||
OperandNo < CS.getNumArgOperands() && !CS.isByValArgument(OperandNo)))
|
||||
continue;
|
||||
|
||||
// Call doesn't access memory through this operand, so we don't care
|
||||
// if it aliases with Object.
|
||||
if (CS.doesNotAccessMemory(OperandNo))
|
||||
continue;
|
||||
|
||||
// If this is a no-capture pointer argument, see if we can tell that it
|
||||
// is impossible to alias the pointer we're checking. If not, we have to
|
||||
// assume that the call could touch the pointer, even though it doesn't
|
||||
// escape.
|
||||
// is impossible to alias the pointer we're checking.
|
||||
AliasResult AR =
|
||||
getBestAAResults().alias(MemoryLocation(*CI), MemoryLocation(Object));
|
||||
if (AR) {
|
||||
PassedAsArg = true;
|
||||
break;
|
||||
|
||||
// Operand doesnt alias 'Object', continue looking for other aliases
|
||||
if (AR == NoAlias)
|
||||
continue;
|
||||
// Operand aliases 'Object', but call doesn't modify it. Strengthen
|
||||
// initial assumption and keep looking in case if there are more aliases.
|
||||
if (CS.onlyReadsMemory(OperandNo)) {
|
||||
Result = static_cast<ModRefInfo>(Result | MRI_Ref);
|
||||
continue;
|
||||
}
|
||||
// Operand aliases 'Object' but call only writes into it.
|
||||
if (CS.doesNotReadMemory(OperandNo)) {
|
||||
Result = static_cast<ModRefInfo>(Result | MRI_Mod);
|
||||
continue;
|
||||
}
|
||||
// This operand aliases 'Object' and call reads and writes into it.
|
||||
Result = MRI_ModRef;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!PassedAsArg)
|
||||
return MRI_NoModRef;
|
||||
// Early return if we improved mod ref information
|
||||
if (Result != MRI_ModRef)
|
||||
return Result;
|
||||
}
|
||||
|
||||
// If the CallSite is to malloc or calloc, we can assume that it doesn't
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
; RUN: opt < %s -basicaa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
|
||||
|
||||
declare void @readonly_attr(i8* readonly nocapture)
|
||||
declare void @writeonly_attr(i8* writeonly nocapture)
|
||||
declare void @readnone_attr(i8* readnone nocapture)
|
||||
|
||||
declare void @readonly_func(i8* nocapture) readonly
|
||||
declare void @writeonly_func(i8* nocapture) writeonly
|
||||
declare void @readnone_func(i8* nocapture) readnone
|
||||
|
||||
declare void @read_write(i8* writeonly nocapture, i8* readonly nocapture, i8* readnone nocapture)
|
||||
|
||||
declare void @func()
|
||||
|
||||
define void @test(i8* noalias %p) {
|
||||
entry:
|
||||
call void @readonly_attr(i8* %p)
|
||||
call void @readonly_func(i8* %p)
|
||||
|
||||
call void @writeonly_attr(i8* %p)
|
||||
call void @writeonly_func(i8* %p)
|
||||
|
||||
call void @readnone_attr(i8* %p)
|
||||
call void @readnone_func(i8* %p)
|
||||
|
||||
call void @read_write(i8* %p, i8* %p, i8* %p)
|
||||
|
||||
call void @func() ["deopt" (i8* %p)]
|
||||
call void @writeonly_attr(i8* %p) ["deopt" (i8* %p)]
|
||||
|
||||
ret void
|
||||
}
|
||||
|
||||
; CHECK: Just Ref: Ptr: i8* %p <-> call void @readonly_attr(i8* %p)
|
||||
; CHECK: Just Ref: Ptr: i8* %p <-> call void @readonly_func(i8* %p)
|
||||
; CHECK: Just Mod: Ptr: i8* %p <-> call void @writeonly_attr(i8* %p)
|
||||
; CHECK: Just Mod: Ptr: i8* %p <-> call void @writeonly_func(i8* %p)
|
||||
; CHECK: NoModRef: Ptr: i8* %p <-> call void @readnone_attr(i8* %p)
|
||||
; CHECK: NoModRef: Ptr: i8* %p <-> call void @readnone_func(i8* %p)
|
||||
; CHECK: Both ModRef: Ptr: i8* %p <-> call void @read_write(i8* %p, i8* %p, i8* %p)
|
||||
; CHECK: Just Ref: Ptr: i8* %p <-> call void @func() [ "deopt"(i8* %p) ]
|
||||
; CHECK: Both ModRef: Ptr: i8* %p <-> call void @writeonly_attr(i8* %p) [ "deopt"(i8* %p) ]
|
|
@ -1,4 +1,3 @@
|
|||
; XFAIL: *
|
||||
; RUN: opt -newgvn -S -o - < %s | FileCheck %s
|
||||
|
||||
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
|
||||
|
|
Loading…
Reference in New Issue