diff --git a/llvm/include/llvm/Analysis/AliasAnalysis.h b/llvm/include/llvm/Analysis/AliasAnalysis.h --- a/llvm/include/llvm/Analysis/AliasAnalysis.h +++ b/llvm/include/llvm/Analysis/AliasAnalysis.h @@ -226,11 +226,21 @@ /// 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(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(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. /// @@ -239,12 +249,48 @@ FMRL_ArgumentPointees | static_cast(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(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(ModRefInfo::Mod), + + /// 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 | static_cast(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(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(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 @@ // // This property corresponds to the LLVM IR 'writeonly' attribute. // This property corresponds to the IntrWriteMem LLVM intrinsic flag. - FMRB_DoesNotReadMemory = FMRL_Anywhere | static_cast(ModRefInfo::Mod), + FMRB_OnlyWritesMemory = FMRL_Anywhere | static_cast(ModRefInfo::Mod), /// This indicates that the function could not be classified into one of the /// behaviors above. diff --git a/llvm/lib/Analysis/AliasAnalysis.cpp b/llvm/lib/Analysis/AliasAnalysis.cpp --- a/llvm/lib/Analysis/AliasAnalysis.cpp +++ b/llvm/lib/Analysis/AliasAnalysis.cpp @@ -196,8 +196,7 @@ // 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)) diff --git a/llvm/lib/Analysis/BasicAliasAnalysis.cpp b/llvm/lib/Analysis/BasicAliasAnalysis.cpp --- a/llvm/lib/Analysis/BasicAliasAnalysis.cpp +++ b/llvm/lib/Analysis/BasicAliasAnalysis.cpp @@ -723,7 +723,7 @@ 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 @@ if (F->onlyReadsMemory()) Min = FMRB_OnlyReadsMemory; else if (F->doesNotReadMemory()) - Min = FMRB_DoesNotReadMemory; + Min = FMRB_OnlyWritesMemory; if (F->onlyAccessesArgMemory()) Min = FunctionModRefBehavior(Min & FMRB_OnlyAccessesArgumentPointees); diff --git a/llvm/lib/Transforms/Utils/InlineFunction.cpp b/llvm/lib/Transforms/Utils/InlineFunction.cpp --- a/llvm/lib/Transforms/Utils/InlineFunction.cpp +++ b/llvm/lib/Transforms/Utils/InlineFunction.cpp @@ -1002,8 +1002,7 @@ IsFuncCall = true; if (CalleeAAR) { FunctionModRefBehavior MRB = CalleeAAR->getModRefBehavior(Call); - if (MRB == FMRB_OnlyAccessesArgumentPointees || - MRB == FMRB_OnlyReadsArgumentPointees) + if (AAResults::onlyAccessesArgPointees(MRB)) IsArgMemOnlyCall = true; } diff --git a/polly/lib/Analysis/ScopBuilder.cpp b/polly/lib/Analysis/ScopBuilder.cpp --- a/polly/lib/Analysis/ScopBuilder.cpp +++ b/polly/lib/Analysis/ScopBuilder.cpp @@ -1809,16 +1809,21 @@ 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()); diff --git a/polly/lib/Analysis/ScopDetection.cpp b/polly/lib/Analysis/ScopDetection.cpp --- a/polly/lib/Analysis/ScopDetection.cpp +++ b/polly/lib/Analysis/ScopDetection.cpp @@ -696,6 +696,8 @@ 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 @@ 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 @@ // 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; diff --git a/polly/test/ScopInfo/memset_null.ll b/polly/test/ScopInfo/memset_null.ll --- a/polly/test/ScopInfo/memset_null.ll +++ b/polly/test/ScopInfo/memset_null.ll @@ -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,