summaryrefslogtreecommitdiffstats
path: root/lib/Transforms/IPO/FunctionAttrs.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Transforms/IPO/FunctionAttrs.cpp')
-rw-r--r--lib/Transforms/IPO/FunctionAttrs.cpp141
1 files changed, 65 insertions, 76 deletions
diff --git a/lib/Transforms/IPO/FunctionAttrs.cpp b/lib/Transforms/IPO/FunctionAttrs.cpp
index 6165ba0..95decec 100644
--- a/lib/Transforms/IPO/FunctionAttrs.cpp
+++ b/lib/Transforms/IPO/FunctionAttrs.cpp
@@ -23,10 +23,10 @@
#include "llvm/CallGraphSCCPass.h"
#include "llvm/GlobalVariable.h"
#include "llvm/IntrinsicInst.h"
+#include "llvm/LLVMContext.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/CallGraph.h"
#include "llvm/Analysis/CaptureTracking.h"
-#include "llvm/Analysis/MemoryBuiltins.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/UniqueVector.h"
@@ -41,7 +41,9 @@ STATISTIC(NumNoAlias, "Number of function returns marked noalias");
namespace {
struct FunctionAttrs : public CallGraphSCCPass {
static char ID; // Pass identification, replacement for typeid
- FunctionAttrs() : CallGraphSCCPass(ID) {}
+ FunctionAttrs() : CallGraphSCCPass(ID), AA(0) {
+ initializeFunctionAttrsPass(*PassRegistry::getPassRegistry());
+ }
// runOnSCC - Analyze the SCC, performing the transformation if possible.
bool runOnSCC(CallGraphSCC &SCC);
@@ -61,67 +63,25 @@ namespace {
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesCFG();
+ AU.addRequired<AliasAnalysis>();
CallGraphSCCPass::getAnalysisUsage(AU);
}
- bool PointsToLocalMemory(Value *V);
+ private:
+ AliasAnalysis *AA;
};
}
char FunctionAttrs::ID = 0;
-INITIALIZE_PASS(FunctionAttrs, "functionattrs",
- "Deduce function attributes", false, false);
+INITIALIZE_PASS_BEGIN(FunctionAttrs, "functionattrs",
+ "Deduce function attributes", false, false)
+INITIALIZE_AG_DEPENDENCY(CallGraph)
+INITIALIZE_PASS_END(FunctionAttrs, "functionattrs",
+ "Deduce function attributes", false, false)
Pass *llvm::createFunctionAttrsPass() { return new FunctionAttrs(); }
-/// PointsToLocalMemory - Returns whether the given pointer value points to
-/// memory that is local to the function. Global constants are considered
-/// local to all functions.
-bool FunctionAttrs::PointsToLocalMemory(Value *V) {
- SmallVector<Value*, 16> Worklist;
- unsigned MaxLookup = 8;
-
- Worklist.push_back(V);
-
- do {
- V = Worklist.pop_back_val()->getUnderlyingObject();
-
- // An alloca instruction defines local memory.
- if (isa<AllocaInst>(V))
- continue;
-
- // A global constant counts as local memory for our purposes.
- if (GlobalVariable *GV = dyn_cast<GlobalVariable>(V)) {
- if (!GV->isConstant())
- return false;
- continue;
- }
-
- // If both select values point to local memory, then so does the select.
- if (SelectInst *SI = dyn_cast<SelectInst>(V)) {
- Worklist.push_back(SI->getTrueValue());
- Worklist.push_back(SI->getFalseValue());
- continue;
- }
-
- // If all values incoming to a phi node point to local memory, then so does
- // the phi.
- if (PHINode *PN = dyn_cast<PHINode>(V)) {
- // Don't bother inspecting phi nodes with many operands.
- if (PN->getNumIncomingValues() > MaxLookup)
- return false;
- for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i)
- Worklist.push_back(PN->getIncomingValue(i));
- continue;
- }
-
- return false;
- } while (!Worklist.empty() && --MaxLookup);
-
- return Worklist.empty();
-}
-
/// AddReadAttrs - Deduce readonly/readnone attributes for the SCC.
bool FunctionAttrs::AddReadAttrs(const CallGraphSCC &SCC) {
SmallPtrSet<Function*, 8> SCCNodes;
@@ -141,14 +101,15 @@ bool FunctionAttrs::AddReadAttrs(const CallGraphSCC &SCC) {
// External node - may write memory. Just give up.
return false;
- if (F->doesNotAccessMemory())
+ AliasAnalysis::ModRefBehavior MRB = AA->getModRefBehavior(F);
+ if (MRB == AliasAnalysis::DoesNotAccessMemory)
// Already perfect!
continue;
// Definitions with weak linkage may be overridden at linktime with
// something that writes memory, so treat them like declarations.
if (F->isDeclaration() || F->mayBeOverridden()) {
- if (!F->onlyReadsMemory())
+ if (!AliasAnalysis::onlyReadsMemory(MRB))
// May write memory. Just give up.
return false;
@@ -163,32 +124,62 @@ bool FunctionAttrs::AddReadAttrs(const CallGraphSCC &SCC) {
// Some instructions can be ignored even if they read or write memory.
// Detect these now, skipping to the next instruction if one is found.
CallSite CS(cast<Value>(I));
- if (CS && CS.getCalledFunction()) {
+ if (CS) {
// Ignore calls to functions in the same SCC.
- if (SCCNodes.count(CS.getCalledFunction()))
+ if (CS.getCalledFunction() && SCCNodes.count(CS.getCalledFunction()))
continue;
- // Ignore intrinsics that only access local memory.
- if (unsigned id = CS.getCalledFunction()->getIntrinsicID())
- if (AliasAnalysis::getIntrinsicModRefBehavior(id) ==
- AliasAnalysis::AccessesArguments) {
- // Check that all pointer arguments point to local memory.
+ AliasAnalysis::ModRefBehavior MRB = AA->getModRefBehavior(CS);
+ // If the call doesn't access arbitrary memory, we may be able to
+ // figure out something.
+ if (AliasAnalysis::onlyAccessesArgPointees(MRB)) {
+ // If the call does access argument pointees, check each argument.
+ if (AliasAnalysis::doesAccessArgPointees(MRB))
+ // Check whether all pointer arguments point to local memory, and
+ // ignore calls that only access local memory.
for (CallSite::arg_iterator CI = CS.arg_begin(), CE = CS.arg_end();
CI != CE; ++CI) {
Value *Arg = *CI;
- if (Arg->getType()->isPointerTy() && !PointsToLocalMemory(Arg))
- // Writes memory. Just give up.
- return false;
+ if (Arg->getType()->isPointerTy()) {
+ AliasAnalysis::Location Loc(Arg,
+ AliasAnalysis::UnknownSize,
+ I->getMetadata(LLVMContext::MD_tbaa));
+ if (!AA->pointsToConstantMemory(Loc, /*OrLocal=*/true)) {
+ if (MRB & AliasAnalysis::Mod)
+ // Writes non-local memory. Give up.
+ return false;
+ if (MRB & AliasAnalysis::Ref)
+ // Ok, it reads non-local memory.
+ ReadsMemory = true;
+ }
+ }
}
- // Only reads and writes local memory.
- continue;
- }
- } else if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
- // Ignore loads from local memory.
- if (PointsToLocalMemory(LI->getPointerOperand()))
continue;
+ }
+ // The call could access any memory. If that includes writes, give up.
+ if (MRB & AliasAnalysis::Mod)
+ return false;
+ // If it reads, note it.
+ if (MRB & AliasAnalysis::Ref)
+ ReadsMemory = true;
+ continue;
+ } else if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
+ // Ignore non-volatile loads from local memory.
+ if (!LI->isVolatile()) {
+ AliasAnalysis::Location Loc = AA->getLocation(LI);
+ if (AA->pointsToConstantMemory(Loc, /*OrLocal=*/true))
+ continue;
+ }
} else if (StoreInst *SI = dyn_cast<StoreInst>(I)) {
- // Ignore stores to local memory.
- if (PointsToLocalMemory(SI->getPointerOperand()))
+ // Ignore non-volatile stores to local memory.
+ if (!SI->isVolatile()) {
+ AliasAnalysis::Location Loc = AA->getLocation(SI);
+ if (AA->pointsToConstantMemory(Loc, /*OrLocal=*/true))
+ continue;
+ }
+ } else if (VAArgInst *VI = dyn_cast<VAArgInst>(I)) {
+ // Ignore vaargs on local memory.
+ AliasAnalysis::Location Loc = AA->getLocation(VI);
+ if (AA->pointsToConstantMemory(Loc, /*OrLocal=*/true))
continue;
}
@@ -198,10 +189,6 @@ bool FunctionAttrs::AddReadAttrs(const CallGraphSCC &SCC) {
// Writes memory. Just give up.
return false;
- if (isMalloc(I))
- // malloc claims not to write memory! PR3754.
- return false;
-
// If this instruction may read memory, remember that.
ReadsMemory |= I->mayReadFromMemory();
}
@@ -384,6 +371,8 @@ bool FunctionAttrs::AddNoAliasAttrs(const CallGraphSCC &SCC) {
}
bool FunctionAttrs::runOnSCC(CallGraphSCC &SCC) {
+ AA = &getAnalysis<AliasAnalysis>();
+
bool Changed = AddReadAttrs(SCC);
Changed |= AddNoCaptureAttrs(SCC);
Changed |= AddNoAliasAttrs(SCC);
OpenPOWER on IntegriCloud