diff options
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.go | 105 |
1 files changed, 44 insertions, 61 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 89ec34b7e..b9763791d 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 @@ -112,7 +112,7 @@ func passDeadBlockEliminationOpt(b *builder) { // 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. + redundantParams := b.redundantParams[:0] // reuse the slice from previous iterations. // TODO: this might be costly for large programs, but at least, as far as I did the experiment, it's almost the // same as the single iteration version in terms of the overall compilation time. That *might be* mostly thanks to the fact @@ -128,10 +128,11 @@ func passRedundantPhiEliminationOpt(b *builder) { _ = 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.blockIteratorReversePostOrderNext(); blk != nil; blk = b.blockIteratorReversePostOrderNext() { - paramNum := len(blk.params) + params := blk.params.View() + paramNum := len(params) for paramIndex := 0; paramIndex < paramNum; paramIndex++ { - phiValue := blk.params[paramIndex] + phiValue := params[paramIndex] redundant := true nonSelfReferencingValue := ValueInvalid @@ -162,55 +163,58 @@ func passRedundantPhiEliminationOpt(b *builder) { } if redundant { - b.redundantParameterIndexToValue[paramIndex] = nonSelfReferencingValue - redundantParameterIndexes = append(redundantParameterIndexes, paramIndex) + redundantParams = append(redundantParams, redundantParam{ + index: paramIndex, uniqueValue: nonSelfReferencingValue, + }) } } - if len(b.redundantParameterIndexToValue) == 0 { + if len(redundantParams) == 0 { continue } changed = true // Remove the redundant PHIs from the argument list of branching instructions. for predIndex := range blk.preds { - var cur int + redundantParamsCur, predParamCur := 0, 0 predBlk := blk.preds[predIndex] branchInst := predBlk.branch view := branchInst.vs.View() for argIndex, value := range view { - if _, ok := b.redundantParameterIndexToValue[argIndex]; !ok { - view[cur] = value - cur++ + if len(redundantParams) == redundantParamsCur || + redundantParams[redundantParamsCur].index != argIndex { + view[predParamCur] = value + predParamCur++ + } else { + redundantParamsCur++ } } - branchInst.vs.Cut(cur) + branchInst.vs.Cut(predParamCur) } // Still need to have the definition of the value of the PHI (previously as the parameter). - for _, redundantParamIndex := range redundantParameterIndexes { - phiValue := blk.params[redundantParamIndex] - onlyValue := b.redundantParameterIndexToValue[redundantParamIndex] + for i := range redundantParams { + redundantValue := &redundantParams[i] + phiValue := params[redundantValue.index] // Create an alias in this block from the only phi argument to the phi value. - b.alias(phiValue, onlyValue) + b.alias(phiValue, redundantValue.uniqueValue) } // Finally, Remove the param from the blk. - var cur int + paramsCur, redundantParamsCur := 0, 0 for paramIndex := 0; paramIndex < paramNum; paramIndex++ { - param := blk.params[paramIndex] - if _, ok := b.redundantParameterIndexToValue[paramIndex]; !ok { - blk.params[cur] = param - cur++ + param := params[paramIndex] + if len(redundantParams) == redundantParamsCur || redundantParams[redundantParamsCur].index != paramIndex { + params[paramsCur] = param + paramsCur++ + } else { + redundantParamsCur++ } } - blk.params = blk.params[:cur] + blk.params.Cut(paramsCur) // Clears the map for the next iteration. - for _, paramIndex := range redundantParameterIndexes { - delete(b.redundantParameterIndexToValue, paramIndex) - } - redundantParameterIndexes = redundantParameterIndexes[:0] + redundantParams = redundantParams[:0] } if !changed { @@ -219,7 +223,7 @@ func passRedundantPhiEliminationOpt(b *builder) { } // Reuse the slice for the future passes. - b.ints = redundantParameterIndexes + b.redundantParams = redundantParams } // passDeadCodeEliminationOpt traverses all the instructions, and calculates the reference count of each Value, and @@ -231,11 +235,13 @@ func passRedundantPhiEliminationOpt(b *builder) { // TODO: the algorithm here might not be efficient. Get back to this later. func passDeadCodeEliminationOpt(b *builder) { nvid := int(b.nextValueID) - if nvid >= len(b.valueRefCounts) { - b.valueRefCounts = append(b.valueRefCounts, make([]int, nvid-len(b.valueRefCounts)+1)...) - } - if nvid >= len(b.valueIDToInstruction) { - b.valueIDToInstruction = append(b.valueIDToInstruction, make([]*Instruction, nvid-len(b.valueIDToInstruction)+1)...) + if nvid >= len(b.valuesInfo) { + l := nvid - len(b.valuesInfo) + 1 + b.valuesInfo = append(b.valuesInfo, make([]ValueInfo, l)...) + view := b.valuesInfo[len(b.valuesInfo)-l:] + for i := range view { + view[i].alias = ValueInvalid + } } // First, we gather all the instructions with side effects. @@ -255,14 +261,6 @@ func passDeadCodeEliminationOpt(b *builder) { // The strict side effect should create different instruction groups. gid++ } - - r1, rs := cur.Returns() - if r1.Valid() { - b.valueIDToInstruction[r1.ID()] = cur - } - for _, r := range rs { - b.valueIDToInstruction[r.ID()] = cur - } } } @@ -283,28 +281,28 @@ func passDeadCodeEliminationOpt(b *builder) { v1, v2, v3, vs := live.Args() if v1.Valid() { - producingInst := b.valueIDToInstruction[v1.ID()] + producingInst := b.InstructionOfValue(v1) if producingInst != nil { liveInstructions = append(liveInstructions, producingInst) } } if v2.Valid() { - producingInst := b.valueIDToInstruction[v2.ID()] + producingInst := b.InstructionOfValue(v2) if producingInst != nil { liveInstructions = append(liveInstructions, producingInst) } } if v3.Valid() { - producingInst := b.valueIDToInstruction[v3.ID()] + producingInst := b.InstructionOfValue(v3) if producingInst != nil { liveInstructions = append(liveInstructions, producingInst) } } for _, v := range vs { - producingInst := b.valueIDToInstruction[v.ID()] + producingInst := b.InstructionOfValue(v) if producingInst != nil { liveInstructions = append(liveInstructions, producingInst) } @@ -352,34 +350,19 @@ func (b *builder) incRefCount(id ValueID, from *Instruction) { if wazevoapi.SSALoggingEnabled { fmt.Printf("v%d referenced from %v\n", id, from.Format(b)) } - b.valueRefCounts[id]++ + info := &b.valuesInfo[id] + info.RefCount++ } // 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, int(b.nextValueID)-len(b.valueIDToInstruction)+1)...) - } - - for blk := b.blockIteratorBegin(); blk != nil; blk = b.blockIteratorNext() { - for cur := blk.rootInstr; cur != nil; cur = cur.next { - r1, rs := cur.Returns() - if r1.Valid() { - b.valueIDToInstruction[r1.ID()] = cur - } - for _, r := range rs { - b.valueIDToInstruction[r.ID()] = cur - } - } - } - for blk := b.blockIteratorBegin(); blk != nil; blk = b.blockIteratorNext() { for cur := blk.rootInstr; cur != nil; cur = cur.next { switch cur.Opcode() { // TODO: add more logics here. case OpcodeIshl, OpcodeSshr, OpcodeUshr: x, amount := cur.Arg2() - definingInst := b.valueIDToInstruction[amount.ID()] + definingInst := b.InstructionOfValue(amount) if definingInst == nil { // If there's no defining instruction, that means the amount is coming from the parameter. continue |