This is the backend part of unsigned saturation canonicalization patch. https://reviews.llvm.org/D37510

The patch transforms canonical version of unsigned saturation, which is sub(max(a,b),a) or sub(a,min(a,b)) to special psubus insturuction on targets, which support it(8bit and 16bit uints).

umax(a,b) - b -> subus(a,b)

a - umin(a,b) -> subus(a,b)

There is also extra case handled, when right part of sub is 32 bit and can be truncated, using UMIN(this transformation was discussed in https://reviews.llvm.org/D25987).

The example of special case code:

void foo(unsigned short *p, int max, int n) { int i; unsigned m; for (i = 0; i < n; i++) { m = *--p; *p = (unsigned short)(m >= max ? m-max : 0); } }

Max in this example is truncated to max_short value, if it is greater than m, or just truncated to 16 bit, if it is not. It is vaid transformation, because if max > max_short, result of the expression will be zero.

Here is the table of types, I try to support, special case items are bold:

Size | 128 | 256 | 512 |
---|---|---|---|

i8 | v16i8 | v32i8 | v64i8 |

i16 | v8i16 | v16i16 | v32i16 |

i32 | v8i32 | v16i32 | |

i64 | v8i64 |