wazevo: removes unused SSA insts, centralizes debug toggles (#1671)
Signed-off-by: Takeshi Yoneda <t.y.mathetake@gmail.com>
This commit is contained in:
@@ -5,6 +5,7 @@ import (
|
||||
|
||||
"github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc"
|
||||
"github.com/tetratelabs/wazero/internal/engine/wazevo/ssa"
|
||||
"github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi"
|
||||
)
|
||||
|
||||
// NewCompiler returns a new Compiler that can generate a machine code.
|
||||
@@ -143,15 +144,15 @@ type compiler struct {
|
||||
// Compile implements Compiler.Compile.
|
||||
func (c *compiler) Compile() ([]byte, []RelocationInfo, int, error) {
|
||||
c.Lower()
|
||||
if false {
|
||||
if wazevoapi.PrintSSAToBackendIRLowering {
|
||||
fmt.Printf("[[[after lowering]]]%s\n", c.Format())
|
||||
}
|
||||
c.RegAlloc()
|
||||
if false {
|
||||
if wazevoapi.PrintRegisterAllocated {
|
||||
fmt.Printf("[[[after regalloc]]]%s\n", c.Format())
|
||||
}
|
||||
c.Finalize()
|
||||
if false {
|
||||
if wazevoapi.PrintFinalizedMachineCode {
|
||||
fmt.Printf("[[[after finalize]]]%s\n", c.Format())
|
||||
}
|
||||
goPreambleSize := c.Encode()
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package backend
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc"
|
||||
"github.com/tetratelabs/wazero/internal/engine/wazevo/ssa"
|
||||
)
|
||||
@@ -16,15 +14,10 @@ func (c *compiler) Lower() {
|
||||
c.mach.EndLoweringFunction()
|
||||
}
|
||||
|
||||
const debug = false
|
||||
|
||||
// lowerBlocks lowers each block in the ssa.Builder.
|
||||
func (c *compiler) lowerBlocks() {
|
||||
builder := c.ssaBuilder
|
||||
for blk := builder.BlockIteratorReversePostOrderBegin(); blk != nil; blk = builder.BlockIteratorReversePostOrderNext() {
|
||||
if debug {
|
||||
fmt.Printf("lowering block %s\n", blk.Name())
|
||||
}
|
||||
c.lowerBlock(blk)
|
||||
}
|
||||
// After lowering all blocks, we need to link adjacent blocks to layout one single instruction list.
|
||||
@@ -71,10 +64,6 @@ func (c *compiler) lowerBlock(blk ssa.BasicBlock) {
|
||||
continue
|
||||
}
|
||||
|
||||
if debug {
|
||||
fmt.Printf("\tlowering instr %s\n", cur.Format(c.ssaBuilder))
|
||||
}
|
||||
|
||||
switch cur.Opcode() {
|
||||
case ssa.OpcodeReturn:
|
||||
c.lowerFunctionReturns(cur.ReturnVals())
|
||||
|
||||
@@ -3,6 +3,8 @@ package regalloc
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
|
||||
"github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi"
|
||||
)
|
||||
|
||||
// assignRegisters assigns real registers to virtual registers on each instruction.
|
||||
@@ -20,7 +22,7 @@ func (a *Allocator) assignRegisters(f Function) {
|
||||
|
||||
// assignRegistersPerBlock assigns real registers to virtual registers on each instruction in a block.
|
||||
func (a *Allocator) assignRegistersPerBlock(f Function, blk Block, vRegIDToNode []*node, liveNodes []liveNodeInBlock) {
|
||||
if debug {
|
||||
if wazevoapi.RegAllocLoggingEnabled {
|
||||
fmt.Println("---------------------- assigning registers for block", blk.ID(), "----------------------")
|
||||
}
|
||||
|
||||
@@ -59,7 +61,7 @@ func (a *Allocator) assignRegistersPerInstr(f Function, pc programCounter, instr
|
||||
a.vs = append(a.vs, u)
|
||||
continue
|
||||
}
|
||||
if false {
|
||||
if wazevoapi.RegAllocLoggingEnabled {
|
||||
fmt.Printf("%s uses %d\n", instr, u.ID())
|
||||
}
|
||||
n := vRegIDToNode[u.ID()]
|
||||
@@ -90,7 +92,7 @@ func (a *Allocator) assignRegistersPerInstr(f Function, pc programCounter, instr
|
||||
if d.IsRealReg() {
|
||||
return
|
||||
}
|
||||
if false {
|
||||
if wazevoapi.RegAllocLoggingEnabled {
|
||||
fmt.Printf("%s defines %d\n", instr, d.ID())
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@ package regalloc
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
|
||||
"github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi"
|
||||
)
|
||||
|
||||
// buildNeighbors builds the neighbors for each node in the interference graph.
|
||||
@@ -87,7 +89,7 @@ func (a *Allocator) coloringFor(allocatable []RealReg) {
|
||||
return currentDegrees[degreeSortedNodes[i]] < currentDegrees[degreeSortedNodes[j]]
|
||||
})
|
||||
|
||||
if debug {
|
||||
if wazevoapi.RegAllocLoggingEnabled {
|
||||
fmt.Println("-------------------------------")
|
||||
fmt.Printf("coloringStack: ")
|
||||
for _, c := range coloringStack {
|
||||
@@ -122,7 +124,7 @@ func (a *Allocator) coloringFor(allocatable []RealReg) {
|
||||
degreeSortedNodes[0], degreeSortedNodes[tail] = degreeSortedNodes[tail], degreeSortedNodes[0]
|
||||
|
||||
popNum++
|
||||
if debug {
|
||||
if wazevoapi.RegAllocLoggingEnabled {
|
||||
fmt.Printf("Forcibly pop one node %s as a spill target\n", degreeSortedNodes[0].v)
|
||||
}
|
||||
}
|
||||
@@ -139,7 +141,7 @@ func (a *Allocator) coloringFor(allocatable []RealReg) {
|
||||
}
|
||||
}
|
||||
|
||||
if debug {
|
||||
if wazevoapi.RegAllocLoggingEnabled {
|
||||
if len(coloringStack) == total {
|
||||
fmt.Println("-------------------------------")
|
||||
fmt.Printf("coloringStack: ")
|
||||
@@ -159,10 +161,13 @@ func (a *Allocator) coloringFor(allocatable []RealReg) {
|
||||
}
|
||||
}
|
||||
|
||||
if debug {
|
||||
if wazevoapi.RegAllocValidationEnabled {
|
||||
if len(degreeSortedNodes) != 0 {
|
||||
panic("BUG")
|
||||
}
|
||||
}
|
||||
|
||||
if wazevoapi.RegAllocLoggingEnabled {
|
||||
fmt.Println("-------------------------------")
|
||||
}
|
||||
|
||||
@@ -177,7 +182,7 @@ func (a *Allocator) coloringFor(allocatable []RealReg) {
|
||||
continue
|
||||
}
|
||||
|
||||
if debug {
|
||||
if wazevoapi.RegAllocLoggingEnabled {
|
||||
fmt.Printf("coloring %s\n", n)
|
||||
}
|
||||
|
||||
@@ -189,13 +194,13 @@ func (a *Allocator) coloringFor(allocatable []RealReg) {
|
||||
}
|
||||
}
|
||||
|
||||
if debug {
|
||||
if wazevoapi.RegAllocLoggingEnabled {
|
||||
fmt.Printf("\tneighborColors: %v\n", neighborColors)
|
||||
}
|
||||
|
||||
a.assignColor(n, neighborColorsSet, allocatable)
|
||||
|
||||
if debug {
|
||||
if wazevoapi.RegAllocLoggingEnabled {
|
||||
fmt.Printf("\tassigned color: %s\n", n.r)
|
||||
}
|
||||
|
||||
@@ -206,7 +211,7 @@ func (a *Allocator) coloringFor(allocatable []RealReg) {
|
||||
neighborColors = neighborColors[:0]
|
||||
}
|
||||
|
||||
if debug {
|
||||
if wazevoapi.RegAllocValidationEnabled {
|
||||
for _, n := range coloringStack {
|
||||
if n.r == RealRegInvalid {
|
||||
continue
|
||||
|
||||
@@ -17,8 +17,6 @@ import (
|
||||
"github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi"
|
||||
)
|
||||
|
||||
const debug = false
|
||||
|
||||
// NewAllocator returns a new Allocator.
|
||||
func NewAllocator(allocatableRegs *RegisterInfo) Allocator {
|
||||
a := Allocator{
|
||||
@@ -204,7 +202,7 @@ func (a *Allocator) livenessAnalysis(f Function) {
|
||||
pc += pcStride
|
||||
}
|
||||
|
||||
if debug {
|
||||
if wazevoapi.RegAllocLoggingEnabled {
|
||||
fmt.Printf("constructed block info for block[%d]:\n%s\n\n", blkID, info)
|
||||
}
|
||||
}
|
||||
@@ -241,7 +239,7 @@ func (a *Allocator) livenessAnalysis(f Function) {
|
||||
}
|
||||
}
|
||||
|
||||
if debug {
|
||||
if wazevoapi.RegAllocLoggingEnabled {
|
||||
fmt.Printf("\nfinalized info for block[%d]:\n%s\n", blk.ID(), info)
|
||||
}
|
||||
}
|
||||
@@ -252,7 +250,7 @@ func (a *Allocator) livenessAnalysis(f Function) {
|
||||
//
|
||||
// We recursively call this, so passing `depth` for debugging.
|
||||
func (a *Allocator) upAndMarkStack(b Block, v VReg, depth int) {
|
||||
if debug {
|
||||
if wazevoapi.RegAllocLoggingEnabled {
|
||||
fmt.Printf("%supAndMarkStack for %v at %v\n", strings.Repeat("\t", depth), v, b.ID())
|
||||
}
|
||||
|
||||
@@ -264,7 +262,7 @@ func (a *Allocator) upAndMarkStack(b Block, v VReg, depth int) {
|
||||
if _, ok := info.liveIns[v]; ok {
|
||||
return // But this case, it is already visited. (maybe by, for example, sibling blocks).
|
||||
}
|
||||
if debug {
|
||||
if wazevoapi.RegAllocLoggingEnabled {
|
||||
fmt.Printf("%sadding %v live-in at block[%d]\n", strings.Repeat("\t", depth), v, b.ID())
|
||||
}
|
||||
|
||||
@@ -277,7 +275,7 @@ func (a *Allocator) upAndMarkStack(b Block, v VReg, depth int) {
|
||||
|
||||
// and climb up the CFG.
|
||||
for _, pred := range preds {
|
||||
if debug {
|
||||
if wazevoapi.RegAllocLoggingEnabled {
|
||||
fmt.Printf("%sadding %v live-out at block[%d]\n", strings.Repeat("\t", depth+1), v, pred.ID())
|
||||
}
|
||||
a.blockInfoAt(pred.ID()).liveOuts[v] = struct{}{}
|
||||
@@ -369,7 +367,7 @@ func (a *Allocator) buildLiveRangesForNonReals(blkID int, info *blockInfo) {
|
||||
// Reuse for the next block.
|
||||
a.vs = vs[:0]
|
||||
|
||||
if debug {
|
||||
if wazevoapi.RegAllocValidationEnabled {
|
||||
for u := range kills {
|
||||
if !u.IsRealReg() {
|
||||
_, defined := defs[u]
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/tetratelabs/wazero/api"
|
||||
@@ -110,12 +109,6 @@ func (e *engine) CompileModule(_ context.Context, module *wasm.Module, _ []exper
|
||||
fidx := wasm.Index(i + importedFns)
|
||||
fref := frontend.FunctionIndexToFuncRef(fidx)
|
||||
|
||||
const debug = false
|
||||
if debug {
|
||||
name := exportedFnIndex[fidx]
|
||||
fmt.Printf("%[1]s %d/%d %s %[1]s\n", strings.Repeat("-", 30), i, len(module.CodeSection)-1, name)
|
||||
}
|
||||
|
||||
_, needGoEntryPreamble := exportedFnIndex[fidx]
|
||||
if sf := module.StartSection; sf != nil && *sf == fidx {
|
||||
needGoEntryPreamble = true
|
||||
@@ -166,22 +159,22 @@ func (e *engine) CompileModule(_ context.Context, module *wasm.Module, _ []exper
|
||||
return fmt.Errorf("wasm->ssa: %v", err)
|
||||
}
|
||||
|
||||
if debug {
|
||||
fmt.Printf("[[[SSA]]]%s\n", ssaBuilder.Format())
|
||||
if wazevoapi.PrintSSA {
|
||||
fmt.Printf("[[[SSA for %d/%d %s]]]%s\n", i, len(module.CodeSection)-1, exportedFnIndex[fidx], ssaBuilder.Format())
|
||||
}
|
||||
|
||||
// Run SSA-level optimization passes.
|
||||
ssaBuilder.RunPasses()
|
||||
|
||||
if debug {
|
||||
fmt.Printf("[[[optimized SSA]]]%s\n", ssaBuilder.Format())
|
||||
if wazevoapi.PrintOptimizedSSA {
|
||||
fmt.Printf("[[[optimized SSA for %d/%d %s]]]%s\n", i, len(module.CodeSection)-1, exportedFnIndex[fidx], ssaBuilder.Format())
|
||||
}
|
||||
|
||||
// Finalize the layout of SSA blocks which might use the optimization results.
|
||||
ssaBuilder.LayoutBlocks()
|
||||
|
||||
if debug {
|
||||
fmt.Printf("[[[laidout SSA]]]%s\n", ssaBuilder.Format())
|
||||
if wazevoapi.PrintBlockLaidOutSSA {
|
||||
fmt.Printf("[[[laidout SSA for %d/%d %s]]]%s\n", i, len(module.CodeSection)-1, exportedFnIndex[fidx], ssaBuilder.Format())
|
||||
}
|
||||
|
||||
// Now our ssaBuilder contains the necessary information to further lower them to
|
||||
@@ -210,7 +203,7 @@ func (e *engine) CompileModule(_ context.Context, module *wasm.Module, _ []exper
|
||||
copy(copied, body)
|
||||
bodies[i] = copied
|
||||
totalSize += len(body)
|
||||
if debug {
|
||||
if wazevoapi.PrintMachineCodeHexPerFunction {
|
||||
fmt.Println(hex.EncodeToString(body))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,8 +126,6 @@ func (l *loweringState) ctrlPeekAt(n int) (ret *controlFrame) {
|
||||
return &l.controlFrames[tail-n]
|
||||
}
|
||||
|
||||
const debug = false
|
||||
|
||||
// lowerBody lowers the body of the Wasm function to the SSA form.
|
||||
func (c *Compiler) lowerBody(entryBlk ssa.BasicBlock) {
|
||||
c.ssaBuilder.Seal(entryBlk)
|
||||
@@ -142,7 +140,7 @@ func (c *Compiler) lowerBody(entryBlk ssa.BasicBlock) {
|
||||
for c.loweringState.pc < len(c.wasmFunctionBody) {
|
||||
op := c.wasmFunctionBody[c.loweringState.pc]
|
||||
c.lowerOpcode(op)
|
||||
if debug {
|
||||
if wazevoapi.FrontEndLoggingEnabled {
|
||||
fmt.Println("--------- Translated " + wasm.InstructionName(op) + " --------")
|
||||
fmt.Println("state: " + c.loweringState.String())
|
||||
fmt.Println(c.formatBuilder())
|
||||
@@ -693,9 +691,6 @@ func (c *Compiler) lowerOpcode(op wasm.Opcode) {
|
||||
}
|
||||
variable := c.localVariable(index)
|
||||
v := builder.MustFindValue(variable)
|
||||
if false {
|
||||
builder.AnnotateValue(v, fmt.Sprintf("v%d@local[%d]", v.ID(), index))
|
||||
}
|
||||
state.push(v)
|
||||
case wasm.OpcodeLocalSet:
|
||||
index := c.readI32u()
|
||||
|
||||
@@ -418,7 +418,7 @@ func (b *builder) findValue(typ Type, variable Variable, blk *basicBlock) Value
|
||||
// and record it as unknown.
|
||||
// The unknown values are resolved when we call seal this block via BasicBlock.Seal().
|
||||
value := b.allocateValue(typ)
|
||||
if debug {
|
||||
if wazevoapi.SSALoggingEnabled {
|
||||
fmt.Printf("adding unknown value placeholder for %s at %d\n", variable, blk.id)
|
||||
}
|
||||
blk.lastDefinitions[variable] = value
|
||||
@@ -700,7 +700,7 @@ func (b *builder) LayoutBlocks() {
|
||||
}
|
||||
}
|
||||
|
||||
trampolines := []*basicBlock{}
|
||||
var trampolines []*basicBlock
|
||||
|
||||
// Reset the order slice since we update on the fly by splitting critical edges.
|
||||
b.reversePostOrderedBasicBlocks = b.reversePostOrderedBasicBlocks[:0]
|
||||
@@ -754,7 +754,7 @@ func (b *builder) LayoutBlocks() {
|
||||
panic("BUG: predecessor info not found while the successor exists in successors list")
|
||||
}
|
||||
|
||||
if debug {
|
||||
if wazevoapi.SSALoggingEnabled {
|
||||
fmt.Printf("trying to split edge from %d->%d at %s\n",
|
||||
blk.ID(), succ.ID(), predInfo.branch.Format(b))
|
||||
}
|
||||
@@ -763,9 +763,11 @@ func (b *builder) LayoutBlocks() {
|
||||
// Update the successors slice because the target is no longer the original `succ`.
|
||||
blk.success[sidx] = trampoline
|
||||
|
||||
trampolines = append(trampolines, trampoline)
|
||||
if wazevoapi.SSAValidationEnabled {
|
||||
trampolines = append(trampolines, trampoline)
|
||||
}
|
||||
|
||||
if debug {
|
||||
if wazevoapi.SSALoggingEnabled {
|
||||
fmt.Printf("edge split from %d->%d at %s as %d->%d->%d \n",
|
||||
blk.ID(), succ.ID(), predInfo.branch.Format(b),
|
||||
blk.ID(), trampoline.ID(), succ.ID())
|
||||
@@ -791,7 +793,7 @@ func (b *builder) LayoutBlocks() {
|
||||
uninsertedTrampolines = uninsertedTrampolines[:0] // Reuse the stack for the next block.
|
||||
}
|
||||
|
||||
if debug {
|
||||
if wazevoapi.SSALoggingEnabled {
|
||||
var bs []string
|
||||
for _, blk := range b.reversePostOrderedBasicBlocks {
|
||||
bs = append(bs, blk.Name())
|
||||
@@ -803,6 +805,9 @@ func (b *builder) LayoutBlocks() {
|
||||
}
|
||||
sort.Slice(bs, func(i, j int) bool { return bs[i] < bs[j] })
|
||||
fmt.Println("visited blocks: ", strings.Join(bs, ", "))
|
||||
}
|
||||
|
||||
if wazevoapi.SSAValidationEnabled {
|
||||
for _, trampoline := range trampolines {
|
||||
if _, ok := b.blkVisited[trampoline]; !ok {
|
||||
panic("BUG: trampoline block not inserted: " + trampoline.FormatHeader(b))
|
||||
@@ -901,7 +906,7 @@ invert:
|
||||
condBranch.InvertBrx()
|
||||
condBranch.blk = fallthroughTarget
|
||||
fallthroughBranch.blk = condTarget
|
||||
if debug {
|
||||
if wazevoapi.SSALoggingEnabled {
|
||||
fmt.Printf("inverting branches at %d->%d and %d->%d\n",
|
||||
now.ID(), fallthroughTarget.ID(), now.ID(), condTarget.ID())
|
||||
}
|
||||
@@ -909,8 +914,6 @@ invert:
|
||||
return true
|
||||
}
|
||||
|
||||
const debug = false
|
||||
|
||||
// splitCriticalEdge splits the critical edge between the given predecessor (`pred`) and successor (owning `predInfo`).
|
||||
//
|
||||
// - `pred` is the source of the critical edge,
|
||||
@@ -964,7 +967,7 @@ func (b *builder) splitCriticalEdge(pred, succ *basicBlock, predInfo *basicBlock
|
||||
predInfo.blk = trampoline
|
||||
predInfo.branch = originalBranch
|
||||
|
||||
if debug {
|
||||
if wazevoapi.SSAValidationEnabled {
|
||||
trampoline.validate(b)
|
||||
}
|
||||
|
||||
|
||||
@@ -121,7 +121,6 @@ func (i *Instruction) IsBranching() bool {
|
||||
}
|
||||
|
||||
// TODO: complete opcode comments.
|
||||
// TODO: there should be unnecessary opcodes.
|
||||
const (
|
||||
OpcodeInvalid Opcode = iota
|
||||
|
||||
@@ -160,10 +159,6 @@ const (
|
||||
// Note that this is different from call_indirect in Wasm, which also does type checking, etc.
|
||||
OpcodeCallIndirect
|
||||
|
||||
// OpcodeFuncAddr ...
|
||||
// `addr = func_addr FN`.
|
||||
OpcodeFuncAddr
|
||||
|
||||
// OpcodeSplat ...
|
||||
// `v = splat x`.
|
||||
OpcodeSplat
|
||||
@@ -273,34 +268,6 @@ const (
|
||||
// `v = sload32x2 MemFlags, p, Offset`.
|
||||
OpcodeSload32x2
|
||||
|
||||
// OpcodeGlobalValue ...
|
||||
// `v = global_value GV`.
|
||||
OpcodeGlobalValue
|
||||
|
||||
// OpcodeSymbolValue ...
|
||||
// `v = symbol_value GV`.
|
||||
OpcodeSymbolValue
|
||||
|
||||
// OpcodeHeapAddr ...
|
||||
// `addr = heap_addr H, index, Offset, Size`.
|
||||
OpcodeHeapAddr
|
||||
|
||||
// OpcodeHeapLoad ...
|
||||
// `v = heap_load heap_imm, index`.
|
||||
OpcodeHeapLoad
|
||||
|
||||
// OpcodeHeapStore ...
|
||||
// `heap_store heap_imm, index, a`.
|
||||
OpcodeHeapStore
|
||||
|
||||
// OpcodeGetReturnAddress ...
|
||||
// `addr = get_return_address`.
|
||||
OpcodeGetReturnAddress
|
||||
|
||||
// OpcodeTableAddr ...
|
||||
// `addr = table_addr T, p, Offset`.
|
||||
OpcodeTableAddr
|
||||
|
||||
// OpcodeIconst represents the integer const.
|
||||
OpcodeIconst
|
||||
|
||||
@@ -320,14 +287,6 @@ const (
|
||||
// `v = shuffle a, b, mask`.
|
||||
OpcodeShuffle
|
||||
|
||||
// OpcodeNull ...
|
||||
// `v = null`.
|
||||
OpcodeNull
|
||||
|
||||
// OpcodeNop ...
|
||||
// `nop`.
|
||||
OpcodeNop
|
||||
|
||||
// OpcodeSelect chooses between two values based on a condition `c`: `v = Select c, x, y`.
|
||||
OpcodeSelect
|
||||
|
||||
@@ -371,14 +330,6 @@ const (
|
||||
// OpcodeIsub performs an integer subtraction: `v = Isub x, y`.
|
||||
OpcodeIsub
|
||||
|
||||
// OpcodeIneg ...
|
||||
// `v = ineg x`.
|
||||
OpcodeIneg
|
||||
|
||||
// OpcodeIabs ...
|
||||
// `v = iabs x`.
|
||||
OpcodeIabs
|
||||
|
||||
// OpcodeImul performs an integer multiplication: `v = Imul x, y`.
|
||||
OpcodeImul
|
||||
|
||||
@@ -568,106 +519,62 @@ const (
|
||||
// `v = bitrev x`.
|
||||
OpcodeBitrev
|
||||
|
||||
// OpcodeClz ...
|
||||
// `v = clz x`.
|
||||
// OpcodeClz counts the number of leading zeros: `v = clz x`.
|
||||
OpcodeClz
|
||||
|
||||
// OpcodeCls ...
|
||||
// `v = cls x`.
|
||||
OpcodeCls
|
||||
|
||||
// OpcodeCtz ...
|
||||
// `v = ctz x`.
|
||||
// OpcodeCtz counts the number of trailing zeros: `v = ctz x`.
|
||||
OpcodeCtz
|
||||
|
||||
// OpcodeBswap ...
|
||||
// `v = bswap x`.
|
||||
OpcodeBswap
|
||||
|
||||
// OpcodePopcnt ...
|
||||
// `v = popcnt x`.
|
||||
// OpcodePopcnt counts the number of 1-bits: `v = popcnt x`.
|
||||
OpcodePopcnt
|
||||
|
||||
// OpcodeFcmp compares two floating point values: `v = fcmp Cond, x, y`.
|
||||
OpcodeFcmp
|
||||
|
||||
// OpcodeFadd performs an floating point addition.
|
||||
// `v = Fadd x, y`.
|
||||
// OpcodeFadd performs a floating point addition: / `v = Fadd x, y`.
|
||||
OpcodeFadd
|
||||
|
||||
// OpcodeFsub performs an floating point subtraction.
|
||||
// `v = Fsub x, y`.
|
||||
// OpcodeFsub performs a floating point subtraction: `v = Fsub x, y`.
|
||||
OpcodeFsub
|
||||
|
||||
// OpcodeFmul ...
|
||||
// `v = fmul x, y`.
|
||||
// OpcodeFmul performs a floating point multiplication: `v = Fmul x, y`.
|
||||
OpcodeFmul
|
||||
|
||||
// OpcodeFdiv ...
|
||||
// `v = fdiv x, y`.
|
||||
// OpcodeFdiv performs a floating point division: `v = Fdiv x, y`.
|
||||
OpcodeFdiv
|
||||
|
||||
// OpcodeSqrt ...
|
||||
// `v = sqrt x`.
|
||||
// OpcodeSqrt takes the square root of the given floating point value: `v = sqrt x`.
|
||||
OpcodeSqrt
|
||||
|
||||
// OpcodeFma ...
|
||||
// `v = fma x, y, z`.
|
||||
OpcodeFma
|
||||
|
||||
// OpcodeFneg negates the given floating point value: `v = Fneg x`.
|
||||
OpcodeFneg
|
||||
|
||||
// OpcodeFabs ...
|
||||
// `v = fabs x`.
|
||||
// OpcodeFabs takes the absolute value of the given floating point value: `v = fabs x`.
|
||||
OpcodeFabs
|
||||
|
||||
// OpcodeFcopysign ...
|
||||
// `v = fcopysign x, y`.
|
||||
OpcodeFcopysign
|
||||
|
||||
// OpcodeFmin ...
|
||||
// `v = fmin x, y`.
|
||||
// OpcodeFmin takes the minimum of two floating point values: `v = fmin x, y`.
|
||||
OpcodeFmin
|
||||
|
||||
// OpcodeFminPseudo ...
|
||||
// `v = fmin_pseudo x, y`.
|
||||
OpcodeFminPseudo
|
||||
|
||||
// OpcodeFmax ...
|
||||
// `v = fmax x, y`.
|
||||
// OpcodeFmax takes the maximum of two floating point values: `v = fmax x, y`.
|
||||
OpcodeFmax
|
||||
|
||||
// OpcodeFmaxPseudo ...
|
||||
// `v = fmax_pseudo x, y`.
|
||||
OpcodeFmaxPseudo
|
||||
|
||||
// OpcodeCeil ...
|
||||
// `v = ceil x`.
|
||||
// OpcodeCeil takes the ceiling of the given floating point value: `v = ceil x`.
|
||||
OpcodeCeil
|
||||
|
||||
// OpcodeFloor ...
|
||||
// `v = floor x`.
|
||||
// OpcodeFloor takes the floor of the given floating point value: `v = floor x`.
|
||||
OpcodeFloor
|
||||
|
||||
// OpcodeTrunc ...
|
||||
// `v = trunc x`.
|
||||
// OpcodeTrunc takes the truncation of the given floating point value: `v = trunc x`.
|
||||
OpcodeTrunc
|
||||
|
||||
// OpcodeNearest ...
|
||||
// `v = nearest x`.
|
||||
// OpcodeNearest takes the nearest integer of the given floating point value: `v = nearest x`.
|
||||
OpcodeNearest
|
||||
|
||||
// OpcodeIsNull ...
|
||||
// `v = is_null x`.
|
||||
OpcodeIsNull
|
||||
|
||||
// OpcodeIsInvalid ...
|
||||
// `v = is_invalid x`.
|
||||
OpcodeIsInvalid
|
||||
|
||||
// OpcodeBitcast ...
|
||||
// `v = bitcast MemFlags, x`.
|
||||
// OpcodeBitcast is a bitcast operation: `v = bitcast MemFlags, x`.
|
||||
OpcodeBitcast
|
||||
|
||||
// OpcodeScalarToVector ...
|
||||
@@ -1851,8 +1758,6 @@ func (o Opcode) String() (ret string) {
|
||||
return "Call"
|
||||
case OpcodeCallIndirect:
|
||||
return "CallIndirect"
|
||||
case OpcodeFuncAddr:
|
||||
return "FuncAddr"
|
||||
case OpcodeSplat:
|
||||
return "Splat"
|
||||
case OpcodeSwizzle:
|
||||
@@ -1913,20 +1818,6 @@ func (o Opcode) String() (ret string) {
|
||||
return "Uload32x2"
|
||||
case OpcodeSload32x2:
|
||||
return "Sload32x2"
|
||||
case OpcodeGlobalValue:
|
||||
return "GlobalValue"
|
||||
case OpcodeSymbolValue:
|
||||
return "SymbolValue"
|
||||
case OpcodeHeapAddr:
|
||||
return "HeapAddr"
|
||||
case OpcodeHeapLoad:
|
||||
return "HeapLoad"
|
||||
case OpcodeHeapStore:
|
||||
return "HeapStore"
|
||||
case OpcodeGetReturnAddress:
|
||||
return "GetReturnAddress"
|
||||
case OpcodeTableAddr:
|
||||
return "TableAddr"
|
||||
case OpcodeIconst:
|
||||
return "Iconst"
|
||||
case OpcodeF32const:
|
||||
@@ -1937,10 +1828,6 @@ func (o Opcode) String() (ret string) {
|
||||
return "Vconst"
|
||||
case OpcodeShuffle:
|
||||
return "Shuffle"
|
||||
case OpcodeNull:
|
||||
return "Null"
|
||||
case OpcodeNop:
|
||||
return "Nop"
|
||||
case OpcodeSelect:
|
||||
return "Select"
|
||||
case OpcodeBitselect:
|
||||
@@ -1965,10 +1852,6 @@ func (o Opcode) String() (ret string) {
|
||||
return "Iadd"
|
||||
case OpcodeIsub:
|
||||
return "Isub"
|
||||
case OpcodeIneg:
|
||||
return "Ineg"
|
||||
case OpcodeIabs:
|
||||
return "Iabs"
|
||||
case OpcodeImul:
|
||||
return "Imul"
|
||||
case OpcodeUmulhi:
|
||||
@@ -2069,12 +1952,8 @@ func (o Opcode) String() (ret string) {
|
||||
return "Bitrev"
|
||||
case OpcodeClz:
|
||||
return "Clz"
|
||||
case OpcodeCls:
|
||||
return "Cls"
|
||||
case OpcodeCtz:
|
||||
return "Ctz"
|
||||
case OpcodeBswap:
|
||||
return "Bswap"
|
||||
case OpcodePopcnt:
|
||||
return "Popcnt"
|
||||
case OpcodeFcmp:
|
||||
@@ -2089,8 +1968,6 @@ func (o Opcode) String() (ret string) {
|
||||
return "Fdiv"
|
||||
case OpcodeSqrt:
|
||||
return "Sqrt"
|
||||
case OpcodeFma:
|
||||
return "Fma"
|
||||
case OpcodeFneg:
|
||||
return "Fneg"
|
||||
case OpcodeFabs:
|
||||
@@ -2099,12 +1976,8 @@ func (o Opcode) String() (ret string) {
|
||||
return "Fcopysign"
|
||||
case OpcodeFmin:
|
||||
return "Fmin"
|
||||
case OpcodeFminPseudo:
|
||||
return "FminPseudo"
|
||||
case OpcodeFmax:
|
||||
return "Fmax"
|
||||
case OpcodeFmaxPseudo:
|
||||
return "FmaxPseudo"
|
||||
case OpcodeCeil:
|
||||
return "Ceil"
|
||||
case OpcodeFloor:
|
||||
@@ -2113,10 +1986,6 @@ func (o Opcode) String() (ret string) {
|
||||
return "Trunc"
|
||||
case OpcodeNearest:
|
||||
return "Nearest"
|
||||
case OpcodeIsNull:
|
||||
return "IsNull"
|
||||
case OpcodeIsInvalid:
|
||||
return "IsInvalid"
|
||||
case OpcodeBitcast:
|
||||
return "Bitcast"
|
||||
case OpcodeScalarToVector:
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
package ssa
|
||||
|
||||
import "fmt"
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi"
|
||||
)
|
||||
|
||||
// RunPasses implements Builder.RunPasses.
|
||||
//
|
||||
@@ -45,7 +49,7 @@ func passDeadBlockEliminationOpt(b *builder) {
|
||||
panic(fmt.Sprintf("%s is not sealed", reachableBlk))
|
||||
}
|
||||
|
||||
if true {
|
||||
if wazevoapi.SSAValidationEnabled {
|
||||
reachableBlk.validate(b)
|
||||
}
|
||||
|
||||
@@ -282,7 +286,7 @@ func passDeadCodeEliminationOpt(b *builder) {
|
||||
}
|
||||
|
||||
func (b *builder) incRefCount(id ValueID, from *Instruction) {
|
||||
if debug {
|
||||
if wazevoapi.SSALoggingEnabled {
|
||||
fmt.Printf("v%d referenced from %v\n", id, from.Format(b))
|
||||
}
|
||||
b.valueRefCounts[id]++
|
||||
|
||||
@@ -3,6 +3,8 @@ package ssa
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
|
||||
"github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi"
|
||||
)
|
||||
|
||||
// Variable is a unique identifier for a source program's variable and will correspond to
|
||||
@@ -49,7 +51,7 @@ func (v Value) formatWithType(b Builder) (ret string) {
|
||||
ret = fmt.Sprintf("v%d:%s", v.ID(), v.Type())
|
||||
}
|
||||
|
||||
if debug { // This is useful to check live value analysis bugs.
|
||||
if wazevoapi.SSALoggingEnabled { // This is useful to check live value analysis bugs.
|
||||
if bd := b.(*builder); bd.donePasses {
|
||||
id := v.ID()
|
||||
ret += fmt.Sprintf("(ref=%d)", bd.valueRefCounts[id])
|
||||
|
||||
35
internal/engine/wazevo/wazevoapi/debug_consts.go
Normal file
35
internal/engine/wazevo/wazevoapi/debug_consts.go
Normal file
@@ -0,0 +1,35 @@
|
||||
package wazevoapi
|
||||
|
||||
// These consts are used various places in the wazevo implementations.
|
||||
// Instead of defining them in each file, we define them here so that we can quickly iterate on
|
||||
// debugging without spending "where do we have debug logging?" time.
|
||||
|
||||
// ----- Debug logging -----
|
||||
// These consts must be disabled by default. Enable them only when debugging.
|
||||
|
||||
const (
|
||||
FrontEndLoggingEnabled = false
|
||||
SSALoggingEnabled = false
|
||||
RegAllocLoggingEnabled = false
|
||||
)
|
||||
|
||||
// ----- Output prints -----
|
||||
// These consts must be disabled by default. Enable them only when debugging.
|
||||
|
||||
const (
|
||||
PrintSSA = false
|
||||
PrintOptimizedSSA = false
|
||||
PrintBlockLaidOutSSA = false
|
||||
PrintSSAToBackendIRLowering = false
|
||||
PrintRegisterAllocated = false
|
||||
PrintFinalizedMachineCode = false
|
||||
PrintMachineCodeHexPerFunction = false
|
||||
)
|
||||
|
||||
// ----- Validations -----
|
||||
// These consts must be enabled by default until we reach the point where we can disable them (e.g. multiple days of fuzzing passes).
|
||||
|
||||
const (
|
||||
RegAllocValidationEnabled = true
|
||||
SSAValidationEnabled = true
|
||||
)
|
||||
Reference in New Issue
Block a user