Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

regalloc: eliminates unnecessary Instr loop #2258

Merged
merged 1 commit into from
Jun 18, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 22 additions & 21 deletions internal/engine/wazevo/backend/regalloc/regalloc.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ type (
allocatedCalleeSavedRegs []VReg
vs []VReg
vs2 []VRegID
is []Instr
phiDefInstListPool wazevoapi.Pool[phiDefInstList]

// Followings are re-used during various places.
Expand Down Expand Up @@ -660,6 +661,7 @@ func (a *Allocator) allocBlock(f Function, blk Block) {
desiredUpdated := a.vs2[:0]

// Update the last use of each VReg.
a.is = a.is[:0] // Stores the copy instructions.
var pc programCounter
for instr := blk.InstrIteratorBegin(); instr != nil; instr = blk.InstrIteratorNext() {
var use, def VReg
Expand All @@ -670,6 +672,7 @@ func (a *Allocator) allocBlock(f Function, blk Block) {
}

if instr.IsCopy() {
a.is = append(a.is, instr)
def = instr.Defs(&a.vs)[0]
r := def.RealReg()
if r != RealRegInvalid {
Expand Down Expand Up @@ -722,22 +725,20 @@ func (a *Allocator) allocBlock(f Function, blk Block) {
}

// Propagate the desired register values from the end of the block to the beginning.
for instr := blk.InstrRevIteratorBegin(); instr != nil; instr = blk.InstrRevIteratorNext() {
if instr.IsCopy() {
def := instr.Defs(&a.vs)[0]
defState := s.getVRegState(def.ID())
desired := defState.desiredLoc.realReg()
if desired == RealRegInvalid {
continue
}
for _, instr := range a.is {
def := instr.Defs(&a.vs)[0]
defState := s.getVRegState(def.ID())
desired := defState.desiredLoc.realReg()
if desired == RealRegInvalid {
continue
}

use := instr.Uses(&a.vs)[0]
useID := use.ID()
useState := s.getVRegState(useID)
if s.phiBlk(useID) != succ && useState.desiredLoc == desiredLocUnspecified {
useState.desiredLoc = newDesiredLocReg(desired)
desiredUpdated = append(desiredUpdated, useID)
}
use := instr.Uses(&a.vs)[0]
useID := use.ID()
useState := s.getVRegState(useID)
if s.phiBlk(useID) != succ && useState.desiredLoc == desiredLocUnspecified {
useState.desiredLoc = newDesiredLocReg(desired)
desiredUpdated = append(desiredUpdated, useID)
}
}

Expand Down Expand Up @@ -796,10 +797,9 @@ func (a *Allocator) allocBlock(f Function, blk Block) {
}

isIndirect := instr.IsIndirectCall()
call := instr.IsCall() || isIndirect
if call {
if instr.IsCall() || isIndirect {
addr := RealRegInvalid
if instr.IsIndirectCall() {
if isIndirect {
addr = a.vs[0].RealReg()
}
a.releaseCallerSavedRegs(addr)
Expand All @@ -811,8 +811,8 @@ func (a *Allocator) allocBlock(f Function, blk Block) {
a.reals = killSet

defs := instr.Defs(&a.vs)
switch {
case len(defs) > 1:
switch len(defs) {
default:
// Some instructions define multiple values on real registers.
// E.g. call instructions (following calling convention) / div instruction on x64 that defines both rax and rdx.
//
Expand All @@ -829,7 +829,8 @@ func (a *Allocator) allocBlock(f Function, blk Block) {
}
s.useRealReg(r, def)
}
case len(defs) == 1:
case 0:
case 1:
def := defs[0]
if def.IsRealReg() {
r := def.RealReg()
Expand Down
Loading