Index: lib/Transforms/Scalar/EarlyCSE.cpp =================================================================== --- lib/Transforms/Scalar/EarlyCSE.cpp +++ lib/Transforms/Scalar/EarlyCSE.cpp @@ -271,8 +271,11 @@ return false; CallInst *CI = dyn_cast(Inst); - if (!CI || !CI->onlyReadsMemory()) + + // Handle readnone, readonly and writeonly. + if (!CI || !(CI->doesNotReadMemory() || CI->onlyReadsMemory())) return false; + return true; } }; @@ -996,7 +999,7 @@ !(MemInst.isValid() && !MemInst.mayReadFromMemory())) LastStore = nullptr; - // If this is a read-only call, process it. + // If this is a read-only or writeonly call, process it. if (CallValue::canHandle(Inst)) { // If we have an available version of this call, and if it is the right // generation, replace this instruction. @@ -1010,6 +1013,13 @@ LLVM_DEBUG(dbgs() << "Skipping due to debug counter\n"); continue; } + // When handling writeonly function calls we need to update lastStore + // and currentGen. + if (dyn_cast(Inst)->doesNotReadMemory() && + !dyn_cast(Inst)->doesNotAccessMemory()) { + ++CurrentGeneration; + LastStore = nullptr; + } if (!Inst->use_empty()) Inst->replaceAllUsesWith(InVal.first); removeMSSA(Inst); @@ -1018,10 +1028,18 @@ ++NumCSECall; continue; } - // Otherwise, remember that we have this instruction. AvailableCalls.insert( Inst, std::pair(Inst, CurrentGeneration)); + + // When handling writeonly function calls we need to update lastStore + // and currentGen. + if (dyn_cast(Inst)->doesNotReadMemory() && + !dyn_cast(Inst)->doesNotAccessMemory()) { + ++CurrentGeneration; + LastStore = nullptr; + } + continue; }