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