The logic in this patch is that if we find a comparison which would be unsigned except for when the loop is infinite, and we can prove that an infinite loop must be ill defined, we can still make the predicate unsigned.
The eventual goal (combined with a follow on patch) is to use the fact the loop exits to remove the zext (see tests) entirely.
A couple of points worth noting:
- We loose the ability to prove the loop unreachable by committing to the must exit interpretation. If instead, we later proved that rhs was definitely outside the range required for finiteness, we could have killed the loop entirely. (We don't currently implement this transform, but could in theory, do so.)
- simplifyAndExtend has a very limited list of users it walks. In particular, in the examples is stops at the zext and never visits the icmp. (Because we can't fold the zext to an addrec yet in SCEV.) Being willing to visit when we haven't simplified regresses multiple tests (seemingly because of less optimal results when computing trip counts).
- D109457 is geared at the same basic problem, but handles a non-fully overlapping set of cases.
Here's an Alive2 proof of a related property:
declare void @llvm.assume(i1)
define i1 @src(i32 noundef %x, i16 noundef %y) {
%and = and i32 %x, 65532 %add = add i32 %and, -1 %assume = icmp ne i32 %add, -1 call void @llvm.assume(i1 %assume) %zext = zext i16 %y to i32 %res = icmp sgt i32 %add, %zext ret i1 %res
}
define i1 @tgt(i32 noundef %x, i16 noundef %y) {
%and = and i32 %x, 65532 %add = add i32 %and, -1 %assume = icmp ne i32 %add, -1 call void @llvm.assume(i1 %assume) %zext = zext i16 %y to i32 %res = icmp ugt i32 %add, %zext ret i1 %res
}
(In this patch, the must exit property provides the assumption in the alive2 example. You can also vary the predicate type to see it holds for other signed predicates)
Looks like a great place to use pattern matching.