summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms
diff options
context:
space:
mode:
authorBrian Homerding <homerdin@gmail.com>2018-08-23 15:05:22 +0000
committerBrian Homerding <homerdin@gmail.com>2018-08-23 15:05:22 +0000
commit3ecabd709f7d7031df9368d27d0b300460d51cf1 (patch)
tree797f11dddac85063e9b39da25aa143a06d8114b6 /llvm/lib/Transforms
parent1715efd7ff6825bf8633759a43560f47b492128b (diff)
downloadbcm5719-llvm-3ecabd709f7d7031df9368d27d0b300460d51cf1.tar.gz
bcm5719-llvm-3ecabd709f7d7031df9368d27d0b300460d51cf1.zip
[FunctionAttrs] Infer WriteOnly Function Attribute
These changes expand the FunctionAttr logic in order to mark functions as WriteOnly when appropriate. This is done through an additional bool variable and extended logic. Reviewers: hfinkel, jdoerfert Differential Revision: https://reviews.llvm.org/D48387 llvm-svn: 340537
Diffstat (limited to 'llvm/lib/Transforms')
-rw-r--r--llvm/lib/Transforms/IPO/FunctionAttrs.cpp48
1 files changed, 38 insertions, 10 deletions
diff --git a/llvm/lib/Transforms/IPO/FunctionAttrs.cpp b/llvm/lib/Transforms/IPO/FunctionAttrs.cpp
index 925f4af9d48..d40ee30f453 100644
--- a/llvm/lib/Transforms/IPO/FunctionAttrs.cpp
+++ b/llvm/lib/Transforms/IPO/FunctionAttrs.cpp
@@ -66,6 +66,7 @@ using namespace llvm;
STATISTIC(NumReadNone, "Number of functions marked readnone");
STATISTIC(NumReadOnly, "Number of functions marked readonly");
+STATISTIC(NumWriteOnly, "Number of functions marked writeonly");
STATISTIC(NumNoCapture, "Number of arguments marked nocapture");
STATISTIC(NumReturned, "Number of arguments marked returned");
STATISTIC(NumReadNoneArg, "Number of arguments marked readnone");
@@ -113,12 +114,16 @@ static MemoryAccessKind checkFunctionMemoryAccess(Function &F, bool ThisBody,
if (AliasAnalysis::onlyReadsMemory(MRB))
return MAK_ReadOnly;
- // Conservatively assume it writes to memory.
+ if (AliasAnalysis::doesNotReadMemory(MRB))
+ return MAK_WriteOnly;
+
+ // Conservatively assume it reads and writes to memory.
return MAK_MayWrite;
}
// Scan the function body for instructions that may read or write memory.
bool ReadsMemory = false;
+ bool WritesMemory = false;
for (inst_iterator II = inst_begin(F), E = inst_end(F); II != E; ++II) {
Instruction *I = &*II;
@@ -141,9 +146,9 @@ static MemoryAccessKind checkFunctionMemoryAccess(Function &F, bool ThisBody,
continue;
if (!AliasAnalysis::onlyAccessesArgPointees(MRB)) {
- // The call could access any memory. If that includes writes, give up.
+ // The call could access any memory. If that includes writes, note it.
if (isModSet(MRI))
- return MAK_MayWrite;
+ WritesMemory = true;
// If it reads, note it.
if (isRefSet(MRI))
ReadsMemory = true;
@@ -168,8 +173,8 @@ static MemoryAccessKind checkFunctionMemoryAccess(Function &F, bool ThisBody,
continue;
if (isModSet(MRI))
- // Writes non-local memory. Give up.
- return MAK_MayWrite;
+ // Writes non-local memory.
+ WritesMemory = true;
if (isRefSet(MRI))
// Ok, it reads non-local memory.
ReadsMemory = true;
@@ -198,14 +203,21 @@ static MemoryAccessKind checkFunctionMemoryAccess(Function &F, bool ThisBody,
// Any remaining instructions need to be taken seriously! Check if they
// read or write memory.
- if (I->mayWriteToMemory())
- // Writes memory. Just give up.
- return MAK_MayWrite;
+ //
+ // Writes memory, remember that.
+ WritesMemory |= I->mayWriteToMemory();
// If this instruction may read memory, remember that.
ReadsMemory |= I->mayReadFromMemory();
}
+ if (WritesMemory) {
+ if (!ReadsMemory)
+ return MAK_WriteOnly;
+ else
+ return MAK_MayWrite;
+ }
+
return ReadsMemory ? MAK_ReadOnly : MAK_ReadNone;
}
@@ -220,6 +232,7 @@ static bool addReadAttrs(const SCCNodeSet &SCCNodes, AARGetterT &&AARGetter) {
// Check if any of the functions in the SCC read or write memory. If they
// write memory then they can't be marked readnone or readonly.
bool ReadsMemory = false;
+ bool WritesMemory = false;
for (Function *F : SCCNodes) {
// Call the callable parameter to look up AA results for this function.
AAResults &AAR = AARGetter(*F);
@@ -234,6 +247,9 @@ static bool addReadAttrs(const SCCNodeSet &SCCNodes, AARGetterT &&AARGetter) {
case MAK_ReadOnly:
ReadsMemory = true;
break;
+ case MAK_WriteOnly:
+ WritesMemory = true;
+ break;
case MAK_ReadNone:
// Nothing to do!
break;
@@ -243,6 +259,9 @@ static bool addReadAttrs(const SCCNodeSet &SCCNodes, AARGetterT &&AARGetter) {
// Success! Functions in this SCC do not access memory, or only read memory.
// Give them the appropriate attribute.
bool MadeChange = false;
+
+ assert(!(ReadsMemory && WritesMemory) &&
+ "Function marked read-only and write-only");
for (Function *F : SCCNodes) {
if (F->doesNotAccessMemory())
// Already perfect!
@@ -252,16 +271,25 @@ static bool addReadAttrs(const SCCNodeSet &SCCNodes, AARGetterT &&AARGetter) {
// No change.
continue;
+ if (F->doesNotReadMemory() && WritesMemory)
+ continue;
+
MadeChange = true;
// Clear out any existing attributes.
F->removeFnAttr(Attribute::ReadOnly);
F->removeFnAttr(Attribute::ReadNone);
+ F->removeFnAttr(Attribute::WriteOnly);
// Add in the new attribute.
- F->addFnAttr(ReadsMemory ? Attribute::ReadOnly : Attribute::ReadNone);
+ if (WritesMemory && !ReadsMemory)
+ F->addFnAttr(Attribute::WriteOnly);
+ else
+ F->addFnAttr(ReadsMemory ? Attribute::ReadOnly : Attribute::ReadNone);
- if (ReadsMemory)
+ if (WritesMemory && !ReadsMemory)
+ ++NumWriteOnly;
+ else if (ReadsMemory)
++NumReadOnly;
else
++NumReadNone;
OpenPOWER on IntegriCloud