aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Transforms/IPO/AddReadAttrs.cpp23
-rw-r--r--test/Transforms/AddReadAttrs/2008-12-29-Constant.ll8
2 files changed, 27 insertions, 4 deletions
diff --git a/lib/Transforms/IPO/AddReadAttrs.cpp b/lib/Transforms/IPO/AddReadAttrs.cpp
index 5460a5bde7..2835d5e9f3 100644
--- a/lib/Transforms/IPO/AddReadAttrs.cpp
+++ b/lib/Transforms/IPO/AddReadAttrs.cpp
@@ -17,6 +17,7 @@
#define DEBUG_TYPE "addreadattrs"
#include "llvm/Transforms/IPO.h"
#include "llvm/CallGraphSCCPass.h"
+#include "llvm/GlobalVariable.h"
#include "llvm/Instructions.h"
#include "llvm/Analysis/CallGraph.h"
#include "llvm/ADT/SmallPtrSet.h"
@@ -40,6 +41,8 @@ namespace {
AU.setPreservesCFG();
CallGraphSCCPass::getAnalysisUsage(AU);
}
+
+ bool PointsToLocalMemory(Value *V);
};
}
@@ -50,6 +53,20 @@ X("addreadattrs", "Mark functions readnone/readonly");
Pass *llvm::createAddReadAttrsPass() { return new AddReadAttrs(); }
+/// 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 AddReadAttrs::PointsToLocalMemory(Value *V) {
+ V = V->getUnderlyingObject();
+ // An alloca instruction defines local memory.
+ if (isa<AllocaInst>(V))
+ return true;
+ // A global constant counts as local memory for our purposes.
+ if (GlobalVariable *GV = dyn_cast<GlobalVariable>(V))
+ return GV->isConstant();
+ return false;
+}
+
bool AddReadAttrs::runOnSCC(const std::vector<CallGraphNode *> &SCC) {
SmallPtrSet<CallGraphNode *, 8> SCCNodes;
CallGraph &CG = getAnalysis<CallGraph>();
@@ -96,14 +113,12 @@ bool AddReadAttrs::runOnSCC(const std::vector<CallGraphNode *> &SCC) {
if (SCCNodes.count(CG[CS.getCalledFunction()]))
continue;
} else if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
- Value *Target = LI->getPointerOperand()->getUnderlyingObject();
// Ignore loads from local memory.
- if (isa<AllocaInst>(Target))
+ if (PointsToLocalMemory(LI->getPointerOperand()))
continue;
} else if (StoreInst *SI = dyn_cast<StoreInst>(I)) {
- Value *Target = SI->getPointerOperand()->getUnderlyingObject();
// Ignore stores to local memory.
- if (isa<AllocaInst>(Target))
+ if (PointsToLocalMemory(SI->getPointerOperand()))
continue;
}
diff --git a/test/Transforms/AddReadAttrs/2008-12-29-Constant.ll b/test/Transforms/AddReadAttrs/2008-12-29-Constant.ll
new file mode 100644
index 0000000000..fe038c1be9
--- /dev/null
+++ b/test/Transforms/AddReadAttrs/2008-12-29-Constant.ll
@@ -0,0 +1,8 @@
+; RUN: llvm-as < %s | opt -addreadattrs | llvm-dis | grep readnone
+
+@s = external constant i8 ; <i8*> [#uses=1]
+
+define i8 @f() {
+ %tmp = load i8* @s ; <i8> [#uses=1]
+ ret i8 %tmp
+}