summaryrefslogtreecommitdiff
path: root/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/pass.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/pass.go')
-rw-r--r--vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/pass.go41
1 files changed, 17 insertions, 24 deletions
diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/pass.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/pass.go
index a2e986cd1..89ec34b7e 100644
--- a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/pass.go
+++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/pass.go
@@ -22,9 +22,9 @@ func (b *builder) RunPasses() {
func (b *builder) runPreBlockLayoutPasses() {
passSortSuccessors(b)
passDeadBlockEliminationOpt(b)
- passRedundantPhiEliminationOpt(b)
// The result of passCalculateImmediateDominators will be used by various passes below.
passCalculateImmediateDominators(b)
+ passRedundantPhiEliminationOpt(b)
passNopInstElimination(b)
// TODO: implement either conversion of irreducible CFG into reducible one, or irreducible CFG detection where we panic.
@@ -78,12 +78,11 @@ func (b *builder) runFinalizingPasses() {
// passDeadBlockEliminationOpt searches the unreachable blocks, and sets the basicBlock.invalid flag true if so.
func passDeadBlockEliminationOpt(b *builder) {
entryBlk := b.entryBlk()
- b.clearBlkVisited()
b.blkStack = append(b.blkStack, entryBlk)
for len(b.blkStack) > 0 {
reachableBlk := b.blkStack[len(b.blkStack)-1]
b.blkStack = b.blkStack[:len(b.blkStack)-1]
- b.blkVisited[reachableBlk] = 0 // the value won't be used in this pass.
+ reachableBlk.visited = 1
if !reachableBlk.sealed && !reachableBlk.ReturnBlock() {
panic(fmt.Sprintf("%s is not sealed", reachableBlk))
@@ -94,7 +93,7 @@ func passDeadBlockEliminationOpt(b *builder) {
}
for _, succ := range reachableBlk.success {
- if _, ok := b.blkVisited[succ]; ok {
+ if succ.visited == 1 {
continue
}
b.blkStack = append(b.blkStack, succ)
@@ -102,13 +101,16 @@ func passDeadBlockEliminationOpt(b *builder) {
}
for blk := b.blockIteratorBegin(); blk != nil; blk = b.blockIteratorNext() {
- if _, ok := b.blkVisited[blk]; !ok {
+ if blk.visited != 1 {
blk.invalid = true
}
+ blk.visited = 0
}
}
// passRedundantPhiEliminationOpt eliminates the redundant PHIs (in our terminology, parameters of a block).
+// This requires the reverse post-order traversal to be calculated before calling this function,
+// hence passCalculateImmediateDominators must be called before this.
func passRedundantPhiEliminationOpt(b *builder) {
redundantParameterIndexes := b.ints[:0] // reuse the slice from previous iterations.
@@ -118,15 +120,18 @@ func passRedundantPhiEliminationOpt(b *builder) {
// relatively small. For example, sqlite speedtest binary results in the large number of redundant PHIs,
// the maximum number of iteration was 22, which seems to be acceptable but not that small either since the
// complexity here is O(BlockNum * Iterations) at the worst case where BlockNum might be the order of thousands.
+ // -- Note --
+ // Currently, each iteration can run in any order of blocks, but it empirically converges quickly in practice when
+ // running on the reverse post-order. It might be possible to optimize this further by using the dominator tree.
for {
changed := false
- _ = b.blockIteratorBegin() // skip entry block!
+ _ = b.blockIteratorReversePostOrderBegin() // skip entry block!
// Below, we intentionally use the named iteration variable name, as this comes with inevitable nested for loops!
- for blk := b.blockIteratorNext(); blk != nil; blk = b.blockIteratorNext() {
+ for blk := b.blockIteratorReversePostOrderNext(); blk != nil; blk = b.blockIteratorReversePostOrderNext() {
paramNum := len(blk.params)
for paramIndex := 0; paramIndex < paramNum; paramIndex++ {
- phiValue := blk.params[paramIndex].value
+ phiValue := blk.params[paramIndex]
redundant := true
nonSelfReferencingValue := ValueInvalid
@@ -184,7 +189,7 @@ func passRedundantPhiEliminationOpt(b *builder) {
// Still need to have the definition of the value of the PHI (previously as the parameter).
for _, redundantParamIndex := range redundantParameterIndexes {
- phiValue := blk.params[redundantParamIndex].value
+ phiValue := blk.params[redundantParamIndex]
onlyValue := b.redundantParameterIndexToValue[redundantParamIndex]
// Create an alias in this block from the only phi argument to the phi value.
b.alias(phiValue, onlyValue)
@@ -227,10 +232,10 @@ func passRedundantPhiEliminationOpt(b *builder) {
func passDeadCodeEliminationOpt(b *builder) {
nvid := int(b.nextValueID)
if nvid >= len(b.valueRefCounts) {
- b.valueRefCounts = append(b.valueRefCounts, make([]int, b.nextValueID)...)
+ b.valueRefCounts = append(b.valueRefCounts, make([]int, nvid-len(b.valueRefCounts)+1)...)
}
if nvid >= len(b.valueIDToInstruction) {
- b.valueIDToInstruction = append(b.valueIDToInstruction, make([]*Instruction, b.nextValueID)...)
+ b.valueIDToInstruction = append(b.valueIDToInstruction, make([]*Instruction, nvid-len(b.valueIDToInstruction)+1)...)
}
// First, we gather all the instructions with side effects.
@@ -350,22 +355,10 @@ func (b *builder) incRefCount(id ValueID, from *Instruction) {
b.valueRefCounts[id]++
}
-// clearBlkVisited clears the b.blkVisited map so that we can reuse it for multiple places.
-func (b *builder) clearBlkVisited() {
- b.blkStack2 = b.blkStack2[:0]
- for key := range b.blkVisited {
- b.blkStack2 = append(b.blkStack2, key)
- }
- for _, blk := range b.blkStack2 {
- delete(b.blkVisited, blk)
- }
- b.blkStack2 = b.blkStack2[:0]
-}
-
// passNopInstElimination eliminates the instructions which is essentially a no-op.
func passNopInstElimination(b *builder) {
if int(b.nextValueID) >= len(b.valueIDToInstruction) {
- b.valueIDToInstruction = append(b.valueIDToInstruction, make([]*Instruction, b.nextValueID)...)
+ b.valueIDToInstruction = append(b.valueIDToInstruction, make([]*Instruction, int(b.nextValueID)-len(b.valueIDToInstruction)+1)...)
}
for blk := b.blockIteratorBegin(); blk != nil; blk = b.blockIteratorNext() {