There are situations where we may not be able to determine that a value is a particular constant, but we may be able to determine that it must be one of a set of constants. A good example is when trawling through selects or PHIs:
%1 = select i1 %a, i32 42, i32 64 %2 = icmp sgt i32 %1, i32 78
We know %1 must either be 42 or 64. We should be able to use that knowledge to fold %2 to false. In fact, we can do this already for the above simple case due to peepholes in InstCombineCompares. However the following case does not get caught:
%1 = select i1 %a, i32 42, i32 64 %2 = add i32 %1, 1 %3 = icmp sgt i32 %2, i32 78
Because the peepholes in InstCombine can't see through the add.
This patch introduces a general GetUnderlyingValues() function, sort of a corrollary to GetUnderlyingObjects(). It will take a value and attempt to determine a set of other values it could possibly be. In this case GetUnderlyingValues(%2) would return {43, 64}.
We then use this in InstCombineCompares - if all the results returned by GetUnderlyingValues are constant, and the constant folder determines the result of the compare is the same in all cases, constant fold the compare.
We do this in InstCombine rather than InstSimplify primarily because GetUnderlyingValues (like GetUnderlyingObjects) can call into InstSimplify itself and therefore cause unchecked recursion. Calling this only from InstCombine is very nearly as powerful and uses less compile time too (no measured compile time increase).
auto *