We manually partially inline utf8.DecodeRune in a few places in the tree. For example, in bytes.EqualFold, we have:
if s[0] < utf8.RuneSelf {
sr, s = rune(s[0]), s[1:]
} else {
r, size := utf8.DecodeRune(s)
sr, s = r, s[size:]
}
It'd be nice to rewrite utf8.DecodeRune like this:
func DecodeRune(p []byte) (r rune, size int) {
if len(p) > 0 && p[0] < RuneSelf {
return rune(p[0]), 1
}
return decodeRuneSlow(p)
}
and then let mid-stack inlining take it from there. (And delete all the manual partial inlining.)
Unfortunately, this has a cost of 89, over the budget of 80.
This is basically just another variant of https://github.com/golang/go/issues/17566, but I'm filing it separately since that issue is super noisy.
cc @bradfitz @mvdan @dr2chase
Comment From: martisch
While at it we should make it also work for utf8.DecodeRuneInString at the same time.
Comment From: mvdan
Perhaps very clear cases like this can be used to start tweaking the inlining heuristic in the right direction, with the smallest steps possible.
Comment From: corona10
@martisch @mvdan Can I take a look at this issue?
Comment From: mvdan
@corona10 you're certainly welcome to take a look, but if you're looking for low-hanging fruit issues to work on, this isn't a good candidate. It likely requires someone with a good understanding of the compiler, and it's not a simple fix, as @josharian already gave that a try.
Comment From: corona10
@mvdan Oh.. @josharian already tried it. Looks like a not simple issue. I thought it was just an issue of rewriting so that it can help the compiler to do a mid stack inlining, but I did not know that cost was an issue to consider. I will try to find some easier issues.
Comment From: renthraysk
binary.Uvarint() has the same problem. Impossible to write the 1 byte fast path mid stack func without exceeding cost.
Comment From: gopherbot
Change https://go.dev/cl/425459 mentions this issue: bytes/strings: add ASCII fast path to EqualFold
Comment From: jub0bs
@martisch
While at it we should make it also work for utf8.DecodeRuneInString at the same time.
See https://github.com/golang/go/issues/48195#issuecomment-3224273708