aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorDuncan Sands <baldrick@free.fr>2010-01-06 08:45:52 +0000
committerDuncan Sands <baldrick@free.fr>2010-01-06 08:45:52 +0000
commit7c422ac216fe39fc9c402a704cf296cca9dc5b22 (patch)
treede0f0e167e65367280cc1d2239699ff52840d87f /lib
parenteaba5102e4f581b2d99794bffcbf2f6d7c3c7dc2 (diff)
downloadexternal_llvm-7c422ac216fe39fc9c402a704cf296cca9dc5b22.tar.gz
external_llvm-7c422ac216fe39fc9c402a704cf296cca9dc5b22.tar.bz2
external_llvm-7c422ac216fe39fc9c402a704cf296cca9dc5b22.zip
Partially address a README by having functionattrs consider calls to
memcpy, memset and other intrinsics that only access their arguments to be readnone if the intrinsic's arguments all point to local memory. This improves the testcase in the README to readonly, but it could in theory be made readnone, however this would involve more sophisticated analysis that looks through the memcpy. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@92829 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/Analysis/AliasAnalysis.cpp11
-rw-r--r--lib/Target/README.txt4
-rw-r--r--lib/Transforms/IPO/FunctionAttrs.cpp15
3 files changed, 24 insertions, 6 deletions
diff --git a/lib/Analysis/AliasAnalysis.cpp b/lib/Analysis/AliasAnalysis.cpp
index dee9b53587..371dcafa9f 100644
--- a/lib/Analysis/AliasAnalysis.cpp
+++ b/lib/Analysis/AliasAnalysis.cpp
@@ -116,13 +116,16 @@ AliasAnalysis::getModRefBehavior(Function *F,
return DoesNotAccessMemory;
if (F->onlyReadsMemory())
return OnlyReadsMemory;
- if (unsigned id = F->getIntrinsicID()) {
+ if (unsigned id = F->getIntrinsicID())
+ return getModRefBehavior(id);
+ }
+ return UnknownModRefBehavior;
+}
+
+AliasAnalysis::ModRefBehavior AliasAnalysis::getModRefBehavior(unsigned iid) {
#define GET_INTRINSIC_MODREF_BEHAVIOR
#include "llvm/Intrinsics.gen"
#undef GET_INTRINSIC_MODREF_BEHAVIOR
- }
- }
- return UnknownModRefBehavior;
}
AliasAnalysis::ModRefResult
diff --git a/lib/Target/README.txt b/lib/Target/README.txt
index 22dadfeb3d..38c3daa938 100644
--- a/lib/Target/README.txt
+++ b/lib/Target/README.txt
@@ -1678,8 +1678,8 @@ And functionattrs doesn't realize that the p.0 load points to function local
memory.
Also, functionattrs doesn't know about memcpy/memset. This function should be
-marked readnone, since it only twiddles local memory, but functionattrs doesn't
-handle memset/memcpy/memmove aggressively:
+marked readnone rather than readonly, since it only twiddles local memory, but
+functionattrs doesn't handle memset/memcpy/memmove aggressively:
struct X { int *p; int *q; };
int foo() {
diff --git a/lib/Transforms/IPO/FunctionAttrs.cpp b/lib/Transforms/IPO/FunctionAttrs.cpp
index a16d335ef5..0bff2b94e9 100644
--- a/lib/Transforms/IPO/FunctionAttrs.cpp
+++ b/lib/Transforms/IPO/FunctionAttrs.cpp
@@ -136,6 +136,21 @@ bool FunctionAttrs::AddReadAttrs(const std::vector<CallGraphNode *> &SCC) {
// Ignore calls to functions in the same SCC.
if (SCCNodes.count(CS.getCalledFunction()))
continue;
+ // Ignore intrinsics that only access local memory.
+ if (unsigned id = CS.getCalledFunction()->getIntrinsicID())
+ if (AliasAnalysis::getModRefBehavior(id) ==
+ AliasAnalysis::AccessesArguments) {
+ // Check that all pointer arguments point to local memory.
+ for (CallSite::arg_iterator CI = CS.arg_begin(), CE = CS.arg_end();
+ CI != CE; ++CI) {
+ Value *Arg = *CI;
+ if (isa<PointerType>(Arg->getType()) && !PointsToLocalMemory(Arg))
+ // Writes memory. Just give up.
+ return false;
+ }
+ // Only reads and writes local memory.
+ continue;
+ }
} else if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
// Ignore loads from local memory.
if (PointsToLocalMemory(LI->getPointerOperand()))