Index: include/llvm/IR/Instruction.h =================================================================== --- include/llvm/IR/Instruction.h +++ include/llvm/IR/Instruction.h @@ -424,6 +424,11 @@ /// Return true if this instruction may throw an exception. bool mayThrow() const; + /// Return true if this instruction may throw an exception or read memory. + bool mayReadFromMemoryOrThrow() const { + return mayReadFromMemory() || mayThrow(); + } + /// Return true if this instruction behaves like a memory fence: it can load /// or store to memory location without being given a memory location. bool isFenceLike() const { Index: lib/Transforms/Scalar/EarlyCSE.cpp =================================================================== --- lib/Transforms/Scalar/EarlyCSE.cpp +++ lib/Transforms/Scalar/EarlyCSE.cpp @@ -766,7 +766,7 @@ // memory. The target may override this (e.g. so that a store intrinsic // does not read from memory, and thus will be treated the same as a // regular store for commoning purposes). - if (Inst->mayReadFromMemory() && + if (Inst->mayReadFromMemoryOrThrow() && !(MemInst.isValid() && !MemInst.mayReadFromMemory())) LastStore = nullptr; Index: test/Transforms/EarlyCSE/readnone-mayunwind.ll =================================================================== --- /dev/null +++ test/Transforms/EarlyCSE/readnone-mayunwind.ll @@ -0,0 +1,15 @@ +; RUN: opt -S -early-cse < %s | FileCheck %s + +declare void @readnone_may_unwind() readnone + +define void @f(i32* %ptr) { +; CHECK-LABEL: @f( +; CHECK: store i32 100, i32* %ptr +; CHECK: call void @readnone_may_unwind() +; CHECK: store i32 200, i32* %ptr + + store i32 100, i32* %ptr + call void @readnone_may_unwind() + store i32 200, i32* %ptr + ret void +}