[llvm] r261589 - More detailed dependence test between volatile and non-volatile accesses
Krzysztof Parzyszek via llvm-commits
llvm-commits at lists.llvm.org
Mon Feb 22 15:07:43 PST 2016
Author: kparzysz
Date: Mon Feb 22 17:07:43 2016
New Revision: 261589
URL: http://llvm.org/viewvc/llvm-project?rev=261589&view=rev
Log:
More detailed dependence test between volatile and non-volatile accesses
Differential Revision: http://reviews.llvm.org/D16857
Added:
llvm/trunk/test/Transforms/GVN/volatile-nonvolatile.ll
Modified:
llvm/trunk/lib/Analysis/MemoryDependenceAnalysis.cpp
Modified: llvm/trunk/lib/Analysis/MemoryDependenceAnalysis.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/MemoryDependenceAnalysis.cpp?rev=261589&r1=261588&r2=261589&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/MemoryDependenceAnalysis.cpp (original)
+++ llvm/trunk/lib/Analysis/MemoryDependenceAnalysis.cpp Mon Feb 22 17:07:43 2016
@@ -505,6 +505,22 @@ MemDepResult MemoryDependenceAnalysis::g
// AliasAnalysis::callCapturesBefore.
OrderedBasicBlock OBB(BB);
+ // Return "true" if and only if the instruction I is either a non-simple
+ // load or a non-simple store.
+ auto isNonSimpleLoadOrStore = [] (Instruction *I) -> bool {
+ if (auto *LI = dyn_cast<LoadInst>(I))
+ return !LI->isSimple();
+ if (auto *SI = dyn_cast<StoreInst>(I))
+ return !SI->isSimple();
+ return false;
+ };
+
+ // Return "true" if I is not a load and not a store, but it does access
+ // memory.
+ auto isOtherMemAccess = [] (Instruction *I) -> bool {
+ return !isa<LoadInst>(I) && !isa<StoreInst>(I) && I->mayReadOrWriteMemory();
+ };
+
// Walk backwards through the basic block, looking for dependencies.
while (ScanIt != BB->begin()) {
Instruction *Inst = &*--ScanIt;
@@ -552,24 +568,16 @@ MemDepResult MemoryDependenceAnalysis::g
return MemDepResult::getClobber(LI);
// Otherwise, volatile doesn't imply any special ordering
}
-
+
// Atomic loads have complications involved.
// A Monotonic (or higher) load is OK if the query inst is itself not atomic.
// FIXME: This is overly conservative.
if (LI->isAtomic() && LI->getOrdering() > Unordered) {
- if (!QueryInst)
+ if (!QueryInst || isNonSimpleLoadOrStore(QueryInst) ||
+ isOtherMemAccess(QueryInst))
return MemDepResult::getClobber(LI);
if (LI->getOrdering() != Monotonic)
return MemDepResult::getClobber(LI);
- if (auto *QueryLI = dyn_cast<LoadInst>(QueryInst)) {
- if (!QueryLI->isSimple())
- return MemDepResult::getClobber(LI);
- } else if (auto *QuerySI = dyn_cast<StoreInst>(QueryInst)) {
- if (!QuerySI->isSimple())
- return MemDepResult::getClobber(LI);
- } else if (QueryInst->mayReadOrWriteMemory()) {
- return MemDepResult::getClobber(LI);
- }
}
MemoryLocation LoadLoc = MemoryLocation::get(LI);
@@ -630,20 +638,12 @@ MemDepResult MemoryDependenceAnalysis::g
// Atomic stores have complications involved.
// A Monotonic store is OK if the query inst is itself not atomic.
// FIXME: This is overly conservative.
- if (!SI->isUnordered()) {
- if (!QueryInst)
+ if (!SI->isUnordered() && SI->isAtomic()) {
+ if (!QueryInst || isNonSimpleLoadOrStore(QueryInst) ||
+ isOtherMemAccess(QueryInst))
return MemDepResult::getClobber(SI);
if (SI->getOrdering() != Monotonic)
return MemDepResult::getClobber(SI);
- if (auto *QueryLI = dyn_cast<LoadInst>(QueryInst)) {
- if (!QueryLI->isSimple())
- return MemDepResult::getClobber(SI);
- } else if (auto *QuerySI = dyn_cast<StoreInst>(QueryInst)) {
- if (!QuerySI->isSimple())
- return MemDepResult::getClobber(SI);
- } else if (QueryInst->mayReadOrWriteMemory()) {
- return MemDepResult::getClobber(SI);
- }
}
// FIXME: this is overly conservative.
@@ -651,7 +651,9 @@ MemDepResult MemoryDependenceAnalysis::g
// non-aliasing locations, as normal accesses can for example be reordered
// with volatile accesses.
if (SI->isVolatile())
- return MemDepResult::getClobber(SI);
+ if (!QueryInst || isNonSimpleLoadOrStore(QueryInst) ||
+ isOtherMemAccess(QueryInst))
+ return MemDepResult::getClobber(SI);
// If alias analysis can tell that this store is guaranteed to not modify
// the query pointer, ignore it. Use getModRefInfo to handle cases where
@@ -963,7 +965,7 @@ getNonLocalPointerDependency(Instruction
assert(Loc.Ptr->getType()->isPointerTy() &&
"Can't get pointer deps of a non-pointer!");
Result.clear();
-
+
// This routine does not expect to deal with volatile instructions.
// Doing so would require piping through the QueryInst all the way through.
// TODO: volatiles can't be elided, but they can be reordered with other
Added: llvm/trunk/test/Transforms/GVN/volatile-nonvolatile.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/volatile-nonvolatile.ll?rev=261589&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/volatile-nonvolatile.ll (added)
+++ llvm/trunk/test/Transforms/GVN/volatile-nonvolatile.ll Mon Feb 22 17:07:43 2016
@@ -0,0 +1,61 @@
+; RUN: opt -tbaa -gvn -S < %s | FileCheck %s
+
+%struct.t = type { i32* }
+
+; The loaded address and the location of the address itself are not aliased,
+; so the second reload is not necessary. Check that it can be eliminated.
+; CHECK-LABEL: test1
+; CHECK: load
+; CHECK-NOT: load
+define void @test1(%struct.t* nocapture readonly %p, i32 %v) #0 {
+entry:
+ %m = getelementptr inbounds %struct.t, %struct.t* %p, i32 0, i32 0
+ %0 = load i32*, i32** %m, align 4, !tbaa !1
+ store volatile i32 %v, i32* %0, align 4, !tbaa !6
+ %1 = load i32*, i32** %m, align 4, !tbaa !1
+ store volatile i32 %v, i32* %1, align 4, !tbaa !6
+ ret void
+}
+
+; The store via the loaded address may overwrite the address itself.
+; Make sure that both loads remain.
+; CHECK-LABEL: test2
+; CHECK: load
+; CHECK: store
+; CHECK: load
+define void @test2(%struct.t* nocapture readonly %p, i32 %v) #0 {
+entry:
+ %m = getelementptr inbounds %struct.t, %struct.t* %p, i32 0, i32 0
+ %0 = load i32*, i32** %m, align 4, !tbaa !1
+ store volatile i32 %v, i32* %0, align 4, !tbaa !1
+ %1 = load i32*, i32** %m, align 4, !tbaa !1
+ store volatile i32 %v, i32* %1, align 4, !tbaa !1
+ ret void
+}
+
+; The loads are ordered and non-monotonic. Although they are not aliased to
+; the stores, make sure both are preserved.
+; CHECK-LABEL: test3
+; CHECK: load
+; CHECK: store
+; CHECK: load
+define void @test3(%struct.t* nocapture readonly %p, i32 %v) #0 {
+entry:
+ %m = getelementptr inbounds %struct.t, %struct.t* %p, i32 0, i32 0
+ %0 = load atomic i32*, i32** %m acquire, align 4, !tbaa !1
+ store volatile i32 %v, i32* %0, align 4, !tbaa !6
+ %1 = load atomic i32*, i32** %m acquire, align 4, !tbaa !1
+ store volatile i32 %v, i32* %1, align 4, !tbaa !6
+ ret void
+}
+
+attributes #0 = { norecurse nounwind }
+
+!1 = !{!2, !3, i64 0}
+!2 = !{!"", !3, i64 0}
+!3 = !{!"any pointer", !4, i64 0}
+!4 = !{!"omnipotent char", !5, i64 0}
+!5 = !{!"Simple C/C++ TBAA"}
+!6 = !{!7, !7, i64 0}
+!7 = !{!"int", !4, i64 0}
+
More information about the llvm-commits
mailing list