diff --git a/internal/engine/wazevo/backend/compiler.go b/internal/engine/wazevo/backend/compiler.go index 0c3d4e5812..aea55ee73a 100644 --- a/internal/engine/wazevo/backend/compiler.go +++ b/internal/engine/wazevo/backend/compiler.go @@ -222,14 +222,13 @@ func (c *compiler) assignVirtualRegisters() { typ := p.Type() vreg := c.AllocateVReg(typ) c.ssaValueToVRegs[pid] = vreg - c.ssaValueDefinitions[pid] = SSAValueDefinition{BlockParamValue: p, BlkParamVReg: vreg} + c.ssaValueDefinitions[pid] = SSAValueDefinition{V: p} c.ssaTypeOfVRegID[vreg.ID()] = p.Type() } // Assigns each value to a virtual register produced by instructions. for cur := blk.Root(); cur != nil; cur = cur.Next() { r, rs := cur.Returns() - var N int if r.Valid() { id := r.ID() ssaTyp := r.Type() @@ -238,11 +237,10 @@ func (c *compiler) assignVirtualRegisters() { c.ssaValueToVRegs[id] = vReg c.ssaValueDefinitions[id] = SSAValueDefinition{ Instr: cur, - N: 0, + V: r, RefCount: refCounts[id].RefCount, } c.ssaTypeOfVRegID[vReg.ID()] = ssaTyp - N++ } for _, r := range rs { id := r.ID() @@ -251,11 +249,10 @@ func (c *compiler) assignVirtualRegisters() { c.ssaValueToVRegs[id] = vReg c.ssaValueDefinitions[id] = SSAValueDefinition{ Instr: cur, - N: N, + V: r, RefCount: refCounts[id].RefCount, } c.ssaTypeOfVRegID[vReg.ID()] = ssaTyp - N++ } } } diff --git a/internal/engine/wazevo/backend/isa/amd64/lower_mem.go b/internal/engine/wazevo/backend/isa/amd64/lower_mem.go index bee673d25c..818f2dbf8b 100644 --- a/internal/engine/wazevo/backend/isa/amd64/lower_mem.go +++ b/internal/engine/wazevo/backend/isa/amd64/lower_mem.go @@ -131,8 +131,8 @@ func (m *machine) lowerAddendsToAmode(x, y addend, offBase uint32) *amode { } func (m *machine) lowerAddend(x *backend.SSAValueDefinition) addend { - if x.IsFromBlockParam() { - return addend{x.BlkParamVReg, 0, 0} + if !x.IsFromInstr() { + return addend{m.c.VRegOf(x.V), 0, 0} } // Ensure the addend is not referenced in multiple places; we will discard nested Iadds. op := m.c.MatchInstrOneOf(x, addendsMatchOpcodes[:]) diff --git a/internal/engine/wazevo/backend/isa/amd64/lower_mem_test.go b/internal/engine/wazevo/backend/isa/amd64/lower_mem_test.go index 7f6d7460f0..1b3006c0b1 100644 --- a/internal/engine/wazevo/backend/isa/amd64/lower_mem_test.go +++ b/internal/engine/wazevo/backend/isa/amd64/lower_mem_test.go @@ -53,7 +53,8 @@ func TestMachine_lowerToAddressMode(t *testing.T) { ptr = iadd.Return() offset = 3 ctx.definitions[iconst1.Return()] = &backend.SSAValueDefinition{Instr: iconst1} - ctx.definitions[p] = &backend.SSAValueDefinition{BlockParamValue: p, BlkParamVReg: raxVReg} + ctx.vRegMap[p] = raxVReg + ctx.definitions[p] = &backend.SSAValueDefinition{V: p} ctx.definitions[ptr] = &backend.SSAValueDefinition{Instr: iadd} return }, @@ -67,8 +68,10 @@ func TestMachine_lowerToAddressMode(t *testing.T) { iadd := b.AllocateInstruction().AsIadd(p1, p2).Insert(b) ptr = iadd.Return() offset = 3 - ctx.definitions[p1] = &backend.SSAValueDefinition{BlockParamValue: p1, BlkParamVReg: raxVReg} - ctx.definitions[p2] = &backend.SSAValueDefinition{BlockParamValue: p2, BlkParamVReg: rcxVReg} + ctx.vRegMap[p1] = raxVReg + ctx.definitions[p1] = &backend.SSAValueDefinition{V: p1} + ctx.vRegMap[p2] = rcxVReg + ctx.definitions[p2] = &backend.SSAValueDefinition{V: p2} ctx.definitions[ptr] = &backend.SSAValueDefinition{Instr: iadd} return }, @@ -79,7 +82,8 @@ func TestMachine_lowerToAddressMode(t *testing.T) { in: func(ctx *mockCompiler, b ssa.Builder, m *machine) (ptr ssa.Value, offset uint32) { ptr = b.CurrentBlock().AddParam(b, ssa.TypeI64) offset = 1 << 31 - ctx.definitions[ptr] = &backend.SSAValueDefinition{BlockParamValue: ptr, BlkParamVReg: raxVReg} + ctx.vRegMap[ptr] = raxVReg + ctx.definitions[ptr] = &backend.SSAValueDefinition{V: ptr} return }, insts: []string{ @@ -109,7 +113,8 @@ func TestMachine_lowerToAddressMode(t *testing.T) { p := b.CurrentBlock().AddParam(b, ssa.TypeI64) iconst64 := b.AllocateInstruction().AsIconst64(2).Insert(b) ishl := b.AllocateInstruction().AsIshl(p, iconst64.Return()).Insert(b) - ctx.definitions[p] = &backend.SSAValueDefinition{BlockParamValue: p, BlkParamVReg: raxVReg} + ctx.vRegMap[p] = raxVReg + ctx.definitions[p] = &backend.SSAValueDefinition{V: p} ctx.definitions[iconst64.Return()] = &backend.SSAValueDefinition{Instr: iconst64} ctx.definitions[ishl.Return()] = &backend.SSAValueDefinition{Instr: ishl} return ishl.Return(), 1 << 30 @@ -127,8 +132,10 @@ func TestMachine_lowerToAddressMode(t *testing.T) { const2 := b.AllocateInstruction().AsIconst64(2).Insert(b) ishl := b.AllocateInstruction().AsIshl(p1, const2.Return()).Insert(b) iadd := b.AllocateInstruction().AsIadd(p2, ishl.Return()).Insert(b) - ctx.definitions[p1] = &backend.SSAValueDefinition{BlockParamValue: p1, BlkParamVReg: raxVReg} - ctx.definitions[p2] = &backend.SSAValueDefinition{BlockParamValue: p2, BlkParamVReg: rcxVReg} + ctx.vRegMap[p1] = raxVReg + ctx.definitions[p1] = &backend.SSAValueDefinition{V: p1} + ctx.vRegMap[p2] = rcxVReg + ctx.definitions[p2] = &backend.SSAValueDefinition{V: p2} ctx.definitions[const2.Return()] = &backend.SSAValueDefinition{Instr: const2} ctx.definitions[ishl.Return()] = &backend.SSAValueDefinition{Instr: ishl} ctx.definitions[iadd.Return()] = &backend.SSAValueDefinition{Instr: iadd} @@ -181,7 +188,8 @@ func TestMachine_lowerAddendFromInstr(t *testing.T) { name: "uextend const64", in: func(ctx *mockCompiler, b ssa.Builder, m *machine) *ssa.Instruction { p := b.CurrentBlock().AddParam(b, ssa.TypeI32) - ctx.definitions[p] = &backend.SSAValueDefinition{BlkParamVReg: raxVReg, BlockParamValue: p} + ctx.vRegMap[p] = raxVReg + ctx.definitions[p] = &backend.SSAValueDefinition{V: p} return b.AllocateInstruction().AsUExtend(p, 32, 64).Insert(b) }, exp: addend{raxVReg, 0, 0}, @@ -190,7 +198,8 @@ func TestMachine_lowerAddendFromInstr(t *testing.T) { name: "uextend param i32", in: func(ctx *mockCompiler, b ssa.Builder, m *machine) *ssa.Instruction { p := b.CurrentBlock().AddParam(b, ssa.TypeI32) - ctx.definitions[p] = &backend.SSAValueDefinition{BlkParamVReg: raxVReg, BlockParamValue: p} + ctx.vRegMap[p] = raxVReg + ctx.definitions[p] = &backend.SSAValueDefinition{V: p} return b.AllocateInstruction().AsUExtend(p, 32, 64).Insert(b) }, exp: addend{raxVReg, 0, 0}, @@ -208,7 +217,8 @@ func TestMachine_lowerAddendFromInstr(t *testing.T) { name: "sextend const64", in: func(ctx *mockCompiler, b ssa.Builder, m *machine) *ssa.Instruction { p := b.CurrentBlock().AddParam(b, ssa.TypeI32) - ctx.definitions[p] = &backend.SSAValueDefinition{BlkParamVReg: raxVReg, BlockParamValue: p} + ctx.vRegMap[p] = raxVReg + ctx.definitions[p] = &backend.SSAValueDefinition{V: p} return b.AllocateInstruction().AsSExtend(p, 32, 64).Insert(b) }, exp: addend{raxVReg, 0, 0}, @@ -217,7 +227,8 @@ func TestMachine_lowerAddendFromInstr(t *testing.T) { name: "sextend param i32", in: func(ctx *mockCompiler, b ssa.Builder, m *machine) *ssa.Instruction { p := b.CurrentBlock().AddParam(b, ssa.TypeI32) - ctx.definitions[p] = &backend.SSAValueDefinition{BlkParamVReg: raxVReg, BlockParamValue: p} + ctx.vRegMap[p] = raxVReg + ctx.definitions[p] = &backend.SSAValueDefinition{V: p} return b.AllocateInstruction().AsSExtend(p, 32, 64).Insert(b) }, exp: addend{raxVReg, 0, 0}, diff --git a/internal/engine/wazevo/backend/isa/amd64/machine_test.go b/internal/engine/wazevo/backend/isa/amd64/machine_test.go index 5614b45cbf..b02a5bd700 100644 --- a/internal/engine/wazevo/backend/isa/amd64/machine_test.go +++ b/internal/engine/wazevo/backend/isa/amd64/machine_test.go @@ -46,7 +46,8 @@ func TestMachine_getOperand_Reg(t *testing.T) { { name: "block param", setup: func(ctx *mockCompiler, builder ssa.Builder, m *machine) *backend.SSAValueDefinition { - return &backend.SSAValueDefinition{BlkParamVReg: raxVReg, Instr: nil, N: 0} + ctx.vRegMap[1234] = raxVReg + return &backend.SSAValueDefinition{V: 1234, Instr: nil} }, exp: newOperandReg(raxVReg), }, @@ -58,7 +59,7 @@ func TestMachine_getOperand_Reg(t *testing.T) { instr.AsIconst32(0xf00000f) builder.InsertInstruction(instr) ctx.vRegCounter = 99 - return &backend.SSAValueDefinition{Instr: instr, N: 0} + return &backend.SSAValueDefinition{Instr: instr} }, exp: newOperandReg(regalloc.VReg(100).SetRegType(regalloc.RegTypeInt)), instructions: []string{"movl $251658255, %r100d?"}, @@ -73,7 +74,7 @@ func TestMachine_getOperand_Reg(t *testing.T) { builder.InsertInstruction(c) r := c.Return() ctx.vRegMap[r] = regalloc.VReg(50) - return &backend.SSAValueDefinition{Instr: c, N: 0} + return &backend.SSAValueDefinition{V: r} }, exp: newOperandReg(regalloc.VReg(50)), }, @@ -87,7 +88,7 @@ func TestMachine_getOperand_Reg(t *testing.T) { builder.InsertInstruction(c) _, rs := c.Returns() ctx.vRegMap[rs[1]] = regalloc.VReg(50) - return &backend.SSAValueDefinition{Instr: c, N: 2} + return &backend.SSAValueDefinition{V: rs[1]} }, exp: newOperandReg(regalloc.VReg(50)), }, @@ -112,7 +113,8 @@ func TestMachine_getOperand_Imm32_Reg(t *testing.T) { { name: "block param falls back to getOperand_Reg", setup: func(ctx *mockCompiler, builder ssa.Builder, m *machine) *backend.SSAValueDefinition { - return &backend.SSAValueDefinition{BlkParamVReg: raxVReg, Instr: nil, N: 0} + ctx.vRegMap[1234] = raxVReg + return &backend.SSAValueDefinition{V: 1234, Instr: nil} }, exp: newOperandReg(raxVReg), }, @@ -124,7 +126,7 @@ func TestMachine_getOperand_Imm32_Reg(t *testing.T) { builder.InsertInstruction(instr) ctx.vRegCounter = 99 ctx.currentGID = 0xff // const can be merged anytime, regardless of the group id. - return &backend.SSAValueDefinition{Instr: instr, N: 0} + return &backend.SSAValueDefinition{Instr: instr} }, exp: newOperandImm32(0xf00000f), }, @@ -155,7 +157,8 @@ func Test_machine_getOperand_Mem_Imm32_Reg(t *testing.T) { { name: "block param falls back to getOperand_Imm32_Reg", setup: func(ctx *mockCompiler, builder ssa.Builder, m *machine) *backend.SSAValueDefinition { - return &backend.SSAValueDefinition{BlkParamVReg: raxVReg, Instr: nil, N: 0} + ctx.vRegMap[1234] = raxVReg + return &backend.SSAValueDefinition{V: 1234, Instr: nil} }, exp: newOperandReg(raxVReg), }, @@ -164,10 +167,11 @@ func Test_machine_getOperand_Mem_Imm32_Reg(t *testing.T) { setup: func(ctx *mockCompiler, builder ssa.Builder, m *machine) *backend.SSAValueDefinition { blk := builder.CurrentBlock() ptr := blk.AddParam(builder, ssa.TypeI64) - ctx.definitions[ptr] = &backend.SSAValueDefinition{BlockParamValue: ptr, BlkParamVReg: raxVReg} + ctx.vRegMap[ptr] = raxVReg + ctx.definitions[ptr] = &backend.SSAValueDefinition{V: ptr} instr := builder.AllocateInstruction() instr.AsLoad(ptr, 123, ssa.TypeI64).Insert(builder) - return &backend.SSAValueDefinition{Instr: instr, N: 0} + return &backend.SSAValueDefinition{Instr: instr} }, exp: newOperandMem(newAmodeImmReg(123, raxVReg)), }, @@ -178,7 +182,7 @@ func Test_machine_getOperand_Mem_Imm32_Reg(t *testing.T) { instr := builder.AllocateInstruction() instr.AsLoad(iconst.Return(), 123, ssa.TypeI64).Insert(builder) ctx.definitions[iconst.Return()] = &backend.SSAValueDefinition{Instr: iconst} - return &backend.SSAValueDefinition{Instr: instr, N: 0} + return &backend.SSAValueDefinition{Instr: instr} }, instructions: []string{ "movabsq $579, %r1?", // r1 := 123+456 @@ -197,7 +201,7 @@ func Test_machine_getOperand_Mem_Imm32_Reg(t *testing.T) { ctx.definitions[uextend.Return()] = &backend.SSAValueDefinition{Instr: uextend} ctx.definitions[iconst.Return()] = &backend.SSAValueDefinition{Instr: iconst} - return &backend.SSAValueDefinition{Instr: instr, N: 0} + return &backend.SSAValueDefinition{Instr: instr} }, instructions: []string{ fmt.Sprintf("movabsq $%d, %%r1?", 0xffffff+123), @@ -216,7 +220,7 @@ func Test_machine_getOperand_Mem_Imm32_Reg(t *testing.T) { ctx.definitions[uextend.Return()] = &backend.SSAValueDefinition{Instr: uextend} ctx.definitions[iconst.Return()] = &backend.SSAValueDefinition{Instr: iconst} - return &backend.SSAValueDefinition{Instr: instr, N: 0} + return &backend.SSAValueDefinition{Instr: instr} }, instructions: []string{ fmt.Sprintf("movabsq $%d, %%r1?", 456+123), @@ -233,11 +237,12 @@ func Test_machine_getOperand_Mem_Imm32_Reg(t *testing.T) { instr := builder.AllocateInstruction() instr.AsLoad(iadd.Return(), 789, ssa.TypeI64).Insert(builder) - ctx.definitions[p] = &backend.SSAValueDefinition{BlockParamValue: p, BlkParamVReg: raxVReg} + ctx.vRegMap[p] = raxVReg + ctx.definitions[p] = &backend.SSAValueDefinition{V: p} ctx.definitions[iconst.Return()] = &backend.SSAValueDefinition{Instr: iconst} ctx.definitions[iadd.Return()] = &backend.SSAValueDefinition{Instr: iadd} - return &backend.SSAValueDefinition{Instr: instr, N: 0} + return &backend.SSAValueDefinition{Instr: instr} }, exp: newOperandMem(newAmodeImmReg(456+789, raxVReg)), }, @@ -255,7 +260,7 @@ func Test_machine_getOperand_Mem_Imm32_Reg(t *testing.T) { ctx.definitions[iconst2.Return()] = &backend.SSAValueDefinition{Instr: iconst2} ctx.definitions[iadd.Return()] = &backend.SSAValueDefinition{Instr: iadd} - return &backend.SSAValueDefinition{Instr: instr, N: 0} + return &backend.SSAValueDefinition{Instr: instr} }, instructions: []string{ fmt.Sprintf("movabsq $%d, %%r1?", 123+456+789), @@ -361,7 +366,8 @@ L2: p := b.CurrentBlock().AddParam(b, tc.typ) m.cpuFeatures = tc.cpuFlags - ctx.definitions[p] = &backend.SSAValueDefinition{BlockParamValue: p, BlkParamVReg: raxVReg} + ctx.vRegMap[p] = raxVReg + ctx.definitions[p] = &backend.SSAValueDefinition{V: p} ctx.vRegMap[0] = rcxVReg instr := &ssa.Instruction{} instr.AsClz(p) @@ -434,7 +440,8 @@ L2: p := b.CurrentBlock().AddParam(b, tc.typ) m.cpuFeatures = tc.cpuFlags - ctx.definitions[p] = &backend.SSAValueDefinition{BlockParamValue: p, BlkParamVReg: raxVReg} + ctx.vRegMap[p] = raxVReg + ctx.definitions[p] = &backend.SSAValueDefinition{V: p} ctx.vRegMap[0] = rcxVReg instr := &ssa.Instruction{} instr.AsCtz(p) diff --git a/internal/engine/wazevo/backend/isa/amd64/operands.go b/internal/engine/wazevo/backend/isa/amd64/operands.go index 10b727e7c9..46fb0f6866 100644 --- a/internal/engine/wazevo/backend/isa/amd64/operands.go +++ b/internal/engine/wazevo/backend/isa/amd64/operands.go @@ -253,11 +253,11 @@ func (a *amode) String() string { } func (m *machine) getOperand_Mem_Reg(def *backend.SSAValueDefinition) (op operand) { - if def.IsFromBlockParam() { - return newOperandReg(def.BlkParamVReg) + if !def.IsFromInstr() { + return newOperandReg(m.c.VRegOf(def.V)) } - if def.SSAValue().Type() == ssa.TypeV128 { + if def.V.Type() == ssa.TypeV128 { // SIMD instructions require strict memory alignment, so we don't support the memory operand for V128 at the moment. return m.getOperand_Reg(def) } @@ -273,8 +273,8 @@ func (m *machine) getOperand_Mem_Reg(def *backend.SSAValueDefinition) (op operan } func (m *machine) getOperand_Mem_Imm32_Reg(def *backend.SSAValueDefinition) (op operand) { - if def.IsFromBlockParam() { - return newOperandReg(def.BlkParamVReg) + if !def.IsFromInstr() { + return newOperandReg(m.c.VRegOf(def.V)) } if m.c.MatchInstr(def, ssa.OpcodeLoad) { @@ -288,8 +288,8 @@ func (m *machine) getOperand_Mem_Imm32_Reg(def *backend.SSAValueDefinition) (op } func (m *machine) getOperand_Imm32_Reg(def *backend.SSAValueDefinition) (op operand) { - if def.IsFromBlockParam() { - return newOperandReg(def.BlkParamVReg) + if !def.IsFromInstr() { + return newOperandReg(m.c.VRegOf(def.V)) } instr := def.Instr @@ -325,22 +325,12 @@ func asImm32(val uint64, allowSignExt bool) (uint32, bool) { func (m *machine) getOperand_Reg(def *backend.SSAValueDefinition) (op operand) { var v regalloc.VReg - if def.IsFromBlockParam() { - v = def.BlkParamVReg + if instr := def.Instr; instr != nil && instr.Constant() { + // We inline all the constant instructions so that we could reduce the register usage. + v = m.lowerConstant(instr) + instr.MarkLowered() } else { - instr := def.Instr - if instr.Constant() { - // We inline all the constant instructions so that we could reduce the register usage. - v = m.lowerConstant(instr) - instr.MarkLowered() - } else { - if n := def.N; n == 0 { - v = m.c.VRegOf(instr.Return()) - } else { - _, rs := instr.Returns() - v = m.c.VRegOf(rs[n-1]) - } - } + v = m.c.VRegOf(def.V) } return newOperandReg(v) } diff --git a/internal/engine/wazevo/backend/isa/arm64/lower_instr_operands.go b/internal/engine/wazevo/backend/isa/arm64/lower_instr_operands.go index d9fbf1789b..1f56435605 100644 --- a/internal/engine/wazevo/backend/isa/arm64/lower_instr_operands.go +++ b/internal/engine/wazevo/backend/isa/arm64/lower_instr_operands.go @@ -163,8 +163,8 @@ func (o operand) assignReg(v regalloc.VReg) operand { // `mode` is used to extend the operand if the bit length is smaller than mode.bits(). // If the operand can be expressed as operandKindImm12, `mode` is ignored. func (m *machine) getOperand_Imm12_ER_SR_NR(def *backend.SSAValueDefinition, mode extMode) (op operand) { - if def.IsFromBlockParam() { - return operandNR(def.BlkParamVReg) + if !def.IsFromInstr() { + return operandNR(m.compiler.VRegOf(def.V)) } instr := def.Instr @@ -180,8 +180,8 @@ func (m *machine) getOperand_Imm12_ER_SR_NR(def *backend.SSAValueDefinition, mod // getOperand_MaybeNegatedImm12_ER_SR_NR is almost the same as getOperand_Imm12_ER_SR_NR, but this might negate the immediate value. // If the immediate value is negated, the second return value is true, otherwise always false. func (m *machine) getOperand_MaybeNegatedImm12_ER_SR_NR(def *backend.SSAValueDefinition, mode extMode) (op operand, negatedImm12 bool) { - if def.IsFromBlockParam() { - return operandNR(def.BlkParamVReg), false + if !def.IsFromInstr() { + return operandNR(m.compiler.VRegOf(def.V)), false } instr := def.Instr @@ -193,7 +193,7 @@ func (m *machine) getOperand_MaybeNegatedImm12_ER_SR_NR(def *backend.SSAValueDef } signExtended := int64(c) - if def.SSAValue().Type().Bits() == 32 { + if def.V.Type().Bits() == 32 { signExtended = (signExtended << 32) >> 32 } negatedWithoutSign := -signExtended @@ -209,8 +209,8 @@ func (m *machine) getOperand_MaybeNegatedImm12_ER_SR_NR(def *backend.SSAValueDef // // `mode` is used to extend the operand if the bit length is smaller than mode.bits(). func (m *machine) getOperand_ER_SR_NR(def *backend.SSAValueDefinition, mode extMode) (op operand) { - if def.IsFromBlockParam() { - return operandNR(def.BlkParamVReg) + if !def.IsFromInstr() { + return operandNR(m.compiler.VRegOf(def.V)) } if m.compiler.MatchInstr(def, ssa.OpcodeSExtend) || m.compiler.MatchInstr(def, ssa.OpcodeUExtend) { @@ -252,8 +252,8 @@ func (m *machine) getOperand_ER_SR_NR(def *backend.SSAValueDefinition, mode extM // // `mode` is used to extend the operand if the bit length is smaller than mode.bits(). func (m *machine) getOperand_SR_NR(def *backend.SSAValueDefinition, mode extMode) (op operand) { - if def.IsFromBlockParam() { - return operandNR(def.BlkParamVReg) + if !def.IsFromInstr() { + return operandNR(m.compiler.VRegOf(def.V)) } if m.compiler.MatchInstr(def, ssa.OpcodeIshl) { @@ -274,8 +274,8 @@ func (m *machine) getOperand_SR_NR(def *backend.SSAValueDefinition, mode extMode // getOperand_ShiftImm_NR returns an operand of either operandKindShiftImm or operandKindNR from the given value (defined by `def). func (m *machine) getOperand_ShiftImm_NR(def *backend.SSAValueDefinition, mode extMode, shiftBitWidth byte) (op operand) { - if def.IsFromBlockParam() { - return operandNR(def.BlkParamVReg) + if !def.IsFromInstr() { + return operandNR(m.compiler.VRegOf(def.V)) } instr := def.Instr @@ -291,26 +291,16 @@ func (m *machine) getOperand_ShiftImm_NR(def *backend.SSAValueDefinition, mode e // `mode` is used to extend the operand if the bit length is smaller than mode.bits(). func (m *machine) getOperand_NR(def *backend.SSAValueDefinition, mode extMode) (op operand) { var v regalloc.VReg - if def.IsFromBlockParam() { - v = def.BlkParamVReg + if def.IsFromInstr() && def.Instr.Constant() { + // We inline all the constant instructions so that we could reduce the register usage. + v = m.lowerConstant(def.Instr) + def.Instr.MarkLowered() } else { - instr := def.Instr - if instr.Constant() { - // We inline all the constant instructions so that we could reduce the register usage. - v = m.lowerConstant(instr) - instr.MarkLowered() - } else { - if n := def.N; n == 0 { - v = m.compiler.VRegOf(instr.Return()) - } else { - _, rs := instr.Returns() - v = m.compiler.VRegOf(rs[n-1]) - } - } + v = m.compiler.VRegOf(def.V) } r := v - switch inBits := def.SSAValue().Type().Bits(); { + switch inBits := def.V.Type().Bits(); { case mode == extModeNone: case inBits == 32 && (mode == extModeZeroExtend32 || mode == extModeSignExtend32): case inBits == 32 && mode == extModeZeroExtend64: diff --git a/internal/engine/wazevo/backend/isa/arm64/lower_instr_operands_test.go b/internal/engine/wazevo/backend/isa/arm64/lower_instr_operands_test.go index 114946528e..ba7520fb5c 100644 --- a/internal/engine/wazevo/backend/isa/arm64/lower_instr_operands_test.go +++ b/internal/engine/wazevo/backend/isa/arm64/lower_instr_operands_test.go @@ -40,7 +40,8 @@ func TestMachine_getOperand_NR(t *testing.T) { setup: func(ctx *mockCompiler, builder ssa.Builder, m *machine) (def *backend.SSAValueDefinition, mode extMode) { blk := builder.CurrentBlock() v := blk.AddParam(builder, ssa.TypeI64) - def = &backend.SSAValueDefinition{BlkParamVReg: regToVReg(x4), BlockParamValue: v} + ctx.vRegMap[v] = regToVReg(x4) + def = &backend.SSAValueDefinition{V: v} return def, extModeZeroExtend64 }, exp: operandNR(regToVReg(x4)), @@ -50,7 +51,8 @@ func TestMachine_getOperand_NR(t *testing.T) { setup: func(ctx *mockCompiler, builder ssa.Builder, m *machine) (def *backend.SSAValueDefinition, mode extMode) { blk := builder.CurrentBlock() v := blk.AddParam(builder, ssa.TypeI32) - def = &backend.SSAValueDefinition{BlkParamVReg: regToVReg(x4), BlockParamValue: v} + ctx.vRegMap[v] = regToVReg(x4) + def = &backend.SSAValueDefinition{V: v} return def, extModeZeroExtend64 }, exp: operandNR(regalloc.VReg(1).SetRegType(regalloc.RegTypeInt)), @@ -61,7 +63,8 @@ func TestMachine_getOperand_NR(t *testing.T) { setup: func(ctx *mockCompiler, builder ssa.Builder, m *machine) (def *backend.SSAValueDefinition, mode extMode) { blk := builder.CurrentBlock() v := blk.AddParam(builder, ssa.TypeI32) - def = &backend.SSAValueDefinition{BlkParamVReg: regToVReg(x4), BlockParamValue: v} + ctx.vRegMap[v] = regToVReg(x4) + def = &backend.SSAValueDefinition{V: v} return def, extModeSignExtend64 }, exp: operandNR(regalloc.VReg(1).SetRegType(regalloc.RegTypeInt)), @@ -73,7 +76,7 @@ func TestMachine_getOperand_NR(t *testing.T) { instr := builder.AllocateInstruction() instr.AsIconst32(0xf00000f) builder.InsertInstruction(instr) - def = &backend.SSAValueDefinition{Instr: instr, N: 0} + def = &backend.SSAValueDefinition{Instr: instr, V: instr.Return()} ctx.vRegCounter = 99 return }, @@ -93,7 +96,7 @@ func TestMachine_getOperand_NR(t *testing.T) { builder.InsertInstruction(c) _, rs := c.Returns() ctx.vRegMap[rs[1]] = regalloc.VReg(50) - def = &backend.SSAValueDefinition{Instr: c, N: 2} + def = &backend.SSAValueDefinition{Instr: c, V: rs[1]} return }, exp: operandNR(regalloc.VReg(50)), @@ -132,14 +135,16 @@ func TestMachine_getOperand_SR_NR(t *testing.T) { ishl.AsIshl(addResult, amountVal) builder.InsertInstruction(ishl) - ctx.definitions[p1] = &backend.SSAValueDefinition{BlkParamVReg: regalloc.VReg(1), BlockParamValue: p1} - ctx.definitions[p2] = &backend.SSAValueDefinition{BlkParamVReg: regalloc.VReg(2), BlockParamValue: p2} - ctx.definitions[addResult] = &backend.SSAValueDefinition{Instr: add, N: 0} - ctx.definitions[amountVal] = &backend.SSAValueDefinition{Instr: amount, N: 0} + ctx.vRegMap[p1] = regalloc.VReg(1) + ctx.definitions[p1] = &backend.SSAValueDefinition{V: p1} + ctx.vRegMap[p2] = regalloc.VReg(2) + ctx.definitions[p2] = &backend.SSAValueDefinition{V: p2} + ctx.definitions[addResult] = &backend.SSAValueDefinition{Instr: add, V: addResult} + ctx.definitions[amountVal] = &backend.SSAValueDefinition{Instr: amount, V: amountVal} ctx.vRegMap[addResult] = regalloc.VReg(1234) ctx.vRegMap[ishl.Return()] = regalloc.VReg(10) - def = &backend.SSAValueDefinition{Instr: ishl, N: 0} + def = &backend.SSAValueDefinition{Instr: ishl, V: ishl.Return()} mode = extModeNone verify = func(t *testing.T) { require.True(t, ishl.Lowered()) @@ -159,7 +164,8 @@ func TestMachine_getOperand_SR_NR(t *testing.T) { setup: func(ctx *mockCompiler, builder ssa.Builder, m *machine) (def *backend.SSAValueDefinition, mode extMode, verify func(t *testing.T)) { blk := builder.CurrentBlock() v := blk.AddParam(builder, ssa.TypeI64) - def = &backend.SSAValueDefinition{BlkParamVReg: regToVReg(x4), BlockParamValue: v} + ctx.vRegMap[v] = regToVReg(x4) + def = &backend.SSAValueDefinition{V: v} return def, extModeNone, func(t *testing.T) {} }, exp: operandNR(regToVReg(x4)), @@ -181,13 +187,16 @@ func TestMachine_getOperand_SR_NR(t *testing.T) { ishl.AsIshl(addResult, p3) builder.InsertInstruction(ishl) - ctx.definitions[p1] = &backend.SSAValueDefinition{BlkParamVReg: regalloc.VReg(1), BlockParamValue: p1} - ctx.definitions[p2] = &backend.SSAValueDefinition{BlkParamVReg: regalloc.VReg(2), BlockParamValue: p2} - ctx.definitions[p3] = &backend.SSAValueDefinition{BlkParamVReg: regalloc.VReg(3), BlockParamValue: p3} - ctx.definitions[addResult] = &backend.SSAValueDefinition{Instr: add, N: 0} + ctx.vRegMap[p1] = regalloc.VReg(1) + ctx.definitions[p1] = &backend.SSAValueDefinition{V: p1} + ctx.vRegMap[p2] = regalloc.VReg(2) + ctx.definitions[p2] = &backend.SSAValueDefinition{V: p2} + ctx.vRegMap[p3] = regalloc.VReg(3) + ctx.definitions[p3] = &backend.SSAValueDefinition{V: p3} + ctx.definitions[addResult] = &backend.SSAValueDefinition{Instr: add, V: addResult} ctx.vRegMap[addResult] = regalloc.VReg(1234) // whatever is fine. ctx.vRegMap[ishl.Return()] = regalloc.VReg(10) - def = &backend.SSAValueDefinition{Instr: ishl, N: 0} + def = &backend.SSAValueDefinition{Instr: ishl, V: ishl.Return()} return def, extModeNone, func(t *testing.T) {} }, exp: operandNR(regalloc.VReg(10)), @@ -221,14 +230,16 @@ func TestMachine_getOperand_SR_NR(t *testing.T) { ishl.AsIshl(addResult, amountVal) builder.InsertInstruction(ishl) - ctx.definitions[p1] = &backend.SSAValueDefinition{BlkParamVReg: regalloc.VReg(1), BlockParamValue: p1} - ctx.definitions[p2] = &backend.SSAValueDefinition{BlkParamVReg: regalloc.VReg(2), BlockParamValue: p2} - ctx.definitions[addResult] = &backend.SSAValueDefinition{Instr: add, N: 0} - ctx.definitions[amountVal] = &backend.SSAValueDefinition{Instr: amount, N: 0} + ctx.vRegMap[p1] = regalloc.VReg(1) + ctx.definitions[p1] = &backend.SSAValueDefinition{V: p1} + ctx.vRegMap[p2] = regalloc.VReg(2) + ctx.definitions[p2] = &backend.SSAValueDefinition{V: p2} + ctx.definitions[addResult] = &backend.SSAValueDefinition{Instr: add, V: addResult} + ctx.definitions[amountVal] = &backend.SSAValueDefinition{Instr: amount, V: amountVal} ctx.vRegMap[addResult] = regalloc.VReg(1234) ctx.vRegMap[ishl.Return()] = regalloc.VReg(10) - def = &backend.SSAValueDefinition{Instr: ishl, N: 0} + def = &backend.SSAValueDefinition{Instr: ishl} mode = extModeNone verify = func(t *testing.T) { require.True(t, ishl.Lowered()) @@ -254,11 +265,11 @@ func TestMachine_getOperand_SR_NR(t *testing.T) { ishl.AsIshl(target.Return(), amountVal) builder.InsertInstruction(ishl) - ctx.definitions[targetVal] = &backend.SSAValueDefinition{Instr: target, N: 0} - ctx.definitions[amountVal] = &backend.SSAValueDefinition{Instr: amount, N: 0} + ctx.definitions[targetVal] = &backend.SSAValueDefinition{Instr: target, V: targetVal} + ctx.definitions[amountVal] = &backend.SSAValueDefinition{Instr: amount, V: amountVal} ctx.vRegMap[targetVal] = regalloc.VReg(1234) ctx.vRegMap[ishl.Return()] = regalloc.VReg(10) - def = &backend.SSAValueDefinition{Instr: ishl, N: 0} + def = &backend.SSAValueDefinition{Instr: ishl} mode = extModeNone verify = func(t *testing.T) { require.True(t, ishl.Lowered()) @@ -323,7 +334,8 @@ func TestMachine_getOperand_ER_SR_NR(t *testing.T) { setup: func(ctx *mockCompiler, builder ssa.Builder, m *machine) (def *backend.SSAValueDefinition, mode extMode, verify func(t *testing.T)) { blk := builder.CurrentBlock() v := blk.AddParam(builder, ssa.TypeI64) - def = &backend.SSAValueDefinition{BlkParamVReg: regToVReg(x4), BlockParamValue: v} + ctx.vRegMap[v] = regToVReg(x4) + def = &backend.SSAValueDefinition{V: v} return def, extModeZeroExtend64, func(t *testing.T) {} }, exp: operandNR(regToVReg(x4)), @@ -359,9 +371,9 @@ func TestMachine_getOperand_ER_SR_NR(t *testing.T) { } builder.InsertInstruction(ext) extArg := ext.Arg() - ctx.vRegMap[ext.Arg()] = regalloc.VReg(10) - ctx.definitions[v] = &backend.SSAValueDefinition{BlkParamVReg: regalloc.VReg(10), BlockParamValue: extArg} - def = &backend.SSAValueDefinition{Instr: ext, N: 0} + ctx.vRegMap[extArg] = regalloc.VReg(10) + ctx.definitions[v] = &backend.SSAValueDefinition{V: extArg} + def = &backend.SSAValueDefinition{Instr: ext, V: ext.Return()} return def, extModeNone, func(t *testing.T) { require.True(t, ext.Lowered()) } @@ -571,16 +583,11 @@ func TestMachine_getOperand_ER_SR_NR(t *testing.T) { ctx.vRegMap[ext.Return()] = resultVReg if c.extArgConst { iconst := builder.AllocateInstruction().AsIconst32(0xffff).Insert(builder) - m.compiler.(*mockCompiler).definitions[extArg] = &backend.SSAValueDefinition{ - Instr: iconst, - } + m.compiler.(*mockCompiler).definitions[extArg] = &backend.SSAValueDefinition{Instr: iconst, V: iconst.Return()} } else { - m.compiler.(*mockCompiler).definitions[extArg] = &backend.SSAValueDefinition{ - BlkParamVReg: argVReg, - BlockParamValue: extArg, - } + m.compiler.(*mockCompiler).definitions[extArg] = &backend.SSAValueDefinition{V: extArg} } - def = &backend.SSAValueDefinition{Instr: ext, N: 0} + def = &backend.SSAValueDefinition{Instr: ext} return def, c.mode, func(t *testing.T) { require.Equal(t, c.lowered, ext.Lowered()) } @@ -605,7 +612,8 @@ func TestMachine_getOperand_Imm12_ER_SR_NR(t *testing.T) { setup: func(ctx *mockCompiler, builder ssa.Builder, m *machine) (def *backend.SSAValueDefinition, mode extMode) { blk := builder.CurrentBlock() v := blk.AddParam(builder, ssa.TypeI64) - def = &backend.SSAValueDefinition{BlkParamVReg: regToVReg(x4), BlockParamValue: v} + ctx.vRegMap[v] = regToVReg(x4) + def = &backend.SSAValueDefinition{V: v} return def, extModeZeroExtend64 }, exp: operandNR(regToVReg(x4)), @@ -616,7 +624,7 @@ func TestMachine_getOperand_Imm12_ER_SR_NR(t *testing.T) { cinst := builder.AllocateInstruction() cinst.AsIconst32(0xfff) builder.InsertInstruction(cinst) - def = &backend.SSAValueDefinition{Instr: cinst, N: 0} + def = &backend.SSAValueDefinition{Instr: cinst} ctx.currentGID = 0xff // const can be merged anytime, regardless of the group id. return }, @@ -628,7 +636,7 @@ func TestMachine_getOperand_Imm12_ER_SR_NR(t *testing.T) { cinst := builder.AllocateInstruction() cinst.AsIconst32(0xabc_000) builder.InsertInstruction(cinst) - def = &backend.SSAValueDefinition{Instr: cinst, N: 0} + def = &backend.SSAValueDefinition{Instr: cinst} ctx.currentGID = 0xff // const can be merged anytime, regardless of the group id. return }, @@ -658,7 +666,8 @@ func TestMachine_getOperand_MaybeNegatedImm12_ER_SR_NR(t *testing.T) { setup: func(ctx *mockCompiler, builder ssa.Builder, m *machine) (def *backend.SSAValueDefinition, mode extMode) { blk := builder.CurrentBlock() v := blk.AddParam(builder, ssa.TypeI64) - def = &backend.SSAValueDefinition{BlkParamVReg: regToVReg(x4), BlockParamValue: v} + ctx.vRegMap[v] = regToVReg(x4) + def = &backend.SSAValueDefinition{V: v} return def, extModeZeroExtend64 }, exp: operandNR(regToVReg(x4)), @@ -669,7 +678,7 @@ func TestMachine_getOperand_MaybeNegatedImm12_ER_SR_NR(t *testing.T) { cinst := builder.AllocateInstruction() cinst.AsIconst32(0xfff) builder.InsertInstruction(cinst) - def = &backend.SSAValueDefinition{Instr: cinst, N: 0} + def = &backend.SSAValueDefinition{Instr: cinst} ctx.currentGID = 0xff // const can be merged anytime, regardless of the group id. return }, @@ -682,7 +691,7 @@ func TestMachine_getOperand_MaybeNegatedImm12_ER_SR_NR(t *testing.T) { cinst := builder.AllocateInstruction() cinst.AsIconst32(uint32(c)) builder.InsertInstruction(cinst) - def = &backend.SSAValueDefinition{Instr: cinst, N: 0} + def = &backend.SSAValueDefinition{Instr: cinst, V: cinst.Return()} ctx.currentGID = 0xff // const can be merged anytime, regardless of the group id. return }, @@ -695,7 +704,7 @@ func TestMachine_getOperand_MaybeNegatedImm12_ER_SR_NR(t *testing.T) { cinst := builder.AllocateInstruction() cinst.AsIconst32(0xabc_000) builder.InsertInstruction(cinst) - def = &backend.SSAValueDefinition{Instr: cinst, N: 0} + def = &backend.SSAValueDefinition{Instr: cinst} ctx.currentGID = 0xff // const can be merged anytime, regardless of the group id. return }, @@ -708,7 +717,7 @@ func TestMachine_getOperand_MaybeNegatedImm12_ER_SR_NR(t *testing.T) { cinst := builder.AllocateInstruction() cinst.AsIconst32(uint32(c)) builder.InsertInstruction(cinst) - def = &backend.SSAValueDefinition{Instr: cinst, N: 0} + def = &backend.SSAValueDefinition{Instr: cinst, V: cinst.Return()} ctx.currentGID = 0xff // const can be merged anytime, regardless of the group id. return }, diff --git a/internal/engine/wazevo/backend/isa/arm64/lower_instr_test.go b/internal/engine/wazevo/backend/isa/arm64/lower_instr_test.go index 524811d780..9b8858a339 100644 --- a/internal/engine/wazevo/backend/isa/arm64/lower_instr_test.go +++ b/internal/engine/wazevo/backend/isa/arm64/lower_instr_test.go @@ -46,8 +46,8 @@ func TestMachine_LowerConditionalBranch(t *testing.T) { cmpVal := cmpInstr.Return() ctx.vRegMap[cmpVal] = 3 - ctx.definitions[val1] = &backend.SSAValueDefinition{BlkParamVReg: ctx.vRegMap[val1], BlockParamValue: val1} - ctx.definitions[val2] = &backend.SSAValueDefinition{BlkParamVReg: ctx.vRegMap[val2], BlockParamValue: val2} + ctx.definitions[val1] = &backend.SSAValueDefinition{V: val1} + ctx.definitions[val2] = &backend.SSAValueDefinition{V: val2} ctx.definitions[cmpVal] = &backend.SSAValueDefinition{Instr: cmpInstr} b := builder.AllocateInstruction() if brz { @@ -74,7 +74,7 @@ func TestMachine_LowerConditionalBranch(t *testing.T) { icmp.AsIcmp(v1, v2, ssa.IntegerCmpCondEqual) builder.InsertInstruction(icmp) icmpVal := icmp.Return() - ctx.definitions[v1] = &backend.SSAValueDefinition{BlkParamVReg: intToVReg(1), BlockParamValue: v1} + ctx.definitions[v1] = &backend.SSAValueDefinition{V: v1} ctx.definitions[v2] = &backend.SSAValueDefinition{Instr: iconst} ctx.definitions[icmpVal] = &backend.SSAValueDefinition{Instr: icmp} ctx.vRegMap[v1], ctx.vRegMap[v2], ctx.vRegMap[icmpVal] = intToVReg(1), intToVReg(2), intToVReg(3) @@ -105,7 +105,7 @@ func TestMachine_LowerConditionalBranch(t *testing.T) { icmp.AsIcmp(v1, v2, ssa.IntegerCmpCondEqual) builder.InsertInstruction(icmp) icmpVal := icmp.Return() - ctx.definitions[icmpVal] = &backend.SSAValueDefinition{Instr: icmp} + ctx.definitions[icmpVal] = &backend.SSAValueDefinition{Instr: icmp, V: icmpVal} ctx.vRegMap[v1], ctx.vRegMap[v2], ctx.vRegMap[icmpVal] = intToVReg(1), intToVReg(2), intToVReg(3) brz := builder.AllocateInstruction() diff --git a/internal/engine/wazevo/backend/isa/arm64/lower_mem_test.go b/internal/engine/wazevo/backend/isa/arm64/lower_mem_test.go index e7a054d75a..2dce0633dd 100644 --- a/internal/engine/wazevo/backend/isa/arm64/lower_mem_test.go +++ b/internal/engine/wazevo/backend/isa/arm64/lower_mem_test.go @@ -296,7 +296,8 @@ func TestMachine_collectAddends(t *testing.T) { v1000, v2000 := regalloc.VReg(1000).SetRegType(regalloc.RegTypeInt), regalloc.VReg(2000).SetRegType(regalloc.RegTypeInt) addParam := func(ctx *mockCompiler, b ssa.Builder, typ ssa.Type) ssa.Value { p := b.CurrentBlock().AddParam(b, typ) - ctx.definitions[p] = &backend.SSAValueDefinition{BlockParamValue: p, BlkParamVReg: v1000} + ctx.vRegMap[p] = v1000 + ctx.definitions[p] = &backend.SSAValueDefinition{V: p} return p } insertI32Const := func(m *mockCompiler, b ssa.Builder, v uint32) *ssa.Instruction { @@ -310,14 +311,14 @@ func TestMachine_collectAddends(t *testing.T) { inst := b.AllocateInstruction() inst.AsIconst64(v) b.InsertInstruction(inst) - m.definitions[inst.Return()] = &backend.SSAValueDefinition{Instr: inst} + m.definitions[inst.Return()] = &backend.SSAValueDefinition{Instr: inst, V: inst.Return()} return inst } insertIadd := func(m *mockCompiler, b ssa.Builder, lhs, rhs ssa.Value) *ssa.Instruction { inst := b.AllocateInstruction() inst.AsIadd(lhs, rhs) b.InsertInstruction(inst) - m.definitions[inst.Return()] = &backend.SSAValueDefinition{Instr: inst} + m.definitions[inst.Return()] = &backend.SSAValueDefinition{Instr: inst, V: inst.Return()} return inst } insertExt := func(m *mockCompiler, b ssa.Builder, v ssa.Value, from, to byte, signed bool) *ssa.Instruction { @@ -328,7 +329,7 @@ func TestMachine_collectAddends(t *testing.T) { inst.AsUExtend(v, from, to) } b.InsertInstruction(inst) - m.definitions[inst.Return()] = &backend.SSAValueDefinition{Instr: inst} + m.definitions[inst.Return()] = &backend.SSAValueDefinition{Instr: inst, V: v} return inst } diff --git a/internal/engine/wazevo/backend/vdef.go b/internal/engine/wazevo/backend/vdef.go index 0951f9ab80..3c66a94ad4 100644 --- a/internal/engine/wazevo/backend/vdef.go +++ b/internal/engine/wazevo/backend/vdef.go @@ -1,22 +1,15 @@ package backend import ( - "github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc" "github.com/tetratelabs/wazero/internal/engine/wazevo/ssa" ) // SSAValueDefinition represents a definition of an SSA value. +// TODO: this eventually should be deleted. type SSAValueDefinition struct { - // BlockParamValue is valid if Instr == nil - BlockParamValue ssa.Value - - // BlkParamVReg is valid if Instr == nil - BlkParamVReg regalloc.VReg - + V ssa.Value // Instr is not nil if this is a definition from an instruction. Instr *ssa.Instruction - // N is the index of the return value in the instr's return values list. - N int // RefCount is the number of references to the result. RefCount uint32 } @@ -24,20 +17,3 @@ type SSAValueDefinition struct { func (d *SSAValueDefinition) IsFromInstr() bool { return d.Instr != nil } - -func (d *SSAValueDefinition) IsFromBlockParam() bool { - return d.Instr == nil -} - -func (d *SSAValueDefinition) SSAValue() ssa.Value { - if d.IsFromBlockParam() { - return d.BlockParamValue - } else { - r, rs := d.Instr.Returns() - if d.N == 0 { - return r - } else { - return rs[d.N-1] - } - } -}