[llvm] [InstCombine] Fold extended add/sub of the same type (PR #185259)

via llvm-commits llvm-commits at lists.llvm.org
Mon Mar 9 10:55:23 PDT 2026


sweiglbosker wrote:




> `zext` and `trunc` don't seem to be involved in the core of this optimization. I think this can be considered more general:
> 
>     * `umin(a + b, lower bitwidth MAX)` --> `uadd.sat(a, b)`
> 
>     * `smax(a - b, 0)` --> `usub.sat(a, b)`
> 
> 
> I'm currently conducting this test locally, along with the other scenarios mentioned by @sweiglbosker . Once my locally written test and existing tests pass, I will push and update the PR description.

I'm not sure exactly what fold you are talking about, please write proofs.

If you mean `umin(a+b, <N>_MAX) -> uadd.sat.i<N>(a, b)`, you are incorrect: https://alive2.llvm.org/ce/z/bs36GM

but if the result of a + b is known to not overflow (this is what the zext contributes to the pattern), they are equivalent

the trunc is what makes it directly fold to the uadd.sat (because 8 bit saturating add produces an 8 bit result). If there is no trunc, you could fold to zext(uadd.sat(a,b)) i guess.

And yes generalizations are possible but the many motivation was to handle this case:

```c
  uint8_t saturating_add_scalar(uint8_t a, uint8_t b) {
      uint16_t sum = a + b;
      return (sum > 255) ? 255 : (uint8_t)sum;
  }
```

Which I also now notice is the first result that comes up when you google "c function to do saturating 8 bit add"






https://github.com/llvm/llvm-project/pull/185259


More information about the llvm-commits mailing list