We'd like to make use of the new saturating add intrinsics in Rust (in part because some obvious patterns don't optimize when implemented via with.overflow intrinsics). However right now saturing adds seems to be completely opaque to the optimizer.

This patch implements some basic optimization support for saturating add intrinsics, namely:

- Constant folding sat(C1 + C2) -> C3
- sat(X + 0) -> X
- sat(X + undef) -> X
- sat(X uadd MAX) -> MAX
- sat(sat(X + C1) + C2) -> sat(X + C3) where legal
- sat(X1 + X2) -> add nuw/nsw where possible