regalloc: simplifies regInUseSet (#2227)
This makes the compilation slightly faster and simplifies the codebase.
```
goos: darwin
goarch: arm64
pkg: github.com/tetratelabs/wazero
│ old.txt │ new.txt │
│ sec/op │ sec/op vs base │
Compilation-10 2.499 ± 0% 2.478 ± 2% -0.84% (p=0.026 n=7)
│ old.txt │ new.txt │
│ B/op │ B/op vs base │
Compilation-10 341.0Mi ± 0% 341.1Mi ± 0% ~ (p=0.128 n=7)
│ old.txt │ new.txt │
│ allocs/op │ allocs/op vs base │
Compilation-10 606.9k ± 0% 606.9k ± 0% ~ (p=0.383 n=7)
```
Signed-off-by: Takeshi Yoneda <t.y.mathetake@gmail.com>
This commit is contained in:
@@ -972,6 +972,12 @@ func (a *Allocator) fixMergeState(f Function, blk Block) {
|
|||||||
bID := blk.ID()
|
bID := blk.ID()
|
||||||
blkSt := a.getOrAllocateBlockState(bID)
|
blkSt := a.getOrAllocateBlockState(bID)
|
||||||
desiredOccupants := &blkSt.startRegs
|
desiredOccupants := &blkSt.startRegs
|
||||||
|
var desiredOccupantsSet RegSet
|
||||||
|
for i, v := range desiredOccupants {
|
||||||
|
if v != VRegInvalid {
|
||||||
|
desiredOccupantsSet = desiredOccupantsSet.add(RealReg(i))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if wazevoapi.RegAllocLoggingEnabled {
|
if wazevoapi.RegAllocLoggingEnabled {
|
||||||
fmt.Println("fixMergeState", blk.ID(), ":", desiredOccupants.format(a.regInfo))
|
fmt.Println("fixMergeState", blk.ID(), ":", desiredOccupants.format(a.regInfo))
|
||||||
@@ -993,12 +999,12 @@ func (a *Allocator) fixMergeState(f Function, blk Block) {
|
|||||||
// Finds the free registers if any.
|
// Finds the free registers if any.
|
||||||
intTmp, floatTmp := VRegInvalid, VRegInvalid
|
intTmp, floatTmp := VRegInvalid, VRegInvalid
|
||||||
if intFree := s.findAllocatable(
|
if intFree := s.findAllocatable(
|
||||||
a.regInfo.AllocatableRegisters[RegTypeInt], desiredOccupants.set,
|
a.regInfo.AllocatableRegisters[RegTypeInt], desiredOccupantsSet,
|
||||||
); intFree != RealRegInvalid {
|
); intFree != RealRegInvalid {
|
||||||
intTmp = FromRealReg(intFree, RegTypeInt)
|
intTmp = FromRealReg(intFree, RegTypeInt)
|
||||||
}
|
}
|
||||||
if floatFree := s.findAllocatable(
|
if floatFree := s.findAllocatable(
|
||||||
a.regInfo.AllocatableRegisters[RegTypeFloat], desiredOccupants.set,
|
a.regInfo.AllocatableRegisters[RegTypeFloat], desiredOccupantsSet,
|
||||||
); floatFree != RealRegInvalid {
|
); floatFree != RealRegInvalid {
|
||||||
floatTmp = FromRealReg(floatFree, RegTypeFloat)
|
floatTmp = FromRealReg(floatFree, RegTypeFloat)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -366,7 +366,7 @@ func TestAllocator_livenessAnalysis_copy(t *testing.T) {
|
|||||||
|
|
||||||
func Test_findOrSpillAllocatable_prefersSpill(t *testing.T) {
|
func Test_findOrSpillAllocatable_prefersSpill(t *testing.T) {
|
||||||
t.Run("ok", func(t *testing.T) {
|
t.Run("ok", func(t *testing.T) {
|
||||||
s := &state{}
|
s := &state{regsInUse: newRegInUseSet()}
|
||||||
s.regsInUse.add(RealReg(1), VReg(2222222))
|
s.regsInUse.add(RealReg(1), VReg(2222222))
|
||||||
got := s.findOrSpillAllocatable(&Allocator{}, []RealReg{3}, 0, 3)
|
got := s.findOrSpillAllocatable(&Allocator{}, []RealReg{3}, 0, 3)
|
||||||
require.Equal(t, RealReg(3), got)
|
require.Equal(t, RealReg(3), got)
|
||||||
|
|||||||
@@ -46,23 +46,24 @@ func (rs RegSet) Range(f func(allocatedRealReg RealReg)) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type regInUseSet struct {
|
type regInUseSet [64]VReg
|
||||||
set RegSet
|
|
||||||
vrs [64]VReg
|
func newRegInUseSet() regInUseSet {
|
||||||
|
var ret regInUseSet
|
||||||
|
ret.reset()
|
||||||
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rs *regInUseSet) reset() {
|
func (rs *regInUseSet) reset() {
|
||||||
rs.set = 0
|
for i := range rs {
|
||||||
for i := range rs.vrs {
|
rs[i] = VRegInvalid
|
||||||
rs.vrs[i] = VRegInvalid
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rs *regInUseSet) format(info *RegisterInfo) string { //nolint:unused
|
func (rs *regInUseSet) format(info *RegisterInfo) string { //nolint:unused
|
||||||
var ret []string
|
var ret []string
|
||||||
for i := 0; i < 64; i++ {
|
for i, vr := range rs {
|
||||||
if rs.set&(1<<uint(i)) != 0 {
|
if vr != VRegInvalid {
|
||||||
vr := rs.vrs[i]
|
|
||||||
ret = append(ret, fmt.Sprintf("(%s->v%d)", info.RealRegName(RealReg(i)), vr.ID()))
|
ret = append(ret, fmt.Sprintf("(%s->v%d)", info.RealRegName(RealReg(i)), vr.ID()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -70,39 +71,28 @@ func (rs *regInUseSet) format(info *RegisterInfo) string { //nolint:unused
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (rs *regInUseSet) has(r RealReg) bool {
|
func (rs *regInUseSet) has(r RealReg) bool {
|
||||||
if r >= 64 {
|
return r < 64 && rs[r] != VRegInvalid
|
||||||
return false
|
|
||||||
}
|
|
||||||
return rs.set&(1<<uint(r)) != 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rs *regInUseSet) get(r RealReg) VReg {
|
func (rs *regInUseSet) get(r RealReg) VReg {
|
||||||
if r >= 64 {
|
return rs[r]
|
||||||
return VRegInvalid
|
|
||||||
}
|
|
||||||
return rs.vrs[r]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rs *regInUseSet) remove(r RealReg) {
|
func (rs *regInUseSet) remove(r RealReg) {
|
||||||
if r >= 64 {
|
rs[r] = VRegInvalid
|
||||||
return
|
|
||||||
}
|
|
||||||
rs.set &= ^(1 << uint(r))
|
|
||||||
rs.vrs[r] = VRegInvalid
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rs *regInUseSet) add(r RealReg, vr VReg) {
|
func (rs *regInUseSet) add(r RealReg, vr VReg) {
|
||||||
if r >= 64 {
|
if r >= 64 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
rs.set |= 1 << uint(r)
|
rs[r] = vr
|
||||||
rs.vrs[r] = vr
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rs *regInUseSet) range_(f func(allocatedRealReg RealReg, vr VReg)) {
|
func (rs *regInUseSet) range_(f func(allocatedRealReg RealReg, vr VReg)) {
|
||||||
for i := 0; i < 64; i++ {
|
for i, vr := range rs {
|
||||||
if rs.set&(1<<uint(i)) != 0 {
|
if vr != VRegInvalid {
|
||||||
f(RealReg(i), rs.vrs[i])
|
f(RealReg(i), vr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user