https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120817
--- Comment #7 from Tamar Christina <tnfchris at gcc dot gnu.org> --- (In reply to Richard Biener from comment #6) > A C testcase would be really nice. Have not been able to reproduce it as C yet, but here's a cut-down C++ version #include <array> #include <cstdint> #include <iostream> extern int getSafeSize(int inSize, int outSize); auto copySourceIntoTarget(const std::string& source) { std::array<std::uint8_t, 5> target{}; const auto loop_end = source.begin() + getSafeSize(source.size(), target.size()); auto source_it = source.begin(); auto target_it = target.begin(); for (; source_it != loop_end; source_it++, target_it++) { *target_it = *source_it; } return target; } DSE5 is eliminating the epilogue loop by removing all side-effects from it. It marks the store Deleted dead call: # .MEM_29 = VDEF <.MEM_42> # USE = anything # CLB = anything .MASK_STORE (vectp_target.45_76, 8B, max_mask_82, vect__30.43_63); as dead, even though it's not. So far my equivalent C version works fine.. void copySourceIntoTarget2 (char * __restrict source, char * __restrict target, int src_begin, int src_size, int target_begin, int target_size) { char* loop_end = source + getSafeSize(src_size, target_size); char *source_it = source; char *target_it = target; for (; source_it != loop_end; source_it++, target_it++) { *target_it = *source_it; } } and keeps the epilogue.