This patch makes SCEV recognize 'select A, B, false' and 'select A, true, B'.
This is a performance improvement that will be helpful after unsound select -> and/or transformation is removed, as discussed in D93065.
SCEV's answers for the select form should be a bit more conservative than the equivalent and A, B / or A, B.
Take this example: https://alive2.llvm.org/ce/z/NsP9ue .
To check whether it is valid for SCEV's computeExitLimit to return min(n, m) as ExactNotTaken value, I put llvm.assume at tgt.
It fails because the exit limit becomes poison if n is zero and m is poison. This is problematic if e.g. the exit value of i is replaced with min(n, m).
If either n or m is constant, we can revive the analysis again. I added relevant tests and put alive2 links there.
If and is used instead, this is okay: https://alive2.llvm.org/ce/z/K9rbJk . Hence the existing analysis is sound.
I think we can still do slightly better here: Even if the exact count is non-constant, we should still be able to take the min of the max (constant) counts in any case, right? In which case I would move this check into the EitherMayExit branch below and only adjust the BECount calculation, while keeping MaxBECount the same.
I think the condition you use here may also need more comment, as I would have expected the check to be only !isa<SCEVConstant>(EL1.ExactNotTaken) initially. Is the reasoning here that if EL0.ExactNotTaken is constant but EL1.ExactNotTaken is not, then either EL0.ExactNotTaken is zero, in which case umin will fold to zero and we won't use the second (potentially poison exit count), or it is non-zero, in which case we know that the other condition will be checked at least once and thus can't be poison.
So basically the general condition here would be if (isKnownNotPoison(EL1.ExactNotTaken) || isKnownNonZero(EL0.ExactNotTaken) || isConstantZero(EL0.ExactNotTaken), where the last case is only safe if we do fold down to zero.