There were proposals for optimizing this kind of stuff for C++ in particular for error handling, like:
https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p07...
> Throwing such values behaves as-if the function returned union{R;E;}+bool where on success the function returns the normal return value R and on error the function returns the error value type E, both in the same return channel including using the same registers. The discriminant can use an unused CPU flag or a register