diff --git a/llvm/lib/Transforms/Scalar/EarlyCSE.cpp b/llvm/lib/Transforms/Scalar/EarlyCSE.cpp index a899640d0adc..06c1b9111187 100644 --- a/llvm/lib/Transforms/Scalar/EarlyCSE.cpp +++ b/llvm/lib/Transforms/Scalar/EarlyCSE.cpp @@ -380,8 +380,19 @@ bool EarlyCSE::processNode(DomTreeNode *Node) { // Okay, this isn't something we can CSE at all. Check to see if it is // something that could modify memory. If so, our available memory values // cannot be used so bump the generation count. - if (Inst->mayWriteToMemory()) + if (Inst->mayWriteToMemory()) { ++CurrentGeneration; + + // Okay, we just invalidated anything we knew about loaded values. Try to + // salvage *something* by remembering that the stored value is a live + // version of the pointer. It is safe to forward from volatile stores to + // non-volatile loads, so we don't have to check for volatility of the + // store. + if (StoreInst *SI = dyn_cast(Inst)) { + AvailableLoads->insert(SI->getPointerOperand(), + std::pair(SI->getValueOperand(), CurrentGeneration)); + } + } } unsigned LiveOutGeneration = CurrentGeneration; diff --git a/llvm/test/Transforms/EarlyCSE/basic.ll b/llvm/test/Transforms/EarlyCSE/basic.ll index 6d772599b361..5599a1c0b7b1 100644 --- a/llvm/test/Transforms/EarlyCSE/basic.ll +++ b/llvm/test/Transforms/EarlyCSE/basic.ll @@ -87,3 +87,12 @@ define i32 @test5(i32 *%P) { ret i32 %Diff ; CHECK: ret i32 0 } + +;; Trivial Store->load forwarding +; CHECK: @test6 +define i32 @test6(i32 *%P) { + store i32 42, i32* %P + %V1 = load i32* %P + ret i32 %V1 + ; CHECK: ret i32 42 +}