Open
Description
var t [256]byte
func f(b *[16]byte) {
for i, v := range b {
b[i] = t[v]
}
}
Compiles to:
0x000f 00015 (tmp1.go:7) MOVBLZX (AX), DX
0x0012 00018 (tmp1.go:7) LEAQ "".t(SB), BX
0x0019 00025 (tmp1.go:7) MOVBLZX (BX)(DX*1), DX
0x001d 00029 (tmp1.go:7) MOVQ "".b+8(FP), BX
0x0022 00034 (tmp1.go:7) MOVB DL, (BX)(CX*1)
0x0025 00037 (tmp1.go:6) INCQ AX
0x0028 00040 (tmp1.go:6) INCQ CX
0x002b 00043 (tmp1.go:6) CMPQ CX, $16
0x002f 00047 (tmp1.go:6) JLT $0, 15
Both the LEAQ
and the MOVQ "".b+8
could be done outside the loop.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status
Triage Backlog
Milestone
Relationships
Development
No branches or pull requests
Activity
dr2chase commentedon May 24, 2016
Happy to work on this; I prototyped a loop-invariant code hoister and tried it out, but it didn't (at the time) do anything exciting for performance on amd64. Note that this can increase register pressure.
randall77 commentedon May 24, 2016
I thought the register allocator pre-allocated things like this before loop entry. I suspect that something is not working about that code, not that we need a whole new pass. (Not that a code hoister is a bad idea, just that it may not be needed for this issue.)
mattn commentedon Aug 4, 2016
If overwriting t in goroutine, the loop should refer the new t. So need to LEAQ is required in this loop. If the loop-count is large enough, below should remove the LEAQ in the loop.
dr2chase commentedon Feb 22, 2017
I just revived my old loop-invariant-code experiment, and here's a (very) preliminary result.
CL here: https://go-review.googlesource.com/37338
I'm doing no transformations, just looking at what I might change. To note:
(1) this pushes "loop-invariant" till it finds them all.
(2) anything depending on a store is loop-variant.
(3) anything depending on a phi is loop-variant (this is a little wimpy).
(4) anything rematerializable is considered uninteresting (for reporting purposes)
(5) innermost loops only.
(6) must-execute blocks only.
(6) haven't thought/worried about problem of hoisting things that fault (like division)
(7) there's loop-invariant control flow in there we might want to think about.
gopherbot commentedon Feb 22, 2017
CL https://golang.org/cl/37338 mentions this issue.
navytux commentedon Mar 25, 2017
For the reference - I was looking at
encoding.hex.Encode()
code becuase it shows high in my profiles and noticed: there is the same case presented originally in this issue:The
LEAQ go.string."0123456789abcdef"(SB), R10
is loop invariant here, but(citing from above)
the Encode() function is not reported for being detected with invariant in a loop.
Thanks,
Kirill
josharian commentedon Mar 25, 2017
Out of curiosity, Kirill, is 1.8 any better than tip for Encode? (Or vice versa, depending on which you are using?) There was a recent change to CSE constant strings.
60 remaining items
laboger commentedon May 24, 2022
I'm looking at your latest CL on a simple test like this:
I would like the base address of the flags array (which is a constant) to be hoisted outside the loop. In this test, it is loaded in the first block and stays there through all the passes until it gets to regalloc.
But after regalloc:
I know there are checks for rematerializable with comments that say the loads need to be closer to their uses, so I suspect that is causing this. However, I think in the case where the constant is referenced within a loop, it should at least be able to be hoisted out of the loop.
This situation happens where a loop is stepping through an array and the base address is a constant but can't be hoisted since constants are all rematerializable, which is common.
dr2chase commentedon May 24, 2022
The current code, which is amd64-influenced, may not be aggressive enough to do what you want here; code (fragments) that don't reach a threshold aren't hoisted. Fighting with the register allocator is another issue.
cmd/compile: hoist some loop invariants
gopherbot commentedon Mar 23, 2023
Change https://go.dev/cl/478815 mentions this issue:
cmd/compile: hoist some loop invariants
cmd/compile: hoist some loop invariants