[AliasAnalysis] Add missing FMRB_* enums.

Previously, the enums didn't account for all the possible cases, which
could cause misleading results (particularly for a "switch" on
FunctionModRefBehavior).

Fixes regression in polly from recent patch to add writeonly to memset.

While I'm here, also fix a few dubious uses of the FMRB_* enum values.

Differential Revision: https://reviews.llvm.org/D73154
This commit is contained in:
Eli Friedman 2020-01-21 16:51:17 -08:00
parent 0d401fa36b
commit 2f6b9edfa8
7 changed files with 64 additions and 12 deletions

View File

@ -226,10 +226,20 @@ enum FunctionModRefBehavior {
/// non-volatile loads from objects pointed to by its pointer-typed
/// arguments, with arbitrary offsets.
///
/// This property corresponds to the IntrReadArgMem LLVM intrinsic flag.
/// This property corresponds to the combination of the IntrReadMem
/// and IntrArgMemOnly LLVM intrinsic flags.
FMRB_OnlyReadsArgumentPointees =
FMRL_ArgumentPointees | static_cast<int>(ModRefInfo::Ref),
/// The only memory references in this function (if it has any) are
/// non-volatile stores from objects pointed to by its pointer-typed
/// arguments, with arbitrary offsets.
///
/// This property corresponds to the combination of the IntrWriteMem
/// and IntrArgMemOnly LLVM intrinsic flags.
FMRB_OnlyWritesArgumentPointees =
FMRL_ArgumentPointees | static_cast<int>(ModRefInfo::Mod),
/// The only memory references in this function (if it has any) are
/// non-volatile loads and stores from objects pointed to by its
/// pointer-typed arguments, with arbitrary offsets.
@ -238,6 +248,20 @@ enum FunctionModRefBehavior {
FMRB_OnlyAccessesArgumentPointees =
FMRL_ArgumentPointees | static_cast<int>(ModRefInfo::ModRef),
/// The only memory references in this function (if it has any) are
/// reads of memory that is otherwise inaccessible via LLVM IR.
///
/// This property corresponds to the LLVM IR inaccessiblememonly attribute.
FMRB_OnlyReadsInaccessibleMem =
FMRL_InaccessibleMem | static_cast<int>(ModRefInfo::Ref),
/// The only memory references in this function (if it has any) are
/// writes to memory that is otherwise inaccessible via LLVM IR.
///
/// This property corresponds to the LLVM IR inaccessiblememonly attribute.
FMRB_OnlyWritesInaccessibleMem =
FMRL_InaccessibleMem | static_cast<int>(ModRefInfo::Mod),
/// The only memory references in this function (if it has any) are
/// references of memory that is otherwise inaccessible via LLVM IR.
///
@ -245,6 +269,28 @@ enum FunctionModRefBehavior {
FMRB_OnlyAccessesInaccessibleMem =
FMRL_InaccessibleMem | static_cast<int>(ModRefInfo::ModRef),
/// The function may perform non-volatile loads from objects pointed
/// to by its pointer-typed arguments, with arbitrary offsets, and
/// it may also perform loads of memory that is otherwise
/// inaccessible via LLVM IR.
///
/// This property corresponds to the LLVM IR
/// inaccessiblemem_or_argmemonly attribute.
FMRB_OnlyReadsInaccessibleOrArgMem = FMRL_InaccessibleMem |
FMRL_ArgumentPointees |
static_cast<int>(ModRefInfo::Ref),
/// The function may perform non-volatile stores to objects pointed
/// to by its pointer-typed arguments, with arbitrary offsets, and
/// it may also perform stores of memory that is otherwise
/// inaccessible via LLVM IR.
///
/// This property corresponds to the LLVM IR
/// inaccessiblemem_or_argmemonly attribute.
FMRB_OnlyWritesInaccessibleOrArgMem = FMRL_InaccessibleMem |
FMRL_ArgumentPointees |
static_cast<int>(ModRefInfo::Mod),
/// 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
@ -269,7 +315,7 @@ enum FunctionModRefBehavior {
//
// This property corresponds to the LLVM IR 'writeonly' attribute.
// This property corresponds to the IntrWriteMem LLVM intrinsic flag.
FMRB_DoesNotReadMemory = FMRL_Anywhere | static_cast<int>(ModRefInfo::Mod),
FMRB_OnlyWritesMemory = FMRL_Anywhere | static_cast<int>(ModRefInfo::Mod),
/// This indicates that the function could not be classified into one of the
/// behaviors above.

View File

@ -196,8 +196,7 @@ ModRefInfo AAResults::getModRefInfo(const CallBase *Call,
// Try to refine the mod-ref info further using other API entry points to the
// aggregate set of AA results.
auto MRB = getModRefBehavior(Call);
if (MRB == FMRB_DoesNotAccessMemory ||
MRB == FMRB_OnlyAccessesInaccessibleMem)
if (onlyAccessesInaccessibleMem(MRB))
return ModRefInfo::NoModRef;
if (onlyReadsMemory(MRB))

View File

@ -723,7 +723,7 @@ FunctionModRefBehavior BasicAAResult::getModRefBehavior(const CallBase *Call) {
if (Call->onlyReadsMemory())
Min = FMRB_OnlyReadsMemory;
else if (Call->doesNotReadMemory())
Min = FMRB_DoesNotReadMemory;
Min = FMRB_OnlyWritesMemory;
if (Call->onlyAccessesArgMemory())
Min = FunctionModRefBehavior(Min & FMRB_OnlyAccessesArgumentPointees);
@ -756,7 +756,7 @@ FunctionModRefBehavior BasicAAResult::getModRefBehavior(const Function *F) {
if (F->onlyReadsMemory())
Min = FMRB_OnlyReadsMemory;
else if (F->doesNotReadMemory())
Min = FMRB_DoesNotReadMemory;
Min = FMRB_OnlyWritesMemory;
if (F->onlyAccessesArgMemory())
Min = FunctionModRefBehavior(Min & FMRB_OnlyAccessesArgumentPointees);

View File

@ -1002,8 +1002,7 @@ static void AddAliasScopeMetadata(CallSite CS, ValueToValueMapTy &VMap,
IsFuncCall = true;
if (CalleeAAR) {
FunctionModRefBehavior MRB = CalleeAAR->getModRefBehavior(Call);
if (MRB == FMRB_OnlyAccessesArgumentPointees ||
MRB == FMRB_OnlyReadsArgumentPointees)
if (AAResults::onlyAccessesArgPointees(MRB))
IsArgMemOnlyCall = true;
}

View File

@ -1809,16 +1809,21 @@ bool ScopBuilder::buildAccessCallInst(MemAccInst Inst, ScopStmt *Stmt) {
llvm_unreachable("Unknown mod ref behaviour cannot be represented.");
case FMRB_DoesNotAccessMemory:
return true;
case FMRB_DoesNotReadMemory:
case FMRB_OnlyWritesMemory:
case FMRB_OnlyWritesInaccessibleMem:
case FMRB_OnlyWritesInaccessibleOrArgMem:
case FMRB_OnlyAccessesInaccessibleMem:
case FMRB_OnlyAccessesInaccessibleOrArgMem:
return false;
case FMRB_OnlyReadsMemory:
case FMRB_OnlyReadsInaccessibleMem:
case FMRB_OnlyReadsInaccessibleOrArgMem:
GlobalReads.emplace_back(Stmt, CI);
return true;
case FMRB_OnlyReadsArgumentPointees:
ReadOnly = true;
LLVM_FALLTHROUGH;
case FMRB_OnlyWritesArgumentPointees:
case FMRB_OnlyAccessesArgumentPointees: {
auto AccType = ReadOnly ? MemoryAccess::READ : MemoryAccess::MAY_WRITE;
Loop *L = LI.getLoopFor(Inst->getParent());

View File

@ -696,6 +696,8 @@ bool ScopDetection::isValidCallInst(CallInst &CI,
return false;
case FMRB_DoesNotAccessMemory:
case FMRB_OnlyReadsMemory:
case FMRB_OnlyReadsInaccessibleMem:
case FMRB_OnlyReadsInaccessibleOrArgMem:
// Implicitly disable delinearization since we have an unknown
// accesses with an unknown access function.
Context.HasUnknownAccess = true;
@ -705,6 +707,7 @@ bool ScopDetection::isValidCallInst(CallInst &CI,
return true;
case FMRB_OnlyReadsArgumentPointees:
case FMRB_OnlyAccessesArgumentPointees:
case FMRB_OnlyWritesArgumentPointees:
for (const auto &Arg : CI.arg_operands()) {
if (!Arg->getType()->isPointerTy())
continue;
@ -728,7 +731,9 @@ bool ScopDetection::isValidCallInst(CallInst &CI,
// pointer into the alias set.
Context.AST.addUnknown(&CI);
return true;
case FMRB_DoesNotReadMemory:
case FMRB_OnlyWritesMemory:
case FMRB_OnlyWritesInaccessibleMem:
case FMRB_OnlyWritesInaccessibleOrArgMem:
case FMRB_OnlyAccessesInaccessibleMem:
case FMRB_OnlyAccessesInaccessibleOrArgMem:
return false;

View File

@ -1,7 +1,5 @@
; RUN: opt %loadPolly -polly-allow-modref-calls -polly-scops -analyze < %s | FileCheck %s
; RUN: opt %loadPolly -polly-allow-modref-calls -S -polly-codegen < %s
; XFAIL'ed due to change to memset attributes.
; XFAIL: *
;
; Verify we can handle a memset to "null" and that we do not model it.
; TODO: FIXME: We could use the undefined memset to optimize the code further,