Index: lib/Analysis/MemoryDependenceAnalysis.cpp =================================================================== --- lib/Analysis/MemoryDependenceAnalysis.cpp +++ lib/Analysis/MemoryDependenceAnalysis.cpp @@ -407,10 +407,29 @@ // Values depend on loads if the pointers are must aliased. This means that // a load depends on another must aliased load from the same value. + // One exception is atomic loads: a value can depend on an atomic load that it + // does not alias with. if (LoadInst *LI = dyn_cast(Inst)) { // Atomic loads have complications involved. + // A monotonic load is OK if the query inst is itself not atomic. // FIXME: This is overly conservative. - if (!LI->isUnordered()) + if (!LI->isUnordered()) { + if (!QueryInst) + return MemDepResult::getClobber(LI); + if (LI->getOrdering() != Monotonic) + return MemDepResult::getClobber(LI); + if (auto *QueryLI = dyn_cast(QueryInst)) + if (!QueryLI->isSimple()) + return MemDepResult::getClobber(LI); + if (auto *QuerySI = dyn_cast(QueryInst)) + if (!QuerySI->isSimple()) + return MemDepResult::getClobber(LI); + } + + // FIXME: this is overly conservative. + // While volatile access cannot be eliminated, they do not have to kill + // optimisation in that way. + if (LI->isVolatile()) return MemDepResult::getClobber(LI); AliasAnalysis::Location LoadLoc = AA->getLocation(LI); @@ -469,8 +488,25 @@ if (StoreInst *SI = dyn_cast(Inst)) { // 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 (!SI->isUnordered()) { + if (!QueryInst) + return MemDepResult::getClobber(SI); + if (SI->getOrdering() != Monotonic) + return MemDepResult::getClobber(SI); + if (auto *QueryLI = dyn_cast(QueryInst)) + if (!QueryLI->isSimple()) + return MemDepResult::getClobber(SI); + if (auto *QuerySI = dyn_cast(QueryInst)) + if (!QuerySI->isSimple()) + return MemDepResult::getClobber(SI); + } + + // FIXME: this is overly conservative. + // While volatile access cannot be eliminated, they do not have to kill + // optimisation in that way. + if (SI->isVolatile()) return MemDepResult::getClobber(SI); // If alias analysis can tell that this store is guaranteed to not modify Index: test/Transforms/DeadStoreElimination/atomic.ll =================================================================== --- test/Transforms/DeadStoreElimination/atomic.ll +++ test/Transforms/DeadStoreElimination/atomic.ll @@ -105,3 +105,50 @@ ret i32 %x } +; DSE across monotonic load (allowed as long as the eliminated store isUnordered) +define i32 @test9() nounwind uwtable ssp { +; CHECK: test9 +; CHECK-NOT: store i32 0 +; CHECK: store i32 1 +entry: + store i32 0, i32* @x + %x = load atomic i32* @y monotonic, align 4 + store i32 1, i32* @x + ret i32 %x +} + +; DSE across monotonic store (allowed as long as the eliminated store isUnordered) +define void @test10() nounwind uwtable ssp { +; CHECK: test10 +; CHECK-NOT: store i32 0 +; CHECK: store i32 1 +entry: + store i32 0, i32* @x + store atomic i32 42, i32* @y monotonic, align 4 + store i32 1, i32* @x + ret void +} + +; DSE across monotonic load (forbidden since the eliminated store is atomic) +define i32 @test11() nounwind uwtable ssp { +; CHECK: test11 +; CHECK: store atomic i32 0 +; CHECK: store atomic i32 1 +entry: + store atomic i32 0, i32* @x monotonic, align 4 + %x = load atomic i32* @y monotonic, align 4 + store atomic i32 1, i32* @x monotonic, align 4 + ret i32 %x +} + +; DSE across monotonic store (forbidden since the eliminated store is atomic) +define void @test12() nounwind uwtable ssp { +; CHECK: test12 +; CHECK: store atomic i32 0 +; CHECK: store atomic i32 1 +entry: + store atomic i32 0, i32* @x monotonic, align 4 + store atomic i32 42, i32* @y monotonic, align 4 + store atomic i32 1, i32* @x monotonic, align 4 + ret void +} Index: test/Transforms/GVN/atomic.ll =================================================================== --- test/Transforms/GVN/atomic.ll +++ test/Transforms/GVN/atomic.ll @@ -78,3 +78,29 @@ %x3 = add i32 %x, %x2 ret i32 %x3 } + +; GVN across monotonic store (allowed) +define i32 @test7() nounwind uwtable ssp { +; CHECK: test7 +; CHECK: add i32 %x, %x +entry: + %x = load i32* @y + store atomic i32 %x, i32* @x monotonic, align 4 + %y = load i32* @y + %z = add i32 %x, %y + ret i32 %z +} + +; GVN of an unordered across monotonic load (not allowed) +define i32 @test8() nounwind uwtable ssp { +; CHECK: test8 +; CHECK: add i32 %x, %y +entry: + %x = load atomic i32* @y unordered, align 4 + %clobber = load atomic i32* @x monotonic, align 4 + %y = load atomic i32* @y monotonic, align 4 + %z = add i32 %x, %y + ret i32 %z +} + +