Issue 78875
Summary Consecutive comparisons are not combined into a single comparison (impacts safety checks)
Labels new issue
Assignees
Reporter davidben
    Clang does not seem to be able to figure out these two functions are the same:

```
void f(const int *data, size_t size) {
    if (size < 5) __builtin_trap();
    if (size == 5) __builtin_trap();
}

void g(const int *data, size_t size) {
 if (size < 5 || size == 5) __builtin_trap();
}
```

Given `f`, it emits two branches. Given `g`, it figures out this comparison is simply `size <= 5`:

This came up as I was putting together a fix for https://github.com/llvm/llvm-project/issues/78829, equivalently step 1 of https://github.com/llvm/llvm-project/issues/78771. My new version, in addition to being safe, generally optimized better, *except* that `*(span.begin() + 5)` gets slightly worse.

This is because there are two not-quite-redundant preconditions on this operation, whether `begin() + 5` is allowed, and whether `operator*` is allowed. `begin() + 5`'s precondition is `size() >= 5`. In particular, if `size() == 5`, it is still okay to utter `begin() + 5` because you just get to `end()`. However, `*iter` then needs to check if we're at end()`, at which point `size() == 5` is rejected. Without being able to combine the two conditions into `size() > 5`, we get two branches instead of one.

Here's a godbolt link with a more extensive set of examples.
https://godbolt.org/z/K6Yz4M8ae

(CC @danakj. I suspect this missed optimization impacts Chromium's existing checked iterator too.)
_______________________________________________
llvm-bugs mailing list
llvm-bugs@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to