For the following code LLVM inlines `std::vector::at` and optimizes away the bounds check ```cpp std::vector<int> without_try_catch() { std::vector<int> v(10'000); for(int i = 0; i < 10'000; ++i) { v.at(i) = i; } return v; } ``` However, for the following, the presence of a `try`/`catch` precludes LLVM from proving away the bounds check and the subsequent throwing path. ```cpp std::vector<int> with_try_catch() { std::vector<int> v(10'000); for(int i = 0; i < 10'000; ++i) { try { v.at(i) = i; } catch(...) {} } return v; } ``` As a result this dead-code `try`/`catch` results in far worse codegen. CE link: https://godbolt.org/z/e3sT1z4bd