mirror of
https://github.com/superseriousbusiness/gotosocial
synced 2025-06-05 21:59:39 +02:00
update go-ffmpreg to v0.2.5 (pulls in latest tetratelabs/wazero) (#3203)
This commit is contained in:
43
vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/basic_block.go
generated
vendored
43
vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/basic_block.go
generated
vendored
@ -34,9 +34,6 @@ type BasicBlock interface {
|
||||
// The returned Value is the definition of the param in this block.
|
||||
Param(i int) Value
|
||||
|
||||
// InsertInstruction inserts an instruction that implements Value into the tail of this block.
|
||||
InsertInstruction(raw *Instruction)
|
||||
|
||||
// Root returns the root instruction of this block.
|
||||
Root() *Instruction
|
||||
|
||||
@ -81,7 +78,7 @@ type (
|
||||
rootInstr, currentInstr *Instruction
|
||||
// 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
|
||||
params Values
|
||||
preds []basicBlockPredecessorInfo
|
||||
success []*basicBlock
|
||||
// singlePred is the alias to preds[0] for fast lookup, and only set after Seal is called.
|
||||
@ -179,23 +176,23 @@ 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, paramValue)
|
||||
bb.params = bb.params.Append(&b.(*builder).varLengthPool, paramValue)
|
||||
return paramValue
|
||||
}
|
||||
|
||||
// addParamOn adds a parameter to this block whose value is already allocated.
|
||||
func (bb *basicBlock) addParamOn(value Value) {
|
||||
bb.params = append(bb.params, value)
|
||||
func (bb *basicBlock) addParamOn(b *builder, value Value) {
|
||||
bb.params = bb.params.Append(&b.varLengthPool, value)
|
||||
}
|
||||
|
||||
// Params implements BasicBlock.Params.
|
||||
func (bb *basicBlock) Params() int {
|
||||
return len(bb.params)
|
||||
return len(bb.params.View())
|
||||
}
|
||||
|
||||
// Param implements BasicBlock.Param.
|
||||
func (bb *basicBlock) Param(i int) Value {
|
||||
return bb.params[i]
|
||||
return bb.params.View()[i]
|
||||
}
|
||||
|
||||
// Valid implements BasicBlock.Valid.
|
||||
@ -208,8 +205,8 @@ func (bb *basicBlock) Sealed() bool {
|
||||
return bb.sealed
|
||||
}
|
||||
|
||||
// InsertInstruction implements BasicBlock.InsertInstruction.
|
||||
func (bb *basicBlock) InsertInstruction(next *Instruction) {
|
||||
// insertInstruction implements BasicBlock.InsertInstruction.
|
||||
func (bb *basicBlock) insertInstruction(b *builder, next *Instruction) {
|
||||
current := bb.currentInstr
|
||||
if current != nil {
|
||||
current.next = next
|
||||
@ -221,12 +218,12 @@ func (bb *basicBlock) InsertInstruction(next *Instruction) {
|
||||
|
||||
switch next.opcode {
|
||||
case OpcodeJump, OpcodeBrz, OpcodeBrnz:
|
||||
target := next.blk.(*basicBlock)
|
||||
target.addPred(bb, next)
|
||||
target := BasicBlockID(next.rValue)
|
||||
b.basicBlock(target).addPred(bb, next)
|
||||
case OpcodeBrTable:
|
||||
for _, _target := range next.targets {
|
||||
target := _target.(*basicBlock)
|
||||
target.addPred(bb, next)
|
||||
for _, _target := range next.rValues.View() {
|
||||
target := BasicBlockID(_target)
|
||||
b.basicBlock(target).addPred(bb, next)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -268,7 +265,7 @@ func (bb *basicBlock) Tail() *Instruction {
|
||||
|
||||
// reset resets the basicBlock to its initial state so that it can be reused for another function.
|
||||
func resetBasicBlock(bb *basicBlock) {
|
||||
bb.params = bb.params[:0]
|
||||
bb.params = ValuesNil
|
||||
bb.rootInstr, bb.currentInstr = nil, nil
|
||||
bb.preds = bb.preds[:0]
|
||||
bb.success = bb.success[:0]
|
||||
@ -310,8 +307,8 @@ func (bb *basicBlock) addPred(blk BasicBlock, branch *Instruction) {
|
||||
|
||||
// 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 := make([]string, len(bb.params.View()))
|
||||
for i, p := range bb.params.View() {
|
||||
ps[i] = p.formatWithType(b)
|
||||
}
|
||||
|
||||
@ -339,7 +336,9 @@ func (bb *basicBlock) validate(b *builder) {
|
||||
if len(bb.preds) > 0 {
|
||||
for _, pred := range bb.preds {
|
||||
if pred.branch.opcode != OpcodeBrTable {
|
||||
if target := pred.branch.blk; target != bb {
|
||||
blockID := int(pred.branch.rValue)
|
||||
target := b.basicBlocksPool.View(blockID)
|
||||
if target != bb {
|
||||
panic(fmt.Sprintf("BUG: '%s' is not branch to %s, but to %s",
|
||||
pred.branch.Format(b), bb.Name(), target.Name()))
|
||||
}
|
||||
@ -349,14 +348,14 @@ func (bb *basicBlock) validate(b *builder) {
|
||||
if bb.ReturnBlock() {
|
||||
exp = len(b.currentSignature.Results)
|
||||
} else {
|
||||
exp = len(bb.params)
|
||||
exp = len(bb.params.View())
|
||||
}
|
||||
|
||||
if len(pred.branch.vs.View()) != exp {
|
||||
panic(fmt.Sprintf(
|
||||
"BUG: len(argument at %s) != len(params at %s): %d != %d: %s",
|
||||
pred.blk.Name(), bb.Name(),
|
||||
len(pred.branch.vs.View()), len(bb.params), pred.branch.Format(b),
|
||||
len(pred.branch.vs.View()), len(bb.params.View()), pred.branch.Format(b),
|
||||
))
|
||||
}
|
||||
|
||||
|
2
vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/basic_block_sort.go
generated
vendored
2
vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/basic_block_sort.go
generated
vendored
@ -1,5 +1,3 @@
|
||||
//go:build go1.21
|
||||
|
||||
package ssa
|
||||
|
||||
import (
|
||||
|
24
vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/basic_block_sort_old.go
generated
vendored
24
vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/basic_block_sort_old.go
generated
vendored
@ -1,24 +0,0 @@
|
||||
//go:build !go1.21
|
||||
|
||||
// TODO: delete after the floor Go version is 1.21
|
||||
|
||||
package ssa
|
||||
|
||||
import "sort"
|
||||
|
||||
func sortBlocks(blocks []*basicBlock) {
|
||||
sort.SliceStable(blocks, func(i, j int) bool {
|
||||
iBlk, jBlk := blocks[i], blocks[j]
|
||||
if jBlk.ReturnBlock() {
|
||||
return true
|
||||
}
|
||||
if iBlk.ReturnBlock() {
|
||||
return false
|
||||
}
|
||||
iRoot, jRoot := iBlk.rootInstr, jBlk.rootInstr
|
||||
if iRoot == nil || jRoot == nil { // For testing.
|
||||
return true
|
||||
}
|
||||
return iBlk.rootInstr.id < jBlk.rootInstr.id
|
||||
})
|
||||
}
|
169
vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/builder.go
generated
vendored
169
vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/builder.go
generated
vendored
@ -94,9 +94,9 @@ type Builder interface {
|
||||
// Returns nil if there's no unseen BasicBlock.
|
||||
BlockIteratorNext() BasicBlock
|
||||
|
||||
// ValueRefCounts returns the map of ValueID to its reference count.
|
||||
// The returned slice must not be modified.
|
||||
ValueRefCounts() []int
|
||||
// ValuesInfo returns the data per Value used to lower the SSA in backend.
|
||||
// This is indexed by ValueID.
|
||||
ValuesInfo() []ValueInfo
|
||||
|
||||
// BlockIteratorReversePostOrderBegin is almost the same as BlockIteratorBegin except it returns the BasicBlock in the reverse post-order.
|
||||
// This is available after RunPasses is run.
|
||||
@ -129,20 +129,24 @@ type Builder interface {
|
||||
|
||||
// InsertZeroValue inserts a zero value constant instruction of the given type.
|
||||
InsertZeroValue(t Type)
|
||||
|
||||
// BasicBlock returns the BasicBlock of the given ID.
|
||||
BasicBlock(id BasicBlockID) BasicBlock
|
||||
|
||||
// InstructionOfValue returns the Instruction that produces the given Value or nil if the Value is not produced by any Instruction.
|
||||
InstructionOfValue(v Value) *Instruction
|
||||
}
|
||||
|
||||
// NewBuilder returns a new Builder implementation.
|
||||
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),
|
||||
valueIDAliases: make(map[ValueID]Value),
|
||||
redundantParameterIndexToValue: make(map[int]Value),
|
||||
returnBlk: &basicBlock{id: basicBlockIDReturnBlock},
|
||||
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),
|
||||
returnBlk: &basicBlock{id: basicBlockIDReturnBlock},
|
||||
}
|
||||
}
|
||||
|
||||
@ -159,19 +163,16 @@ type builder struct {
|
||||
currentBB *basicBlock
|
||||
returnBlk *basicBlock
|
||||
|
||||
// variables track the types for Variable with the index regarded Variable.
|
||||
variables []Type
|
||||
// nextValueID is used by builder.AllocateValue.
|
||||
nextValueID ValueID
|
||||
// nextVariable is used by builder.AllocateVariable.
|
||||
nextVariable Variable
|
||||
|
||||
valueIDAliases map[ValueID]Value
|
||||
// valueAnnotations contains the annotations for each Value, only used for debugging.
|
||||
valueAnnotations map[ValueID]string
|
||||
|
||||
// valueRefCounts is used to lower the SSA in backend, and will be calculated
|
||||
// by the last SSA-level optimization pass.
|
||||
valueRefCounts []int
|
||||
// valuesInfo contains the data per Value used to lower the SSA in backend. This is indexed by ValueID.
|
||||
valuesInfo []ValueInfo
|
||||
|
||||
// dominators stores the immediate dominator of each BasicBlock.
|
||||
// The index is blockID of the BasicBlock.
|
||||
@ -184,12 +185,10 @@ type builder struct {
|
||||
loopNestingForestRoots []BasicBlock
|
||||
|
||||
// The followings are used for optimization passes/deterministic compilation.
|
||||
instStack []*Instruction
|
||||
valueIDToInstruction []*Instruction
|
||||
blkStack []*basicBlock
|
||||
blkStack2 []*basicBlock
|
||||
ints []int
|
||||
redundantParameterIndexToValue map[int]Value
|
||||
instStack []*Instruction
|
||||
blkStack []*basicBlock
|
||||
blkStack2 []*basicBlock
|
||||
redundantParams []redundantParam
|
||||
|
||||
// blockIterCur is used to implement blockIteratorBegin and blockIteratorNext.
|
||||
blockIterCur int
|
||||
@ -207,6 +206,34 @@ type builder struct {
|
||||
zeros [typeEnd]Value
|
||||
}
|
||||
|
||||
// ValueInfo contains the data per Value used to lower the SSA in backend.
|
||||
type ValueInfo struct {
|
||||
// RefCount is the reference count of the Value.
|
||||
RefCount uint32
|
||||
alias Value
|
||||
}
|
||||
|
||||
// redundantParam is a pair of the index of the redundant parameter and the Value.
|
||||
// This is used to eliminate the redundant parameters in the optimization pass.
|
||||
type redundantParam struct {
|
||||
// index is the index of the redundant parameter in the basicBlock.
|
||||
index int
|
||||
// uniqueValue is the Value which is passed to the redundant parameter.
|
||||
uniqueValue Value
|
||||
}
|
||||
|
||||
// BasicBlock implements Builder.BasicBlock.
|
||||
func (b *builder) BasicBlock(id BasicBlockID) BasicBlock {
|
||||
return b.basicBlock(id)
|
||||
}
|
||||
|
||||
func (b *builder) basicBlock(id BasicBlockID) *basicBlock {
|
||||
if id == basicBlockIDReturnBlock {
|
||||
return b.returnBlk
|
||||
}
|
||||
return b.basicBlocksPool.View(int(id))
|
||||
}
|
||||
|
||||
// InsertZeroValue implements Builder.InsertZeroValue.
|
||||
func (b *builder) InsertZeroValue(t Type) {
|
||||
if b.zeros[t].Valid() {
|
||||
@ -256,7 +283,7 @@ func (b *builder) Init(s *Signature) {
|
||||
sig.used = false
|
||||
}
|
||||
|
||||
b.ints = b.ints[:0]
|
||||
b.redundantParams = b.redundantParams[:0]
|
||||
b.blkStack = b.blkStack[:0]
|
||||
b.blkStack2 = b.blkStack2[:0]
|
||||
b.dominators = b.dominators[:0]
|
||||
@ -265,17 +292,11 @@ func (b *builder) Init(s *Signature) {
|
||||
|
||||
for v := ValueID(0); v < b.nextValueID; v++ {
|
||||
delete(b.valueAnnotations, v)
|
||||
delete(b.valueIDAliases, v)
|
||||
b.valueRefCounts[v] = 0
|
||||
b.valueIDToInstruction[v] = nil
|
||||
b.valuesInfo[v] = ValueInfo{alias: ValueInvalid}
|
||||
}
|
||||
b.nextValueID = 0
|
||||
b.reversePostOrderedBasicBlocks = b.reversePostOrderedBasicBlocks[:0]
|
||||
b.doneBlockLayout = false
|
||||
for i := range b.valueRefCounts {
|
||||
b.valueRefCounts[i] = 0
|
||||
}
|
||||
|
||||
b.currentSourceOffset = sourceOffsetUnknown
|
||||
}
|
||||
|
||||
@ -355,7 +376,7 @@ func (b *builder) Idom(blk BasicBlock) BasicBlock {
|
||||
|
||||
// InsertInstruction implements Builder.InsertInstruction.
|
||||
func (b *builder) InsertInstruction(instr *Instruction) {
|
||||
b.currentBB.InsertInstruction(instr)
|
||||
b.currentBB.insertInstruction(b, instr)
|
||||
|
||||
if l := b.currentSourceOffset; l.Valid() {
|
||||
// Emit the source offset info only when the instruction has side effect because
|
||||
@ -377,7 +398,7 @@ func (b *builder) InsertInstruction(instr *Instruction) {
|
||||
}
|
||||
|
||||
r1 := b.allocateValue(t1)
|
||||
instr.rValue = r1
|
||||
instr.rValue = r1.setInstructionID(instr.id)
|
||||
|
||||
tsl := len(ts)
|
||||
if tsl == 0 {
|
||||
@ -386,20 +407,14 @@ func (b *builder) InsertInstruction(instr *Instruction) {
|
||||
|
||||
rValues := b.varLengthPool.Allocate(tsl)
|
||||
for i := 0; i < tsl; i++ {
|
||||
rValues = rValues.Append(&b.varLengthPool, b.allocateValue(ts[i]))
|
||||
rn := b.allocateValue(ts[i])
|
||||
rValues = rValues.Append(&b.varLengthPool, rn.setInstructionID(instr.id))
|
||||
}
|
||||
instr.rValues = rValues
|
||||
}
|
||||
|
||||
// DefineVariable implements Builder.DefineVariable.
|
||||
func (b *builder) DefineVariable(variable Variable, value Value, block BasicBlock) {
|
||||
if b.variables[variable].invalid() {
|
||||
panic("BUG: trying to define variable " + variable.String() + " but is not declared yet")
|
||||
}
|
||||
|
||||
if b.variables[variable] != value.Type() {
|
||||
panic(fmt.Sprintf("BUG: inconsistent type for variable %d: expected %s but got %s", variable, b.variables[variable], value.Type()))
|
||||
}
|
||||
bb := block.(*basicBlock)
|
||||
bb.lastDefinitions[variable] = value
|
||||
}
|
||||
@ -426,20 +441,9 @@ func (b *builder) EntryBlock() BasicBlock {
|
||||
|
||||
// DeclareVariable implements Builder.DeclareVariable.
|
||||
func (b *builder) DeclareVariable(typ Type) Variable {
|
||||
v := b.allocateVariable()
|
||||
iv := int(v)
|
||||
if l := len(b.variables); l <= iv {
|
||||
b.variables = append(b.variables, make([]Type, 2*(l+1))...)
|
||||
}
|
||||
b.variables[v] = typ
|
||||
return v
|
||||
}
|
||||
|
||||
// allocateVariable allocates a new variable.
|
||||
func (b *builder) allocateVariable() (ret Variable) {
|
||||
ret = b.nextVariable
|
||||
v := b.nextVariable
|
||||
b.nextVariable++
|
||||
return
|
||||
return v.setType(typ)
|
||||
}
|
||||
|
||||
// allocateValue implements Builder.AllocateValue.
|
||||
@ -475,8 +479,7 @@ func (b *builder) findValueInLinearPath(variable Variable, blk *basicBlock) Valu
|
||||
|
||||
// MustFindValue implements Builder.MustFindValue.
|
||||
func (b *builder) MustFindValue(variable Variable) Value {
|
||||
typ := b.definedVariableType(variable)
|
||||
return b.findValue(typ, variable, b.currentBB)
|
||||
return b.findValue(variable.getType(), variable, b.currentBB)
|
||||
}
|
||||
|
||||
// findValue recursively tries to find the latest definition of a `variable`. The algorithm is described in
|
||||
@ -504,7 +507,7 @@ func (b *builder) findValue(typ Type, variable Variable, blk *basicBlock) 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)]
|
||||
return b.zeros[variable.getType()]
|
||||
}
|
||||
|
||||
if pred := blk.singlePred; pred != nil {
|
||||
@ -536,14 +539,13 @@ func (b *builder) findValue(typ Type, variable Variable, blk *basicBlock) Value
|
||||
|
||||
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)
|
||||
blk.addParamOn(b, 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.
|
||||
@ -566,8 +568,8 @@ func (b *builder) Seal(raw BasicBlock) {
|
||||
|
||||
for _, v := range blk.unknownValues {
|
||||
variable, phiValue := v.variable, v.value
|
||||
typ := b.definedVariableType(variable)
|
||||
blk.addParamOn(phiValue)
|
||||
typ := variable.getType()
|
||||
blk.addParamOn(b, phiValue)
|
||||
for i := range blk.preds {
|
||||
pred := &blk.preds[i]
|
||||
predValue := b.findValue(typ, variable, pred.blk)
|
||||
@ -579,15 +581,6 @@ func (b *builder) Seal(raw BasicBlock) {
|
||||
}
|
||||
}
|
||||
|
||||
// definedVariableType returns the type of the given variable. If the variable is not defined yet, it panics.
|
||||
func (b *builder) definedVariableType(variable Variable) Type {
|
||||
typ := b.variables[variable]
|
||||
if typ.invalid() {
|
||||
panic(fmt.Sprintf("%s is not defined yet", variable))
|
||||
}
|
||||
return typ
|
||||
}
|
||||
|
||||
// Format implements Builder.Format.
|
||||
func (b *builder) Format() string {
|
||||
str := strings.Builder{}
|
||||
@ -689,15 +682,24 @@ func (b *builder) blockIteratorReversePostOrderNext() *basicBlock {
|
||||
}
|
||||
}
|
||||
|
||||
// ValueRefCounts implements Builder.ValueRefCounts.
|
||||
func (b *builder) ValueRefCounts() []int {
|
||||
return b.valueRefCounts
|
||||
// ValuesInfo implements Builder.ValuesInfo.
|
||||
func (b *builder) ValuesInfo() []ValueInfo {
|
||||
return b.valuesInfo
|
||||
}
|
||||
|
||||
// alias records the alias of the given values. The alias(es) will be
|
||||
// eliminated in the optimization pass via resolveArgumentAlias.
|
||||
func (b *builder) alias(dst, src Value) {
|
||||
b.valueIDAliases[dst.ID()] = src
|
||||
did := int(dst.ID())
|
||||
if did >= len(b.valuesInfo) {
|
||||
l := did + 1 - len(b.valuesInfo)
|
||||
b.valuesInfo = append(b.valuesInfo, make([]ValueInfo, l)...)
|
||||
view := b.valuesInfo[len(b.valuesInfo)-l:]
|
||||
for i := range view {
|
||||
view[i].alias = ValueInvalid
|
||||
}
|
||||
}
|
||||
b.valuesInfo[did].alias = src
|
||||
}
|
||||
|
||||
// resolveArgumentAlias resolves the alias of the arguments of the given instruction.
|
||||
@ -722,10 +724,13 @@ func (b *builder) resolveArgumentAlias(instr *Instruction) {
|
||||
|
||||
// resolveAlias resolves the alias of the given value.
|
||||
func (b *builder) resolveAlias(v Value) Value {
|
||||
info := b.valuesInfo
|
||||
l := ValueID(len(info))
|
||||
// Some aliases are chained, so we need to resolve them recursively.
|
||||
for {
|
||||
if src, ok := b.valueIDAliases[v.ID()]; ok {
|
||||
v = src
|
||||
vid := v.ID()
|
||||
if vid < l && info[vid].alias.Valid() {
|
||||
v = info[vid].alias
|
||||
} else {
|
||||
break
|
||||
}
|
||||
@ -773,3 +778,13 @@ func (b *builder) LoopNestingForestRoots() []BasicBlock {
|
||||
func (b *builder) LowestCommonAncestor(blk1, blk2 BasicBlock) BasicBlock {
|
||||
return b.sparseTree.findLCA(blk1.ID(), blk2.ID())
|
||||
}
|
||||
|
||||
// InstructionOfValue returns the instruction that produces the given Value, or nil
|
||||
// if the Value is not produced by any instruction.
|
||||
func (b *builder) InstructionOfValue(v Value) *Instruction {
|
||||
instrID := v.instructionID()
|
||||
if instrID <= 0 {
|
||||
return nil
|
||||
}
|
||||
return b.instructionsPool.View(instrID - 1)
|
||||
}
|
||||
|
47
vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/instructions.go
generated
vendored
47
vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/instructions.go
generated
vendored
@ -25,11 +25,13 @@ type Instruction struct {
|
||||
v3 Value
|
||||
vs Values
|
||||
typ Type
|
||||
blk BasicBlock
|
||||
targets []BasicBlock
|
||||
prev, next *Instruction
|
||||
|
||||
rValue Value
|
||||
// rValue is the (first) return value of this instruction.
|
||||
// For branching instructions except for OpcodeBrTable, they hold BlockID to jump cast to Value.
|
||||
rValue Value
|
||||
// rValues are the rest of the return values of this instruction.
|
||||
// For OpcodeBrTable, it holds the list of BlockID to jump cast to Value.
|
||||
rValues Values
|
||||
gid InstructionGroupID
|
||||
sourceOffset SourceOffset
|
||||
@ -105,6 +107,9 @@ type InstructionGroupID uint32
|
||||
// Returns Value(s) produced by this instruction if any.
|
||||
// The `first` is the first return value, and `rest` is the rest of the values.
|
||||
func (i *Instruction) Returns() (first Value, rest []Value) {
|
||||
if i.IsBranching() {
|
||||
return ValueInvalid, nil
|
||||
}
|
||||
return i.rValue, i.rValues.View()
|
||||
}
|
||||
|
||||
@ -2077,7 +2082,7 @@ func (i *Instruction) InvertBrx() {
|
||||
}
|
||||
|
||||
// BranchData returns the branch data for this instruction necessary for backends.
|
||||
func (i *Instruction) BranchData() (condVal Value, blockArgs []Value, target BasicBlock) {
|
||||
func (i *Instruction) BranchData() (condVal Value, blockArgs []Value, target BasicBlockID) {
|
||||
switch i.opcode {
|
||||
case OpcodeJump:
|
||||
condVal = ValueInvalid
|
||||
@ -2087,17 +2092,17 @@ func (i *Instruction) BranchData() (condVal Value, blockArgs []Value, target Bas
|
||||
panic("BUG")
|
||||
}
|
||||
blockArgs = i.vs.View()
|
||||
target = i.blk
|
||||
target = BasicBlockID(i.rValue)
|
||||
return
|
||||
}
|
||||
|
||||
// BrTableData returns the branch table data for this instruction necessary for backends.
|
||||
func (i *Instruction) BrTableData() (index Value, targets []BasicBlock) {
|
||||
func (i *Instruction) BrTableData() (index Value, targets Values) {
|
||||
if i.opcode != OpcodeBrTable {
|
||||
panic("BUG: BrTableData only available for OpcodeBrTable")
|
||||
}
|
||||
index = i.v
|
||||
targets = i.targets
|
||||
targets = i.rValues
|
||||
return
|
||||
}
|
||||
|
||||
@ -2105,7 +2110,7 @@ func (i *Instruction) BrTableData() (index Value, targets []BasicBlock) {
|
||||
func (i *Instruction) AsJump(vs Values, target BasicBlock) *Instruction {
|
||||
i.opcode = OpcodeJump
|
||||
i.vs = vs
|
||||
i.blk = target
|
||||
i.rValue = Value(target.ID())
|
||||
return i
|
||||
}
|
||||
|
||||
@ -2130,7 +2135,7 @@ func (i *Instruction) AsBrz(v Value, args Values, target BasicBlock) {
|
||||
i.opcode = OpcodeBrz
|
||||
i.v = v
|
||||
i.vs = args
|
||||
i.blk = target
|
||||
i.rValue = Value(target.ID())
|
||||
}
|
||||
|
||||
// AsBrnz initializes this instruction as a branch-if-not-zero instruction with OpcodeBrnz.
|
||||
@ -2138,15 +2143,16 @@ func (i *Instruction) AsBrnz(v Value, args Values, target BasicBlock) *Instructi
|
||||
i.opcode = OpcodeBrnz
|
||||
i.v = v
|
||||
i.vs = args
|
||||
i.blk = target
|
||||
i.rValue = Value(target.ID())
|
||||
return i
|
||||
}
|
||||
|
||||
// AsBrTable initializes this instruction as a branch-table instruction with OpcodeBrTable.
|
||||
func (i *Instruction) AsBrTable(index Value, targets []BasicBlock) {
|
||||
// targets is a list of basic block IDs cast to Values.
|
||||
func (i *Instruction) AsBrTable(index Value, targets Values) {
|
||||
i.opcode = OpcodeBrTable
|
||||
i.v = index
|
||||
i.targets = targets
|
||||
i.rValues = targets
|
||||
}
|
||||
|
||||
// AsCall initializes this instruction as a call instruction with OpcodeCall.
|
||||
@ -2531,7 +2537,8 @@ func (i *Instruction) Format(b Builder) string {
|
||||
if i.IsFallthroughJump() {
|
||||
vs[0] = " fallthrough"
|
||||
} else {
|
||||
vs[0] = " " + i.blk.(*basicBlock).Name()
|
||||
blockId := BasicBlockID(i.rValue)
|
||||
vs[0] = " " + b.BasicBlock(blockId).Name()
|
||||
}
|
||||
for idx := range view {
|
||||
vs[idx+1] = view[idx].Format(b)
|
||||
@ -2542,7 +2549,8 @@ func (i *Instruction) Format(b Builder) string {
|
||||
view := i.vs.View()
|
||||
vs := make([]string, len(view)+2)
|
||||
vs[0] = " " + i.v.Format(b)
|
||||
vs[1] = i.blk.(*basicBlock).Name()
|
||||
blockId := BasicBlockID(i.rValue)
|
||||
vs[1] = b.BasicBlock(blockId).Name()
|
||||
for idx := range view {
|
||||
vs[idx+2] = view[idx].Format(b)
|
||||
}
|
||||
@ -2551,8 +2559,8 @@ func (i *Instruction) Format(b Builder) string {
|
||||
// `BrTable index, [label1, label2, ... labelN]`
|
||||
instSuffix = fmt.Sprintf(" %s", i.v.Format(b))
|
||||
instSuffix += ", ["
|
||||
for i, target := range i.targets {
|
||||
blk := target.(*basicBlock)
|
||||
for i, target := range i.rValues.View() {
|
||||
blk := b.BasicBlock(BasicBlockID(target))
|
||||
if i == 0 {
|
||||
instSuffix += blk.Name()
|
||||
} else {
|
||||
@ -2621,11 +2629,12 @@ func (i *Instruction) Format(b Builder) string {
|
||||
instr := i.opcode.String() + instSuffix
|
||||
|
||||
var rvs []string
|
||||
if rv := i.rValue; rv.Valid() {
|
||||
rvs = append(rvs, rv.formatWithType(b))
|
||||
r1, rs := i.Returns()
|
||||
if r1.Valid() {
|
||||
rvs = append(rvs, r1.formatWithType(b))
|
||||
}
|
||||
|
||||
for _, v := range i.rValues.View() {
|
||||
for _, v := range rs {
|
||||
rvs = append(rvs, v.formatWithType(b))
|
||||
}
|
||||
|
||||
|
105
vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/pass.go
generated
vendored
105
vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/pass.go
generated
vendored
@ -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
|
||||
|
19
vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/pass_blk_layouts.go
generated
vendored
19
vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/pass_blk_layouts.go
generated
vendored
@ -33,7 +33,7 @@ func passLayoutBlocks(b *builder) {
|
||||
}
|
||||
nonSplitBlocks = append(nonSplitBlocks, blk)
|
||||
if i != len(b.reversePostOrderedBasicBlocks)-1 {
|
||||
_ = maybeInvertBranches(blk, b.reversePostOrderedBasicBlocks[i+1])
|
||||
_ = maybeInvertBranches(b, blk, b.reversePostOrderedBasicBlocks[i+1])
|
||||
}
|
||||
}
|
||||
|
||||
@ -111,7 +111,7 @@ func passLayoutBlocks(b *builder) {
|
||||
}
|
||||
|
||||
fallthroughBranch := blk.currentInstr
|
||||
if fallthroughBranch.opcode == OpcodeJump && fallthroughBranch.blk == trampoline {
|
||||
if fallthroughBranch.opcode == OpcodeJump && BasicBlockID(fallthroughBranch.rValue) == trampoline.id {
|
||||
// This can be lowered as fallthrough at the end of the block.
|
||||
b.reversePostOrderedBasicBlocks = append(b.reversePostOrderedBasicBlocks, trampoline)
|
||||
trampoline.visited = 1 // mark as inserted.
|
||||
@ -157,7 +157,7 @@ func (b *builder) markFallthroughJumps() {
|
||||
for i, blk := range b.reversePostOrderedBasicBlocks {
|
||||
if i < l {
|
||||
cur := blk.currentInstr
|
||||
if cur.opcode == OpcodeJump && cur.blk == b.reversePostOrderedBasicBlocks[i+1] {
|
||||
if cur.opcode == OpcodeJump && BasicBlockID(cur.rValue) == b.reversePostOrderedBasicBlocks[i+1].id {
|
||||
cur.AsFallthroughJump()
|
||||
}
|
||||
}
|
||||
@ -168,7 +168,7 @@ func (b *builder) markFallthroughJumps() {
|
||||
// nextInRPO is the next block in the reverse post-order.
|
||||
//
|
||||
// Returns true if the branch is inverted for testing purpose.
|
||||
func maybeInvertBranches(now *basicBlock, nextInRPO *basicBlock) bool {
|
||||
func maybeInvertBranches(b *builder, now *basicBlock, nextInRPO *basicBlock) bool {
|
||||
fallthroughBranch := now.currentInstr
|
||||
if fallthroughBranch.opcode == OpcodeBrTable {
|
||||
return false
|
||||
@ -187,7 +187,8 @@ func maybeInvertBranches(now *basicBlock, nextInRPO *basicBlock) bool {
|
||||
// So this block has two branches (a conditional branch followed by an unconditional branch) at the end.
|
||||
// We can invert the condition of the branch if it makes the fallthrough more likely.
|
||||
|
||||
fallthroughTarget, condTarget := fallthroughBranch.blk.(*basicBlock), condBranch.blk.(*basicBlock)
|
||||
fallthroughTarget := b.basicBlock(BasicBlockID(fallthroughBranch.rValue))
|
||||
condTarget := b.basicBlock(BasicBlockID(condBranch.rValue))
|
||||
|
||||
if fallthroughTarget.loopHeader {
|
||||
// First, if the tail's target is loopHeader, we don't need to do anything here,
|
||||
@ -231,8 +232,8 @@ invert:
|
||||
}
|
||||
|
||||
condBranch.InvertBrx()
|
||||
condBranch.blk = fallthroughTarget
|
||||
fallthroughBranch.blk = condTarget
|
||||
condBranch.rValue = Value(fallthroughTarget.ID())
|
||||
fallthroughBranch.rValue = Value(condTarget.ID())
|
||||
if wazevoapi.SSALoggingEnabled {
|
||||
fmt.Printf("inverting branches at %d->%d and %d->%d\n",
|
||||
now.ID(), fallthroughTarget.ID(), now.ID(), condTarget.ID())
|
||||
@ -275,7 +276,7 @@ func (b *builder) splitCriticalEdge(pred, succ *basicBlock, predInfo *basicBlock
|
||||
// Replace originalBranch with the newBranch.
|
||||
newBranch := b.AllocateInstruction()
|
||||
newBranch.opcode = originalBranch.opcode
|
||||
newBranch.blk = trampoline
|
||||
newBranch.rValue = Value(trampoline.ID())
|
||||
switch originalBranch.opcode {
|
||||
case OpcodeJump:
|
||||
case OpcodeBrz, OpcodeBrnz:
|
||||
@ -303,7 +304,7 @@ func (b *builder) splitCriticalEdge(pred, succ *basicBlock, predInfo *basicBlock
|
||||
trampoline.validate(b)
|
||||
}
|
||||
|
||||
if len(trampoline.params) > 0 {
|
||||
if len(trampoline.params.View()) > 0 {
|
||||
panic("trampoline should not have params")
|
||||
}
|
||||
|
||||
|
39
vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/vs.go
generated
vendored
39
vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/vs.go
generated
vendored
@ -15,17 +15,31 @@ import (
|
||||
//
|
||||
// Variable is useful to track the SSA Values of a variable in the source program, and
|
||||
// can be used to find the corresponding latest SSA Value via Builder.FindValue.
|
||||
//
|
||||
// Higher 4-bit is used to store Type for this variable.
|
||||
type Variable uint32
|
||||
|
||||
// String implements fmt.Stringer.
|
||||
func (v Variable) String() string {
|
||||
return fmt.Sprintf("var%d", v)
|
||||
return fmt.Sprintf("var%d", v&0x0fffffff)
|
||||
}
|
||||
|
||||
func (v Variable) setType(typ Type) Variable {
|
||||
if v >= 1<<28 {
|
||||
panic(fmt.Sprintf("Too large variable: %d", v))
|
||||
}
|
||||
return Variable(typ)<<28 | v
|
||||
}
|
||||
|
||||
func (v Variable) getType() Type {
|
||||
return Type(v >> 28)
|
||||
}
|
||||
|
||||
// Value represents an SSA value with a type information. The relationship with Variable is 1: N (including 0),
|
||||
// that means there might be multiple Variable(s) for a Value.
|
||||
//
|
||||
// Higher 32-bit is used to store Type for this value.
|
||||
// 32 to 59-bit is used to store the unique identifier of the Instruction that generates this value if any.
|
||||
// 60 to 63-bit is used to store Type for this value.
|
||||
type Value uint64
|
||||
|
||||
// ValueID is the lower 32bit of Value, which is the pure identifier of Value without type info.
|
||||
@ -33,7 +47,7 @@ type ValueID uint32
|
||||
|
||||
const (
|
||||
valueIDInvalid ValueID = math.MaxUint32
|
||||
ValueInvalid Value = Value(valueIDInvalid)
|
||||
ValueInvalid = Value(valueIDInvalid)
|
||||
)
|
||||
|
||||
// Format creates a debug string for this Value using the data stored in Builder.
|
||||
@ -54,7 +68,7 @@ func (v Value) formatWithType(b Builder) (ret string) {
|
||||
if wazevoapi.SSALoggingEnabled { // This is useful to check live value analysis bugs.
|
||||
if bd := b.(*builder); bd.donePostBlockLayoutPasses {
|
||||
id := v.ID()
|
||||
ret += fmt.Sprintf("(ref=%d)", bd.valueRefCounts[id])
|
||||
ret += fmt.Sprintf("(ref=%d)", bd.valuesInfo[id].RefCount)
|
||||
}
|
||||
}
|
||||
return ret
|
||||
@ -67,7 +81,7 @@ func (v Value) Valid() bool {
|
||||
|
||||
// Type returns the Type of this value.
|
||||
func (v Value) Type() Type {
|
||||
return Type(v >> 32)
|
||||
return Type(v >> 60)
|
||||
}
|
||||
|
||||
// ID returns the valueID of this value.
|
||||
@ -77,7 +91,20 @@ func (v Value) ID() ValueID {
|
||||
|
||||
// setType sets a type to this Value and returns the updated Value.
|
||||
func (v Value) setType(typ Type) Value {
|
||||
return v | Value(typ)<<32
|
||||
return v | Value(typ)<<60
|
||||
}
|
||||
|
||||
// setInstructionID sets an Instruction.id to this Value and returns the updated Value.
|
||||
func (v Value) setInstructionID(id int) Value {
|
||||
if id < 0 || uint(id) >= 1<<28 {
|
||||
panic(fmt.Sprintf("Too large instruction ID: %d", id))
|
||||
}
|
||||
return v | Value(id)<<32
|
||||
}
|
||||
|
||||
// instructionID() returns the Instruction.id of this Value.
|
||||
func (v Value) instructionID() int {
|
||||
return int(v>>32) & 0x0fffffff
|
||||
}
|
||||
|
||||
// Values is a slice of Value. Use this instead of []Value to reuse the underlying memory.
|
||||
|
Reference in New Issue
Block a user