From 014f5bcf7a8bd5fbc1b2c8bc47472f9ebab1968a Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Tue, 15 Mar 2022 19:35:54 +0000 Subject: [PATCH] [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 --- .../llvm/Transforms/IPO/FunctionAttrs.h | 13 ++--- llvm/lib/Transforms/IPO/FunctionAttrs.cpp | 52 +++++++------------ .../Transforms/IPO/ThinLTOBitcodeWriter.cpp | 3 +- .../lib/Transforms/IPO/WholeProgramDevirt.cpp | 2 +- 4 files changed, 25 insertions(+), 45 deletions(-) diff --git a/llvm/include/llvm/Transforms/IPO/FunctionAttrs.h b/llvm/include/llvm/Transforms/IPO/FunctionAttrs.h index 0b6734a3929d..4b2165ead1c5 100644 --- a/llvm/include/llvm/Transforms/IPO/FunctionAttrs.h +++ b/llvm/include/llvm/Transforms/IPO/FunctionAttrs.h @@ -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 diff --git a/llvm/lib/Transforms/IPO/FunctionAttrs.cpp b/llvm/lib/Transforms/IPO/FunctionAttrs.cpp index 1b9276d42dcd..06aab4d7941c 100644 --- a/llvm/lib/Transforms/IPO/FunctionAttrs.cpp +++ b/llvm/lib/Transforms/IPO/FunctionAttrs.cpp @@ -121,24 +121,16 @@ using SCCNodeSet = SmallSetVector; /// 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 diff --git a/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp b/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp index 52708ff2f226..6952b73f74d3 100644 --- a/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp +++ b/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp @@ -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); }); } diff --git a/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp b/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp index d4b669e72460..7ee6bfd25965 100644 --- a/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp +++ b/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp @@ -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;