Consider the following code:
func gte4(x uint64) bool {
return 4 <= x
}
func lt20(x uint64) bool {
return x < 20
}
func example(x uint64, t, f int) int {
if gte4(x) && lt20(x) {
return t
}
return f
}
When compiled this produces:
00007 CMP $4, R0
00008 BLO 14
00009 NOP
00010 CMP $20, R0
00011 BHS 14
00012 MOVD R1, R0
00013 RET
00014 MOVD R2, R0
00015 RET
If, however, I manually inline the gte4
and lt20
functions the result is more optimal:
00006 SUB $4, R0, R3
00007 CMP $16, R3
00008 BHS 11
00009 MOVD R1, R0
00010 RET
00011 MOVD R2, R0
00012 RET
After a bit of investigation it turns out this is because the InlMark
op has a memory argument which currently prevents speculative execution of any block containing it. That in turn blocks the integer range check optimisation. I will send a fix.
Comment From: gopherbot
Change https://go.dev/cl/693795 mentions this issue: cmd/compile: allow InlMark operations to be speculatively executed