Open mariecurried opened 2 weeks ago
Related Issues and Documentation
(Emoji vote if this was helpful or unhelpful; more detailed feedback welcome in this discussion.)
cc @golang/compiler @randall77
This happens without inlining: https://go.godbolt.org/z/v58b47zf3
I know why it fails, there is a systemic tradeoff in most of the compiler only operating on SSA values, when you store things in memory (&i
) a lot of optimization information is lost, here in this case nilcheckelim
abandon.
So only the outer most *&
pair is being optimized because the ****p
is never stored in memory.
Solving this for all possible cases is impossible, and getting right often is extremely costy both in term of compilation time and compiler code complexity which is a tradeoff the go compiler usually do not accept. The CPU perform store → load forward at runtime, I doubt this has huge cost impact at runtime.
I have an idea on how to cheaply improve this extremely naive example but this wont solve much more cases.
Well I was only able to improve the situation slightly:
# /tmp/a.go
00000 (3) TEXT command-line-arguments.f(SB), ABIInternal
00001 (3) FUNCDATA $0, gclocals·g2BeySu+wFnoycgXfElmcg==(SB)
00002 (3) FUNCDATA $1, gclocals·EaPwxsZ75yY1hHMVZLmk6g==(SB)
00003 (3) FUNCDATA $2, command-line-arguments.f.stkobj(SB)
v6 00004 (+4) MOVQ $1, command-line-arguments.i-24(SP)
v27 00005 (+5) LEAQ command-line-arguments.i-24(SP), AX
v10 00006 (5) MOVQ AX, command-line-arguments.p1-8(SP)
v16 00007 (+6) LEAQ command-line-arguments.p1-8(SP), AX
v14 00008 (6) MOVQ AX, command-line-arguments.p2-16(SP)
v24 00009 (+9) MOVQ command-line-arguments.p2-16(SP), AX
v26 00010 (9) MOVQ (AX), AX
v28 00011 (9) MOVQ $100, (AX)
b1 00012 (10) RET
00013 (?) END
I removed the in the way nilchecks, which removes one more load, however then the dead stores become in the way and I don't know of a cheap way to run theses during late opt. I think this fall in the « passes ordering is hard » kind of camp, given it would solve itself if we reran the core generic passes in a loop until things stabilize but that expensive.
Change https://go.dev/cl/609995 mentions this issue: cmd/compile: remove some uneeded nilchecks during opt
Go version
go version devel go1.24-7fcd4a7 Mon Aug 19 23:36:23 2024 +0000 linux/amd64
What did you do?
I was reading https://www.dolthub.com/blog/2024-08-23-the-4-chan-go-programmer and there was a piece of code that caught my attention (keep in mind that it is a contrived example, but could reveal a bigger problem). So I decided to check the generated assembly (https://go.godbolt.org/z/oxqbPnPxn).
What did you see happen?
In some of the functions there were redundant instructions (marked with
; REDUNDANT
).setInt4
is compiled to:setInt3
is compiled to:setInt2
is compiled to:setInt1
is compiled to:What did you expect to see?
I expected to see no redundant instructions.