New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
cmd/compile: bounds checking for unrolled loops is weird #30945
Comments
It's obvious to me also. But it isn't obvious to the compiler. Someone would need to write code to teach the compiler about strided inequalities like this.
I believe what is happening here is that when using I think we could improve the analysis here to fix both of these issues. I'll cc some bounds check / induction variable people. |
Looks |
I was originally thinking strided inequalities would be a cool feature. The 1021 case was an accident I ran into while trying to add a hint so the compiler would know that i could never take a value such that i+3 >= 1024, and it added a panic check. Interestingly: At 1020, there's no panic checks at all, but at 1019 there's all four again. So I think this is probably related to stride analysis in some way. ... And you're right, Oh, and for extra fun: |
There's a CL that's a first step to improving this. I don't think it quite works for your case. |
Yeah, that makes sense. This is some tricky code. |
@seebs - This seems like it's fixed in tip now with https://go-review.googlesource.com/c/go/+/415937. Could you confirm? |
Yes, it is fixed. But, if func foo(s []byte) {
for i := 0; i < len(s) - 3; i += 4 {
_ = s[i+3] // Found IsInBounds
_ = s[i+2] // Found IsInBounds
_ = s[i+1] // Found IsInBounds
_ = s[i]
}
}
func bar(s []byte) {
for i := 0; i <= len(s) - 4; i += 4 {
_ = s[i+3] // Found IsInBounds
_ = s[i+2] // Found IsInBounds
_ = s[i+1] // Found IsInBounds
_ = s[i]
}
} |
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
seems to
What operating system and processor architecture are you using (
go env
)?amd64, but N/A-ish?
go env
OutputWhat did you do?
Tried to unroll a loop, then tried to reduce bounds checking. Here's the godbolt page with the assembly I was looking at.
https://godbolt.org/z/GQuZaf
What did you expect to see?
A lot less bounds checking.
What did you see instead?
It's obvious to me that
i := 0; i < 1024; i += 4
produces no values of i such that i+3 is is outside a :1024 slice.However, there's an even weirder thing: If I do that loop, I get three bounds checks, one for each of the three lines that uses a value computed from i.
But if I change it to
i < 1024-3
, which does not actually change what values i can ever take, it adds a bounds check for the plain i+0 line! That can't possibly be right. If I know the loop's limit is definitely smaller than the size I've already checked the slice to have, that should allow eliminating some bounds checks. (Interestingly, if I set the limit to 1020, then all the bounds checks go away. I suppose I could just unroll the last four entries separately.)The text was updated successfully, but these errors were encountered: