constraint elimination is a super impressive pass but there are some holes in what it’s able to do, often apparently related to our canonicalization choices. for example at present it cannot prove that this assert is unreachable:
void f(long a, long b, long c) {
if (a>b)
if (b>c)
assert(a>c);
}
the IR at the relevant point is:
define void @f(i64 noundef %a, i64 noundef %b, i64 noundef %c) {
entry:
%cmp = icmp sle i64 %a, %b
%cmp1 = icmp sle i64 %b, %c
%or.cond.not11 = or i1 %cmp, %cmp1
%cmp3 = icmp sgt i64 %a, %c
%or.cond10 = or i1 %cmp3, %or.cond.not11
br i1 %or.cond10, label %if.end6, label %if.else
if.else: ; preds = %entry
tail call void @__assert_fail(ptr noundef nonnull @.str, ptr noundef nonnull @.str.1, i32 noundef 6, ptr noundef nonnull @__PRETTY_FUNCTION__.f) #2
unreachable
if.end6: ; preds = %entry
ret void
}
there’s more like this, that’s seemingly well within the purview of this pass, that we don’t optimize. I’ve been looking for these examples using a little script that generates a constraint system and then – if it can be optimized away, according to Alive – uses llvm-reduce to come up with a minimal driver for that particular missed optimization.
is anyone interested in working on this? I would be happy to help, particularly with doing an ongoing search for missed optimizations. if this sounds fun for someone, I can start posting these in our issue tracker.
(edit: I can’t prove that this work will matter, but my strong suspicion is that at a time when there’s a lot of interest in safe languages – that tend to generate a lot of unsatisfiable constraints of the kind that this pass can eliminate – it is in our community’s interests to thoroughly and predictably do this job, for the class of constraints that this pass is designed to attack)