forked from OSchip/llvm-project
[FunctionAttrs] Replace MemoryAccessKind with FMRB.
Update FunctionAttrs to use FunctionModRefBehavior instead MemoryAccessKind. This allows for adding support for inferring argmemonly and others, see D121415. Reviewed By: nikic Differential Revision: https://reviews.llvm.org/D121460
This commit is contained in:
parent
8bd00557e3
commit
014f5bcf7a
|
@ -15,6 +15,7 @@
|
|||
#ifndef LLVM_TRANSFORMS_IPO_FUNCTIONATTRS_H
|
||||
#define LLVM_TRANSFORMS_IPO_FUNCTIONATTRS_H
|
||||
|
||||
#include "llvm/Analysis/AliasAnalysis.h"
|
||||
#include "llvm/Analysis/CGSCCPassManager.h"
|
||||
#include "llvm/Analysis/LazyCallGraph.h"
|
||||
#include "llvm/IR/ModuleSummaryIndex.h"
|
||||
|
@ -27,17 +28,9 @@ class Function;
|
|||
class Module;
|
||||
class Pass;
|
||||
|
||||
/// The three kinds of memory access relevant to 'readonly' and
|
||||
/// 'readnone' attributes.
|
||||
enum MemoryAccessKind {
|
||||
MAK_ReadNone = 0,
|
||||
MAK_ReadOnly = 1,
|
||||
MAK_MayWrite = 2,
|
||||
MAK_WriteOnly = 3
|
||||
};
|
||||
|
||||
/// Returns the memory access properties of this copy of the function.
|
||||
MemoryAccessKind computeFunctionBodyMemoryAccess(Function &F, AAResults &AAR);
|
||||
FunctionModRefBehavior computeFunctionBodyMemoryAccess(Function &F,
|
||||
AAResults &AAR);
|
||||
|
||||
/// Propagate function attributes for function summaries along the index's
|
||||
/// callgraph during thinlink
|
||||
|
|
|
@ -121,24 +121,16 @@ using SCCNodeSet = SmallSetVector<Function *, 8>;
|
|||
/// result will be based only on AA results for the function declaration; it
|
||||
/// will be assumed that some other (perhaps less optimized) version of the
|
||||
/// function may be selected at link time.
|
||||
static MemoryAccessKind checkFunctionMemoryAccess(Function &F, bool ThisBody,
|
||||
AAResults &AAR,
|
||||
const SCCNodeSet &SCCNodes) {
|
||||
static FunctionModRefBehavior
|
||||
checkFunctionMemoryAccess(Function &F, bool ThisBody, AAResults &AAR,
|
||||
const SCCNodeSet &SCCNodes) {
|
||||
FunctionModRefBehavior MRB = AAR.getModRefBehavior(&F);
|
||||
if (MRB == FMRB_DoesNotAccessMemory)
|
||||
// Already perfect!
|
||||
return MAK_ReadNone;
|
||||
return MRB;
|
||||
|
||||
if (!ThisBody) {
|
||||
if (AliasAnalysis::onlyReadsMemory(MRB))
|
||||
return MAK_ReadOnly;
|
||||
|
||||
if (AliasAnalysis::onlyWritesMemory(MRB))
|
||||
return MAK_WriteOnly;
|
||||
|
||||
// Conservatively assume it reads and writes to memory.
|
||||
return MAK_MayWrite;
|
||||
}
|
||||
if (!ThisBody)
|
||||
return MRB;
|
||||
|
||||
// Scan the function body for instructions that may read or write memory.
|
||||
bool ReadsMemory = false;
|
||||
|
@ -232,18 +224,18 @@ static MemoryAccessKind checkFunctionMemoryAccess(Function &F, bool ThisBody,
|
|||
ReadsMemory |= I.mayReadFromMemory();
|
||||
}
|
||||
|
||||
if (WritesMemory) {
|
||||
if (WritesMemory) {
|
||||
if (!ReadsMemory)
|
||||
return MAK_WriteOnly;
|
||||
return FMRB_OnlyWritesMemory;
|
||||
else
|
||||
return MAK_MayWrite;
|
||||
return FMRB_UnknownModRefBehavior;
|
||||
}
|
||||
|
||||
return ReadsMemory ? MAK_ReadOnly : MAK_ReadNone;
|
||||
return ReadsMemory ? FMRB_OnlyReadsMemory : FMRB_DoesNotAccessMemory;
|
||||
}
|
||||
|
||||
MemoryAccessKind llvm::computeFunctionBodyMemoryAccess(Function &F,
|
||||
AAResults &AAR) {
|
||||
FunctionModRefBehavior llvm::computeFunctionBodyMemoryAccess(Function &F,
|
||||
AAResults &AAR) {
|
||||
return checkFunctionMemoryAccess(F, /*ThisBody=*/true, AAR, {});
|
||||
}
|
||||
|
||||
|
@ -262,20 +254,14 @@ static void addMemoryAttrs(const SCCNodeSet &SCCNodes, AARGetterT &&AARGetter,
|
|||
// Non-exact function definitions may not be selected at link time, and an
|
||||
// alternative version that writes to memory may be selected. See the
|
||||
// comment on GlobalValue::isDefinitionExact for more details.
|
||||
switch (checkFunctionMemoryAccess(*F, F->hasExactDefinition(),
|
||||
AAR, SCCNodes)) {
|
||||
case MAK_MayWrite:
|
||||
FunctionModRefBehavior FMRB =
|
||||
checkFunctionMemoryAccess(*F, F->hasExactDefinition(), AAR, SCCNodes);
|
||||
if (isModAndRefSet(createModRefInfo(FMRB)))
|
||||
return;
|
||||
case MAK_ReadOnly:
|
||||
ReadsMemory = true;
|
||||
break;
|
||||
case MAK_WriteOnly:
|
||||
WritesMemory = true;
|
||||
break;
|
||||
case MAK_ReadNone:
|
||||
// Nothing to do!
|
||||
break;
|
||||
}
|
||||
if (FMRB == FMRB_DoesNotAccessMemory)
|
||||
continue;
|
||||
ReadsMemory |= AliasAnalysis::onlyReadsMemory(FMRB);
|
||||
WritesMemory |= AliasAnalysis::onlyWritesMemory(FMRB);
|
||||
}
|
||||
|
||||
// If the SCC contains both functions that read and functions that write, then
|
||||
|
|
|
@ -311,7 +311,8 @@ void splitAndWriteThinLTOBitcode(
|
|||
return;
|
||||
}
|
||||
if (!F->isDeclaration() &&
|
||||
computeFunctionBodyMemoryAccess(*F, AARGetter(*F)) == MAK_ReadNone)
|
||||
computeFunctionBodyMemoryAccess(*F, AARGetter(*F)) ==
|
||||
FMRB_DoesNotAccessMemory)
|
||||
EligibleVirtualFns.insert(F);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1740,7 +1740,7 @@ bool DevirtModule::tryVirtualConstProp(
|
|||
for (VirtualCallTarget &Target : TargetsForSlot) {
|
||||
if (Target.Fn->isDeclaration() ||
|
||||
computeFunctionBodyMemoryAccess(*Target.Fn, AARGetter(*Target.Fn)) !=
|
||||
MAK_ReadNone ||
|
||||
FMRB_DoesNotAccessMemory ||
|
||||
Target.Fn->arg_empty() || !Target.Fn->arg_begin()->use_empty() ||
|
||||
Target.Fn->getReturnType() != RetType)
|
||||
return false;
|
||||
|
|
Loading…
Reference in New Issue