Originally reported in Rust: https://github.com/rust-lang/rust/issues/58602
llvm define i64 @test_icmp_sub_elide(i64 %offset) { start: %0 = icmp ult i64 %offset, 8 br i1 %0, label %body, label %end body: %1 = sub i64 10, %offset %2 = icmp ult i64 %1, 3 br i1 %2, label %dead_branch, label %end dead_branch: ret i64 %1 end: ret i64 0 }
In the above snippet, we already check that offset < 8 in the first block but can't figure out that 10-offset < 3 is redundant. This changes fixes it in 2 parts:
Teach CorrelatedValuePropagation to also handle sub instructions in addition to add. Relatively simple since makeGuaranteedNoWrapRegion already understood sub instructions. Only subtle change is which range is passed as "Other" to that function, since sub isn't commutative.Moved to separate revision: D60036- Teach InstCombine the transformation (icmp P (sub nuw|nsw C2, Y), C) -> (icmp swap(P) Y, C2-C)
For the instcombine tests it's enough to just check the sub+icmp folding to true/false, such as:
Instead we'd want to test more variations here, in particular: Both nuw and nsw should be covered. Cases where the subtraction overflows should be covered. And I believe this transform also needs to be guarded based on the signedness of the predicate -- i.e. you can't do it if you have sub nsw and ult, so we'd want to test such combinations as well.
Test checks can be generated using utils/update_test_checks.py.