[llvm-commits] [llvm] r60794 - in /llvm/trunk: include/llvm/Analysis/MemoryDependenceAnalysis.h lib/Analysis/BasicAliasAnalysis.cpp lib/Analysis/MemoryDependenceAnalysis.cpp test/Transforms/GVN/readonly-calls.ll
Chris Lattner
sabre at nondot.org
Tue Dec 9 13:19:52 PST 2008
Author: lattner
Date: Tue Dec 9 15:19:42 2008
New Revision: 60794
URL: http://llvm.org/viewvc/llvm-project?rev=60794&view=rev
Log:
Teach BasicAA::getModRefInfo(CallSite, CallSite) some
tricks based on readnone/readonly functions.
Teach memdep to look past readonly calls when analyzing
deps for a readonly call. This allows elimination of a
few more calls from 403.gcc:
before:
63 gvn - Number of instructions PRE'd
153986 gvn - Number of instructions deleted
50069 gvn - Number of loads deleted
after:
63 gvn - Number of instructions PRE'd
153991 gvn - Number of instructions deleted
50069 gvn - Number of loads deleted
5 calls isn't much, but this adds plumbing for the next change.
Added:
llvm/trunk/test/Transforms/GVN/readonly-calls.ll
Modified:
llvm/trunk/include/llvm/Analysis/MemoryDependenceAnalysis.h
llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp
llvm/trunk/lib/Analysis/MemoryDependenceAnalysis.cpp
Modified: llvm/trunk/include/llvm/Analysis/MemoryDependenceAnalysis.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/MemoryDependenceAnalysis.h?rev=60794&r1=60793&r2=60794&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Analysis/MemoryDependenceAnalysis.h (original)
+++ llvm/trunk/include/llvm/Analysis/MemoryDependenceAnalysis.h Tue Dec 9 15:19:42 2008
@@ -248,7 +248,7 @@
bool isLoad,
BasicBlock::iterator ScanIt,
BasicBlock *BB);
- MemDepResult getCallSiteDependencyFrom(CallSite C,
+ MemDepResult getCallSiteDependencyFrom(CallSite C, bool isReadOnlyCall,
BasicBlock::iterator ScanIt,
BasicBlock *BB);
void getNonLocalPointerDepFromBB(Value *Pointer, uint64_t Size,
Modified: llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp?rev=60794&r1=60793&r2=60794&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp (original)
+++ llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp Tue Dec 9 15:19:42 2008
@@ -264,10 +264,8 @@
const Value *V2, unsigned V2Size);
ModRefResult getModRefInfo(CallSite CS, Value *P, unsigned Size);
- ModRefResult getModRefInfo(CallSite CS1, CallSite CS2) {
- return NoAA::getModRefInfo(CS1,CS2);
- }
-
+ ModRefResult getModRefInfo(CallSite CS1, CallSite CS2);
+
/// hasNoModRefInfoForCalls - We can provide mod/ref information against
/// non-escaping allocations.
virtual bool hasNoModRefInfoForCalls() const { return false; }
@@ -352,6 +350,24 @@
}
+AliasAnalysis::ModRefResult
+BasicAliasAnalysis::getModRefInfo(CallSite CS1, CallSite CS2) {
+ // If CS1 or CS2 are readnone, they don't interact.
+ ModRefBehavior CS1B = AliasAnalysis::getModRefBehavior(CS1);
+ if (CS1B == DoesNotAccessMemory) return NoModRef;
+
+ ModRefBehavior CS2B = AliasAnalysis::getModRefBehavior(CS2);
+ if (CS2B == DoesNotAccessMemory) return NoModRef;
+
+ // If they both only read from memory, just return ref.
+ if (CS1B == OnlyReadsMemory && CS2B == OnlyReadsMemory)
+ return Ref;
+
+ // Otherwise, fall back to NoAA (mod+ref).
+ return NoAA::getModRefInfo(CS1, CS2);
+}
+
+
// alias - Provide a bunch of ad-hoc rules to disambiguate in common cases, such
// as array references. Note that this function is heavily tail recursive.
// Hopefully we have a smart C++ compiler. :)
Modified: llvm/trunk/lib/Analysis/MemoryDependenceAnalysis.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/MemoryDependenceAnalysis.cpp?rev=60794&r1=60793&r2=60794&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/MemoryDependenceAnalysis.cpp (original)
+++ llvm/trunk/lib/Analysis/MemoryDependenceAnalysis.cpp Tue Dec 9 15:19:42 2008
@@ -99,8 +99,8 @@
/// getCallSiteDependencyFrom - Private helper for finding the local
/// dependencies of a call site.
MemDepResult MemoryDependenceAnalysis::
-getCallSiteDependencyFrom(CallSite CS, BasicBlock::iterator ScanIt,
- BasicBlock *BB) {
+getCallSiteDependencyFrom(CallSite CS, bool isReadOnlyCall,
+ BasicBlock::iterator ScanIt, BasicBlock *BB) {
// Walk backwards through the block, looking for dependencies
while (ScanIt != BB->begin()) {
Instruction *Inst = --ScanIt;
@@ -122,20 +122,31 @@
} else if (isa<CallInst>(Inst) || isa<InvokeInst>(Inst)) {
CallSite InstCS = CallSite::get(Inst);
// If these two calls do not interfere, look past it.
- if (AA->getModRefInfo(CS, InstCS) == AliasAnalysis::NoModRef)
+ switch (AA->getModRefInfo(CS, InstCS)) {
+ case AliasAnalysis::NoModRef:
+ // If the two calls don't interact (e.g. InstCS is readnone) keep
+ // scanning.
continue;
-
- // FIXME: If this is a ref/ref result, we should ignore it!
- // X = strlen(P);
- // Y = strlen(Q);
- // Z = strlen(P); // Z = X
-
- // If they interfere, we generally return clobber. However, if they are
- // calls to the same read-only functions we return Def.
- if (!AA->onlyReadsMemory(CS) || CS.getCalledFunction() == 0 ||
- CS.getCalledFunction() != InstCS.getCalledFunction())
+ case AliasAnalysis::Ref:
+ // If the two calls read the same memory locations and CS is a readonly
+ // function, then we have two cases: 1) the calls may not interfere with
+ // each other at all. 2) the calls may produce the same value. In case
+ // #1 we want to ignore the values, in case #2, we want to return Inst
+ // as a Def dependence. This allows us to CSE in cases like:
+ // X = strlen(P);
+ // memchr(...);
+ // Y = strlen(P); // Y = X
+ if (isReadOnlyCall) {
+ if (CS.getCalledFunction() != 0 &&
+ CS.getCalledFunction() == InstCS.getCalledFunction())
+ return MemDepResult::getDef(Inst);
+ // Ignore unrelated read/read call dependences.
+ continue;
+ }
+ // FALL THROUGH
+ default:
return MemDepResult::getClobber(Inst);
- return MemDepResult::getDef(Inst);
+ }
} else {
// Non-memory instruction.
continue;
@@ -212,7 +223,6 @@
}
// See if this instruction (e.g. a call or vaarg) mod/ref's the pointer.
- // FIXME: If this is a load, we should ignore readonly calls!
switch (AA->getModRefInfo(Inst, MemPtr, MemSize)) {
case AliasAnalysis::NoModRef:
// If the call has no effect on the queried pointer, just ignore it.
@@ -289,7 +299,9 @@
MemSize = TD->getTypeStoreSize(LI->getType());
}
} else if (isa<CallInst>(QueryInst) || isa<InvokeInst>(QueryInst)) {
- LocalCache = getCallSiteDependencyFrom(CallSite::get(QueryInst), ScanPos,
+ CallSite QueryCS = CallSite::get(QueryInst);
+ bool isReadOnly = AA->onlyReadsMemory(QueryCS);
+ LocalCache = getCallSiteDependencyFrom(QueryCS, isReadOnly, ScanPos,
QueryParent);
} else if (FreeInst *FI = dyn_cast<FreeInst>(QueryInst)) {
MemPtr = FI->getPointerOperand();
@@ -367,6 +379,9 @@
NumUncacheNonLocal++;
}
+ // isReadonlyCall - If this is a read-only call, we can be more aggressive.
+ bool isReadonlyCall = AA->onlyReadsMemory(QueryCS);
+
// Visited checked first, vector in sorted order.
SmallPtrSet<BasicBlock*, 64> Visited;
@@ -417,7 +432,7 @@
MemDepResult Dep;
if (ScanPos != DirtyBB->begin()) {
- Dep = getCallSiteDependencyFrom(QueryCS, ScanPos, DirtyBB);
+ Dep = getCallSiteDependencyFrom(QueryCS, isReadonlyCall,ScanPos, DirtyBB);
} else if (DirtyBB != &DirtyBB->getParent()->getEntryBlock()) {
// No dependence found. If this is the entry block of the function, it is
// a clobber, otherwise it is non-local.
Added: llvm/trunk/test/Transforms/GVN/readonly-calls.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/readonly-calls.ll?rev=60794&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/readonly-calls.ll (added)
+++ llvm/trunk/test/Transforms/GVN/readonly-calls.ll Tue Dec 9 15:19:42 2008
@@ -0,0 +1,29 @@
+; RUN: llvm-as < %s | opt -basicaa -gvn | llvm-dis | grep {call.*strlen} | count 1
+; Should delete the second call to strlen even though the intervening strchr call exists.
+
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
+target triple = "i386-apple-darwin7"
+
+define i8* @test(i8* %P, i8* %Q, i32 %x, i32 %y) nounwind readonly {
+entry:
+ %0 = tail call i32 @strlen(i8* %P) nounwind readonly ; <i32> [#uses=2]
+ %1 = icmp eq i32 %0, 0 ; <i1> [#uses=1]
+ br i1 %1, label %bb, label %bb1
+
+bb: ; preds = %entry
+ %2 = sdiv i32 %x, %y ; <i32> [#uses=1]
+ br label %bb1
+
+bb1: ; preds = %bb, %entry
+ %x_addr.0 = phi i32 [ %2, %bb ], [ %x, %entry ] ; <i32> [#uses=1]
+ %3 = tail call i8* @strchr(i8* %Q, i32 97) nounwind readonly ; <i8*> [#uses=1]
+ %4 = tail call i32 @strlen(i8* %P) nounwind readonly ; <i32> [#uses=1]
+ %5 = add i32 %x_addr.0, %0 ; <i32> [#uses=1]
+ %.sum = sub i32 %5, %4 ; <i32> [#uses=1]
+ %6 = getelementptr i8* %3, i32 %.sum ; <i8*> [#uses=1]
+ ret i8* %6
+}
+
+declare i32 @strlen(i8*) nounwind readonly
+
+declare i8* @strchr(i8*, i32) nounwind readonly
More information about the llvm-commits
mailing list