mirror of
https://github.com/superseriousbusiness/gotosocial
synced 2025-06-05 21:59:39 +02:00
[chore] Upgrade wasm-sqlite to v0.16.2 (#2997)
This commit is contained in:
73
vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/basic_block.go
generated
vendored
73
vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/basic_block.go
generated
vendored
@@ -49,21 +49,12 @@ type BasicBlock interface {
|
||||
// ReturnBlock returns ture if this block represents the function return.
|
||||
ReturnBlock() bool
|
||||
|
||||
// FormatHeader returns the debug string of this block, not including instruction.
|
||||
FormatHeader(b Builder) string
|
||||
|
||||
// Valid is true if this block is still valid even after optimizations.
|
||||
Valid() bool
|
||||
|
||||
// Sealed is true if this block has been sealed.
|
||||
Sealed() bool
|
||||
|
||||
// BeginPredIterator returns the first predecessor of this block.
|
||||
BeginPredIterator() BasicBlock
|
||||
|
||||
// NextPredIterator returns the next predecessor of this block.
|
||||
NextPredIterator() BasicBlock
|
||||
|
||||
// Preds returns the number of predecessors of this block.
|
||||
Preds() int
|
||||
|
||||
@@ -88,10 +79,11 @@ type (
|
||||
basicBlock struct {
|
||||
id BasicBlockID
|
||||
rootInstr, currentInstr *Instruction
|
||||
params []blockParam
|
||||
predIter int
|
||||
preds []basicBlockPredecessorInfo
|
||||
success []*basicBlock
|
||||
// params are Values that represent parameters to a basicBlock.
|
||||
// Each parameter can be considered as an output of PHI instruction in traditional SSA.
|
||||
params []Value
|
||||
preds []basicBlockPredecessorInfo
|
||||
success []*basicBlock
|
||||
// singlePred is the alias to preds[0] for fast lookup, and only set after Seal is called.
|
||||
singlePred *basicBlock
|
||||
// lastDefinitions maps Variable to its last definition in this block.
|
||||
@@ -116,11 +108,14 @@ type (
|
||||
|
||||
// loopNestingForestChildren holds the children of this block in the loop nesting forest.
|
||||
// Non-empty if and only if this block is a loop header (i.e. loopHeader=true)
|
||||
loopNestingForestChildren []BasicBlock
|
||||
loopNestingForestChildren wazevoapi.VarLength[BasicBlock]
|
||||
|
||||
// reversePostOrder is used to sort all the blocks in the function in reverse post order.
|
||||
// This is used in builder.LayoutBlocks.
|
||||
reversePostOrder int
|
||||
reversePostOrder int32
|
||||
|
||||
// visited is used during various traversals.
|
||||
visited int32
|
||||
|
||||
// child and sibling are the ones in the dominator tree.
|
||||
child, sibling *basicBlock
|
||||
@@ -128,15 +123,6 @@ type (
|
||||
// BasicBlockID is the unique ID of a basicBlock.
|
||||
BasicBlockID uint32
|
||||
|
||||
// blockParam implements Value and represents a parameter to a basicBlock.
|
||||
blockParam struct {
|
||||
// value is the Value that corresponds to the parameter in this block,
|
||||
// and can be considered as an output of PHI instruction in traditional SSA.
|
||||
value Value
|
||||
// typ is the type of the parameter.
|
||||
typ Type
|
||||
}
|
||||
|
||||
unknownValue struct {
|
||||
// variable is the variable that this unknownValue represents.
|
||||
variable Variable
|
||||
@@ -145,6 +131,9 @@ type (
|
||||
}
|
||||
)
|
||||
|
||||
// basicBlockVarLengthNil is the default nil value for basicBlock.loopNestingForestChildren.
|
||||
var basicBlockVarLengthNil = wazevoapi.NewNilVarLength[BasicBlock]()
|
||||
|
||||
const basicBlockIDReturnBlock = 0xffffffff
|
||||
|
||||
// Name implements BasicBlock.Name.
|
||||
@@ -190,13 +179,13 @@ func (bb *basicBlock) ReturnBlock() bool {
|
||||
// AddParam implements BasicBlock.AddParam.
|
||||
func (bb *basicBlock) AddParam(b Builder, typ Type) Value {
|
||||
paramValue := b.allocateValue(typ)
|
||||
bb.params = append(bb.params, blockParam{typ: typ, value: paramValue})
|
||||
bb.params = append(bb.params, paramValue)
|
||||
return paramValue
|
||||
}
|
||||
|
||||
// addParamOn adds a parameter to this block whose value is already allocated.
|
||||
func (bb *basicBlock) addParamOn(typ Type, value Value) {
|
||||
bb.params = append(bb.params, blockParam{typ: typ, value: value})
|
||||
func (bb *basicBlock) addParamOn(value Value) {
|
||||
bb.params = append(bb.params, value)
|
||||
}
|
||||
|
||||
// Params implements BasicBlock.Params.
|
||||
@@ -206,8 +195,7 @@ func (bb *basicBlock) Params() int {
|
||||
|
||||
// Param implements BasicBlock.Param.
|
||||
func (bb *basicBlock) Param(i int) Value {
|
||||
p := &bb.params[i]
|
||||
return p.value
|
||||
return bb.params[i]
|
||||
}
|
||||
|
||||
// Valid implements BasicBlock.Valid.
|
||||
@@ -248,22 +236,6 @@ func (bb *basicBlock) NumPreds() int {
|
||||
return len(bb.preds)
|
||||
}
|
||||
|
||||
// BeginPredIterator implements BasicBlock.BeginPredIterator.
|
||||
func (bb *basicBlock) BeginPredIterator() BasicBlock {
|
||||
bb.predIter = 0
|
||||
return bb.NextPredIterator()
|
||||
}
|
||||
|
||||
// NextPredIterator implements BasicBlock.NextPredIterator.
|
||||
func (bb *basicBlock) NextPredIterator() BasicBlock {
|
||||
if bb.predIter >= len(bb.preds) {
|
||||
return nil
|
||||
}
|
||||
pred := bb.preds[bb.predIter].blk
|
||||
bb.predIter++
|
||||
return pred
|
||||
}
|
||||
|
||||
// Preds implements BasicBlock.Preds.
|
||||
func (bb *basicBlock) Preds() int {
|
||||
return len(bb.preds)
|
||||
@@ -305,7 +277,8 @@ func resetBasicBlock(bb *basicBlock) {
|
||||
bb.unknownValues = bb.unknownValues[:0]
|
||||
bb.lastDefinitions = wazevoapi.ResetMap(bb.lastDefinitions)
|
||||
bb.reversePostOrder = -1
|
||||
bb.loopNestingForestChildren = bb.loopNestingForestChildren[:0]
|
||||
bb.visited = 0
|
||||
bb.loopNestingForestChildren = basicBlockVarLengthNil
|
||||
bb.loopHeader = false
|
||||
bb.sibling = nil
|
||||
bb.child = nil
|
||||
@@ -335,11 +308,11 @@ func (bb *basicBlock) addPred(blk BasicBlock, branch *Instruction) {
|
||||
pred.success = append(pred.success, bb)
|
||||
}
|
||||
|
||||
// FormatHeader implements BasicBlock.FormatHeader.
|
||||
func (bb *basicBlock) FormatHeader(b Builder) string {
|
||||
// formatHeader returns the string representation of the header of the basicBlock.
|
||||
func (bb *basicBlock) formatHeader(b Builder) string {
|
||||
ps := make([]string, len(bb.params))
|
||||
for i, p := range bb.params {
|
||||
ps[i] = p.value.formatWithType(b)
|
||||
ps[i] = p.formatWithType(b)
|
||||
}
|
||||
|
||||
if len(bb.preds) > 0 {
|
||||
@@ -398,7 +371,7 @@ func (bb *basicBlock) String() string {
|
||||
|
||||
// LoopNestingForestChildren implements BasicBlock.LoopNestingForestChildren.
|
||||
func (bb *basicBlock) LoopNestingForestChildren() []BasicBlock {
|
||||
return bb.loopNestingForestChildren
|
||||
return bb.loopNestingForestChildren.View()
|
||||
}
|
||||
|
||||
// LoopHeader implements BasicBlock.LoopHeader.
|
||||
|
104
vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/builder.go
generated
vendored
104
vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/builder.go
generated
vendored
@@ -54,9 +54,6 @@ type Builder interface {
|
||||
// MustFindValue searches the latest definition of the given Variable and returns the result.
|
||||
MustFindValue(variable Variable) Value
|
||||
|
||||
// MustFindValueInBlk is the same as MustFindValue except it searches the latest definition from the given BasicBlock.
|
||||
MustFindValueInBlk(variable Variable, blk BasicBlock) Value
|
||||
|
||||
// FindValueInLinearPath tries to find the latest definition of the given Variable in the linear path to the current BasicBlock.
|
||||
// If it cannot find the definition, or it's not sealed yet, it returns ValueInvalid.
|
||||
FindValueInLinearPath(variable Variable) Value
|
||||
@@ -127,7 +124,11 @@ type Builder interface {
|
||||
// Idom returns the immediate dominator of the given BasicBlock.
|
||||
Idom(blk BasicBlock) BasicBlock
|
||||
|
||||
// VarLengthPool returns the VarLengthPool of Value.
|
||||
VarLengthPool() *wazevoapi.VarLengthPool[Value]
|
||||
|
||||
// InsertZeroValue inserts a zero value constant instruction of the given type.
|
||||
InsertZeroValue(t Type)
|
||||
}
|
||||
|
||||
// NewBuilder returns a new Builder implementation.
|
||||
@@ -135,10 +136,10 @@ func NewBuilder() Builder {
|
||||
return &builder{
|
||||
instructionsPool: wazevoapi.NewPool[Instruction](resetInstruction),
|
||||
basicBlocksPool: wazevoapi.NewPool[basicBlock](resetBasicBlock),
|
||||
varLengthBasicBlockPool: wazevoapi.NewVarLengthPool[BasicBlock](),
|
||||
varLengthPool: wazevoapi.NewVarLengthPool[Value](),
|
||||
valueAnnotations: make(map[ValueID]string),
|
||||
signatures: make(map[SignatureID]*Signature),
|
||||
blkVisited: make(map[*basicBlock]int),
|
||||
valueIDAliases: make(map[ValueID]Value),
|
||||
redundantParameterIndexToValue: make(map[int]Value),
|
||||
returnBlk: &basicBlock{id: basicBlockIDReturnBlock},
|
||||
@@ -177,12 +178,13 @@ type builder struct {
|
||||
dominators []*basicBlock
|
||||
sparseTree dominatorSparseTree
|
||||
|
||||
varLengthBasicBlockPool wazevoapi.VarLengthPool[BasicBlock]
|
||||
|
||||
// loopNestingForestRoots are the roots of the loop nesting forest.
|
||||
loopNestingForestRoots []BasicBlock
|
||||
|
||||
// The followings are used for optimization passes/deterministic compilation.
|
||||
instStack []*Instruction
|
||||
blkVisited map[*basicBlock]int
|
||||
valueIDToInstruction []*Instruction
|
||||
blkStack []*basicBlock
|
||||
blkStack2 []*basicBlock
|
||||
@@ -200,6 +202,32 @@ type builder struct {
|
||||
donePostBlockLayoutPasses bool
|
||||
|
||||
currentSourceOffset SourceOffset
|
||||
|
||||
// zeros are the zero value constants for each type.
|
||||
zeros [typeEnd]Value
|
||||
}
|
||||
|
||||
// InsertZeroValue implements Builder.InsertZeroValue.
|
||||
func (b *builder) InsertZeroValue(t Type) {
|
||||
if b.zeros[t].Valid() {
|
||||
return
|
||||
}
|
||||
zeroInst := b.AllocateInstruction()
|
||||
switch t {
|
||||
case TypeI32:
|
||||
zeroInst.AsIconst32(0)
|
||||
case TypeI64:
|
||||
zeroInst.AsIconst64(0)
|
||||
case TypeF32:
|
||||
zeroInst.AsF32const(0)
|
||||
case TypeF64:
|
||||
zeroInst.AsF64const(0)
|
||||
case TypeV128:
|
||||
zeroInst.AsVconst(0, 0)
|
||||
default:
|
||||
panic("TODO: " + t.String())
|
||||
}
|
||||
b.zeros[t] = zeroInst.Insert(b).Return()
|
||||
}
|
||||
|
||||
func (b *builder) VarLengthPool() *wazevoapi.VarLengthPool[Value] {
|
||||
@@ -215,10 +243,12 @@ func (b *builder) ReturnBlock() BasicBlock {
|
||||
func (b *builder) Init(s *Signature) {
|
||||
b.nextVariable = 0
|
||||
b.currentSignature = s
|
||||
b.zeros = [typeEnd]Value{ValueInvalid, ValueInvalid, ValueInvalid, ValueInvalid, ValueInvalid, ValueInvalid}
|
||||
resetBasicBlock(b.returnBlk)
|
||||
b.instructionsPool.Reset()
|
||||
b.basicBlocksPool.Reset()
|
||||
b.varLengthPool.Reset()
|
||||
b.varLengthBasicBlockPool.Reset()
|
||||
b.donePreBlockLayoutPasses = false
|
||||
b.doneBlockLayout = false
|
||||
b.donePostBlockLayoutPasses = false
|
||||
@@ -231,11 +261,6 @@ func (b *builder) Init(s *Signature) {
|
||||
b.blkStack2 = b.blkStack2[:0]
|
||||
b.dominators = b.dominators[:0]
|
||||
b.loopNestingForestRoots = b.loopNestingForestRoots[:0]
|
||||
|
||||
for i := 0; i < b.basicBlocksPool.Allocated(); i++ {
|
||||
blk := b.basicBlocksPool.View(i)
|
||||
delete(b.blkVisited, blk)
|
||||
}
|
||||
b.basicBlocksPool.Reset()
|
||||
|
||||
for v := ValueID(0); v < b.nextValueID; v++ {
|
||||
@@ -448,11 +473,6 @@ func (b *builder) findValueInLinearPath(variable Variable, blk *basicBlock) Valu
|
||||
return ValueInvalid
|
||||
}
|
||||
|
||||
func (b *builder) MustFindValueInBlk(variable Variable, blk BasicBlock) Value {
|
||||
typ := b.definedVariableType(variable)
|
||||
return b.findValue(typ, variable, blk.(*basicBlock))
|
||||
}
|
||||
|
||||
// MustFindValue implements Builder.MustFindValue.
|
||||
func (b *builder) MustFindValue(variable Variable) Value {
|
||||
typ := b.definedVariableType(variable)
|
||||
@@ -482,6 +502,9 @@ func (b *builder) findValue(typ Type, variable Variable, blk *basicBlock) Value
|
||||
value: value,
|
||||
})
|
||||
return value
|
||||
} else if blk.EntryBlock() {
|
||||
// If this is the entry block, we reach the uninitialized variable which has zero value.
|
||||
return b.zeros[b.definedVariableType(variable)]
|
||||
}
|
||||
|
||||
if pred := blk.singlePred; pred != nil {
|
||||
@@ -495,21 +518,42 @@ func (b *builder) findValue(typ Type, variable Variable, blk *basicBlock) Value
|
||||
// If this block has multiple predecessors, we have to gather the definitions,
|
||||
// and treat them as an argument to this block.
|
||||
//
|
||||
// The first thing is to define a new parameter to this block which may or may not be redundant, but
|
||||
// later we eliminate trivial params in an optimization pass. This must be done before finding the
|
||||
// definitions in the predecessors so that we can break the cycle.
|
||||
paramValue := blk.AddParam(b, typ)
|
||||
b.DefineVariable(variable, paramValue, blk)
|
||||
|
||||
// After the new param is added, we have to manipulate the original branching instructions
|
||||
// in predecessors so that they would pass the definition of `variable` as the argument to
|
||||
// the newly added PHI.
|
||||
// But before that, we have to check if the possible definitions are the same Value.
|
||||
tmpValue := b.allocateValue(typ)
|
||||
// Break the cycle by defining the variable with the tmpValue.
|
||||
b.DefineVariable(variable, tmpValue, blk)
|
||||
// Check all the predecessors if they have the same definition.
|
||||
uniqueValue := ValueInvalid
|
||||
for i := range blk.preds {
|
||||
pred := &blk.preds[i]
|
||||
value := b.findValue(typ, variable, pred.blk)
|
||||
pred.branch.addArgumentBranchInst(b, value)
|
||||
predValue := b.findValue(typ, variable, blk.preds[i].blk)
|
||||
if uniqueValue == ValueInvalid {
|
||||
uniqueValue = predValue
|
||||
} else if uniqueValue != predValue {
|
||||
uniqueValue = ValueInvalid
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if uniqueValue != ValueInvalid {
|
||||
// If all the predecessors have the same definition, we can use that value.
|
||||
b.DefineVariable(variable, uniqueValue, blk)
|
||||
b.alias(tmpValue, uniqueValue)
|
||||
return uniqueValue
|
||||
} else {
|
||||
// Otherwise, add the tmpValue to this block as a parameter which may or may not be redundant, but
|
||||
// later we eliminate trivial params in an optimization pass. This must be done before finding the
|
||||
// definitions in the predecessors so that we can break the cycle.
|
||||
blk.addParamOn(tmpValue)
|
||||
// After the new param is added, we have to manipulate the original branching instructions
|
||||
// in predecessors so that they would pass the definition of `variable` as the argument to
|
||||
// the newly added PHI.
|
||||
for i := range blk.preds {
|
||||
pred := &blk.preds[i]
|
||||
value := b.findValue(typ, variable, pred.blk)
|
||||
pred.branch.addArgumentBranchInst(b, value)
|
||||
}
|
||||
return tmpValue
|
||||
}
|
||||
return paramValue
|
||||
}
|
||||
|
||||
// Seal implements Builder.Seal.
|
||||
@@ -523,7 +567,7 @@ func (b *builder) Seal(raw BasicBlock) {
|
||||
for _, v := range blk.unknownValues {
|
||||
variable, phiValue := v.variable, v.value
|
||||
typ := b.definedVariableType(variable)
|
||||
blk.addParamOn(typ, phiValue)
|
||||
blk.addParamOn(phiValue)
|
||||
for i := range blk.preds {
|
||||
pred := &blk.preds[i]
|
||||
predValue := b.findValue(typ, variable, pred.blk)
|
||||
@@ -566,7 +610,7 @@ func (b *builder) Format() string {
|
||||
}
|
||||
for bb := iterBegin(); bb != nil; bb = iterNext() {
|
||||
str.WriteByte('\n')
|
||||
str.WriteString(bb.FormatHeader(b))
|
||||
str.WriteString(bb.formatHeader(b))
|
||||
str.WriteByte('\n')
|
||||
|
||||
for cur := bb.Root(); cur != nil; cur = cur.Next() {
|
||||
|
41
vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/pass.go
generated
vendored
41
vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/pass.go
generated
vendored
@@ -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() {
|
||||
|
16
vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/pass_blk_layouts.go
generated
vendored
16
vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/pass_blk_layouts.go
generated
vendored
@@ -23,8 +23,6 @@ import (
|
||||
//
|
||||
// This heuristic is done in maybeInvertBranches function.
|
||||
func passLayoutBlocks(b *builder) {
|
||||
b.clearBlkVisited()
|
||||
|
||||
// We might end up splitting critical edges which adds more basic blocks,
|
||||
// so we store the currently existing basic blocks in nonSplitBlocks temporarily.
|
||||
// That way we can iterate over the original basic blocks while appending new ones into reversePostOrderedBasicBlocks.
|
||||
@@ -47,20 +45,20 @@ func passLayoutBlocks(b *builder) {
|
||||
for _, blk := range nonSplitBlocks {
|
||||
for i := range blk.preds {
|
||||
pred := blk.preds[i].blk
|
||||
if _, ok := b.blkVisited[pred]; ok || !pred.Valid() {
|
||||
if pred.visited == 1 || !pred.Valid() {
|
||||
continue
|
||||
} else if pred.reversePostOrder < blk.reversePostOrder {
|
||||
// This means the edge is critical, and this pred is the trampoline and yet to be inserted.
|
||||
// Split edge trampolines must come before the destination in reverse post-order.
|
||||
b.reversePostOrderedBasicBlocks = append(b.reversePostOrderedBasicBlocks, pred)
|
||||
b.blkVisited[pred] = 0 // mark as inserted, the value is not used.
|
||||
pred.visited = 1 // mark as inserted.
|
||||
}
|
||||
}
|
||||
|
||||
// Now that we've already added all the potential trampoline blocks incoming to this block,
|
||||
// we can add this block itself.
|
||||
b.reversePostOrderedBasicBlocks = append(b.reversePostOrderedBasicBlocks, blk)
|
||||
b.blkVisited[blk] = 0 // mark as inserted, the value is not used.
|
||||
blk.visited = 1 // mark as inserted.
|
||||
|
||||
if len(blk.success) < 2 {
|
||||
// There won't be critical edge originating from this block.
|
||||
@@ -116,7 +114,7 @@ func passLayoutBlocks(b *builder) {
|
||||
if fallthroughBranch.opcode == OpcodeJump && fallthroughBranch.blk == trampoline {
|
||||
// This can be lowered as fallthrough at the end of the block.
|
||||
b.reversePostOrderedBasicBlocks = append(b.reversePostOrderedBasicBlocks, trampoline)
|
||||
b.blkVisited[trampoline] = 0 // mark as inserted, the value is not used.
|
||||
trampoline.visited = 1 // mark as inserted.
|
||||
} else {
|
||||
uninsertedTrampolines = append(uninsertedTrampolines, trampoline)
|
||||
}
|
||||
@@ -126,7 +124,7 @@ func passLayoutBlocks(b *builder) {
|
||||
if trampoline.success[0].reversePostOrder <= trampoline.reversePostOrder { // "<=", not "<" because the target might be itself.
|
||||
// This means the critical edge was backward, so we insert after the current block immediately.
|
||||
b.reversePostOrderedBasicBlocks = append(b.reversePostOrderedBasicBlocks, trampoline)
|
||||
b.blkVisited[trampoline] = 0 // mark as inserted, the value is not used.
|
||||
trampoline.visited = 1 // mark as inserted.
|
||||
} // If the target is forward, we can wait to insert until the target is inserted.
|
||||
}
|
||||
uninsertedTrampolines = uninsertedTrampolines[:0] // Reuse the stack for the next block.
|
||||
@@ -142,8 +140,8 @@ func passLayoutBlocks(b *builder) {
|
||||
|
||||
if wazevoapi.SSAValidationEnabled {
|
||||
for _, trampoline := range trampolines {
|
||||
if _, ok := b.blkVisited[trampoline]; !ok {
|
||||
panic("BUG: trampoline block not inserted: " + trampoline.FormatHeader(b))
|
||||
if trampoline.visited != 1 {
|
||||
panic("BUG: trampoline block not inserted: " + trampoline.formatHeader(b))
|
||||
}
|
||||
trampoline.validate(b)
|
||||
}
|
||||
|
49
vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/pass_cfg.go
generated
vendored
49
vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/pass_cfg.go
generated
vendored
@@ -15,10 +15,6 @@ import (
|
||||
// At the last of pass, this function also does the loop detection and sets the basicBlock.loop flag.
|
||||
func passCalculateImmediateDominators(b *builder) {
|
||||
reversePostOrder := b.reversePostOrderedBasicBlocks[:0]
|
||||
exploreStack := b.blkStack[:0]
|
||||
b.clearBlkVisited()
|
||||
|
||||
entryBlk := b.entryBlk()
|
||||
|
||||
// Store the reverse postorder from the entrypoint into reversePostOrder slice.
|
||||
// This calculation of reverse postorder is not described in the paper,
|
||||
@@ -28,14 +24,17 @@ func passCalculateImmediateDominators(b *builder) {
|
||||
// which is a reasonable assumption as long as SSA Builder is properly used.
|
||||
//
|
||||
// First we push blocks in postorder iteratively visit successors of the entry block.
|
||||
exploreStack = append(exploreStack, entryBlk)
|
||||
entryBlk := b.entryBlk()
|
||||
exploreStack := append(b.blkStack[:0], entryBlk)
|
||||
// These flags are used to track the state of the block in the DFS traversal.
|
||||
// We temporarily use the reversePostOrder field to store the state.
|
||||
const visitStateUnseen, visitStateSeen, visitStateDone = 0, 1, 2
|
||||
b.blkVisited[entryBlk] = visitStateSeen
|
||||
entryBlk.visited = visitStateSeen
|
||||
for len(exploreStack) > 0 {
|
||||
tail := len(exploreStack) - 1
|
||||
blk := exploreStack[tail]
|
||||
exploreStack = exploreStack[:tail]
|
||||
switch b.blkVisited[blk] {
|
||||
switch blk.visited {
|
||||
case visitStateUnseen:
|
||||
// This is likely a bug in the frontend.
|
||||
panic("BUG: unsupported CFG")
|
||||
@@ -48,16 +47,18 @@ func passCalculateImmediateDominators(b *builder) {
|
||||
if succ.ReturnBlock() || succ.invalid {
|
||||
continue
|
||||
}
|
||||
if b.blkVisited[succ] == visitStateUnseen {
|
||||
b.blkVisited[succ] = visitStateSeen
|
||||
if succ.visited == visitStateUnseen {
|
||||
succ.visited = visitStateSeen
|
||||
exploreStack = append(exploreStack, succ)
|
||||
}
|
||||
}
|
||||
// Finally, we could pop this block once we pop all of its successors.
|
||||
b.blkVisited[blk] = visitStateDone
|
||||
blk.visited = visitStateDone
|
||||
case visitStateDone:
|
||||
// Note: at this point we push blk in postorder despite its name.
|
||||
reversePostOrder = append(reversePostOrder, blk)
|
||||
default:
|
||||
panic("BUG")
|
||||
}
|
||||
}
|
||||
// At this point, reversePostOrder has postorder actually, so we reverse it.
|
||||
@@ -67,7 +68,7 @@ func passCalculateImmediateDominators(b *builder) {
|
||||
}
|
||||
|
||||
for i, blk := range reversePostOrder {
|
||||
blk.reversePostOrder = i
|
||||
blk.reversePostOrder = int32(i)
|
||||
}
|
||||
|
||||
// Reuse the dominators slice if possible from the previous computation of function.
|
||||
@@ -180,7 +181,7 @@ func passBuildLoopNestingForest(b *builder) {
|
||||
b.loopNestingForestRoots = append(b.loopNestingForestRoots, blk)
|
||||
} else if n == ent {
|
||||
} else if n.loopHeader {
|
||||
n.loopNestingForestChildren = append(n.loopNestingForestChildren, blk)
|
||||
n.loopNestingForestChildren = n.loopNestingForestChildren.Append(&b.varLengthBasicBlockPool, blk)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,7 +194,7 @@ func passBuildLoopNestingForest(b *builder) {
|
||||
|
||||
func printLoopNestingForest(root *basicBlock, depth int) {
|
||||
fmt.Println(strings.Repeat("\t", depth), "loop nesting forest root:", root.ID())
|
||||
for _, child := range root.loopNestingForestChildren {
|
||||
for _, child := range root.loopNestingForestChildren.View() {
|
||||
fmt.Println(strings.Repeat("\t", depth+1), "child:", child.ID())
|
||||
if child.LoopHeader() {
|
||||
printLoopNestingForest(child.(*basicBlock), depth+2)
|
||||
@@ -202,10 +203,10 @@ func printLoopNestingForest(root *basicBlock, depth int) {
|
||||
}
|
||||
|
||||
type dominatorSparseTree struct {
|
||||
time int
|
||||
time int32
|
||||
euler []*basicBlock
|
||||
first, depth []int
|
||||
table [][]int
|
||||
first, depth []int32
|
||||
table [][]int32
|
||||
}
|
||||
|
||||
// passBuildDominatorTree builds the dominator tree for the function, and constructs builder.sparseTree.
|
||||
@@ -232,11 +233,11 @@ func passBuildDominatorTree(b *builder) {
|
||||
n := b.basicBlocksPool.Allocated()
|
||||
st := &b.sparseTree
|
||||
st.euler = append(st.euler[:0], make([]*basicBlock, 2*n-1)...)
|
||||
st.first = append(st.first[:0], make([]int, n)...)
|
||||
st.first = append(st.first[:0], make([]int32, n)...)
|
||||
for i := range st.first {
|
||||
st.first[i] = -1
|
||||
}
|
||||
st.depth = append(st.depth[:0], make([]int, 2*n-1)...)
|
||||
st.depth = append(st.depth[:0], make([]int32, 2*n-1)...)
|
||||
st.time = 0
|
||||
|
||||
// Start building the sparse tree.
|
||||
@@ -244,9 +245,9 @@ func passBuildDominatorTree(b *builder) {
|
||||
st.buildSparseTable()
|
||||
}
|
||||
|
||||
func (dt *dominatorSparseTree) eulerTour(node *basicBlock, height int) {
|
||||
func (dt *dominatorSparseTree) eulerTour(node *basicBlock, height int32) {
|
||||
if wazevoapi.SSALoggingEnabled {
|
||||
fmt.Println(strings.Repeat("\t", height), "euler tour:", node.ID())
|
||||
fmt.Println(strings.Repeat("\t", int(height)), "euler tour:", node.ID())
|
||||
}
|
||||
dt.euler[dt.time] = node
|
||||
dt.depth[dt.time] = height
|
||||
@@ -270,13 +271,13 @@ func (dt *dominatorSparseTree) buildSparseTable() {
|
||||
table := dt.table
|
||||
|
||||
if n >= len(table) {
|
||||
table = append(table, make([][]int, n+1)...)
|
||||
table = append(table, make([][]int32, n-len(table)+1)...)
|
||||
}
|
||||
for i := range table {
|
||||
if len(table[i]) < k {
|
||||
table[i] = append(table[i], make([]int, k)...)
|
||||
table[i] = append(table[i], make([]int32, k-len(table[i]))...)
|
||||
}
|
||||
table[i][0] = i
|
||||
table[i][0] = int32(i)
|
||||
}
|
||||
|
||||
for j := 1; 1<<j <= n; j++ {
|
||||
@@ -292,7 +293,7 @@ func (dt *dominatorSparseTree) buildSparseTable() {
|
||||
}
|
||||
|
||||
// rmq performs a range minimum query on the sparse table.
|
||||
func (dt *dominatorSparseTree) rmq(l, r int) int {
|
||||
func (dt *dominatorSparseTree) rmq(l, r int32) int32 {
|
||||
table := dt.table
|
||||
depth := dt.depth
|
||||
j := int(math.Log2(float64(r - l + 1)))
|
||||
|
3
vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/type.go
generated
vendored
3
vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/type.go
generated
vendored
@@ -21,6 +21,9 @@ const (
|
||||
|
||||
// TypeV128 represents 128-bit SIMD vectors.
|
||||
TypeV128
|
||||
|
||||
// -- Do not add new types after this line. ----
|
||||
typeEnd
|
||||
)
|
||||
|
||||
// String implements fmt.Stringer.
|
||||
|
Reference in New Issue
Block a user