The current infrastructure for exhaustive ConstantRange testing is somewhat confusing in what exactly it tests (D88283) and currently cannot even be used for operations that produce smallest-size results, rather than signed/unsigned approximations.
This patch tries to make the testing more principled by collecting the exact set of results of an operation into a bit set and then comparing it against the range approximation by:
- Checking conservative correctness: All elements in the set must be in the range.
- Checking optimality under a given preference function: None of the (slack-free) ranges that can be constructed from the set are preferred over the computed range.
Implemented preference functions are:
- PreferSmallest: Smallest range regardless of signed/unsigned wrapping behavior. Probably what we would call "optimal" without further qualification.
- PreferSmallestUnsigned/Signed: Smallest range that has no unsigned/signed wrapping. We use this if our calculation is precise only up to signed/unsigned envelope.
- PreferSmallestNonFullUnsigned/Signed: Smallest range that has no unsigned/signed wrapping -- but preferring a smaller wrapping range over a (non-wrapping) full range. We use this if we have a fully precise calculation but apply a sign preference to the result (union/intersection). Even with a sign preference, returning a wrapping range is still "strictly better" than returning a full one.
clang-format: please reformat the code