inst,ir: cancelling inputs (#92)
Adds support for a `CancellingInputs` instruction flag, to indicate cases like `XORQ R10, R10` where the instruction actually does not depend on the value of `R10` at all. Closes #89
This commit is contained in:
committed by
GitHub
parent
8f97788836
commit
d43efabdbe
10
ir/ir.go
10
ir/ir.go
@@ -42,9 +42,10 @@ type Instruction struct {
|
||||
Inputs []operand.Op
|
||||
Outputs []operand.Op
|
||||
|
||||
IsTerminal bool
|
||||
IsBranch bool
|
||||
IsConditional bool
|
||||
IsTerminal bool
|
||||
IsBranch bool
|
||||
IsConditional bool
|
||||
CancellingInputs bool
|
||||
|
||||
// CFG.
|
||||
Pred []*Instruction
|
||||
@@ -88,6 +89,9 @@ func (i Instruction) InputRegisters() []reg.Register {
|
||||
for _, op := range i.Inputs {
|
||||
rs = append(rs, operand.Registers(op)...)
|
||||
}
|
||||
if i.CancellingInputs && rs[0] == rs[1] {
|
||||
rs = []reg.Register{}
|
||||
}
|
||||
for _, op := range i.Outputs {
|
||||
if operand.IsMem(op) {
|
||||
rs = append(rs, operand.Registers(op)...)
|
||||
|
||||
@@ -3,6 +3,10 @@ package ir
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/mmcloughlin/avo/operand"
|
||||
|
||||
"github.com/mmcloughlin/avo/reg"
|
||||
)
|
||||
|
||||
func TestFunctionLabels(t *testing.T) {
|
||||
@@ -20,3 +24,72 @@ func TestFunctionLabels(t *testing.T) {
|
||||
t.Fatalf("f.Labels() = %v; expect %v", got, expect)
|
||||
}
|
||||
}
|
||||
|
||||
func TestInputRegisters(t *testing.T) {
|
||||
cases := []struct {
|
||||
Name string
|
||||
Inst *Instruction
|
||||
Expect []reg.Register
|
||||
}{
|
||||
{
|
||||
Name: "reg",
|
||||
Inst: &Instruction{
|
||||
Inputs: []operand.Op{
|
||||
reg.RAX,
|
||||
reg.R13,
|
||||
},
|
||||
Outputs: []operand.Op{
|
||||
reg.RBX,
|
||||
},
|
||||
},
|
||||
Expect: []reg.Register{reg.RAX, reg.R13},
|
||||
},
|
||||
{
|
||||
Name: "mem",
|
||||
Inst: &Instruction{
|
||||
Inputs: []operand.Op{
|
||||
operand.Mem{
|
||||
Base: reg.RSI,
|
||||
Index: reg.RDI,
|
||||
},
|
||||
reg.R13,
|
||||
},
|
||||
Outputs: []operand.Op{
|
||||
operand.Mem{
|
||||
Base: reg.R9,
|
||||
Index: reg.R11,
|
||||
},
|
||||
},
|
||||
},
|
||||
Expect: []reg.Register{
|
||||
reg.RSI,
|
||||
reg.RDI,
|
||||
reg.R13,
|
||||
reg.R9,
|
||||
reg.R11,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "cancelling_inputs",
|
||||
Inst: &Instruction{
|
||||
CancellingInputs: true,
|
||||
Inputs: []operand.Op{
|
||||
reg.R13,
|
||||
reg.R13,
|
||||
},
|
||||
Outputs: []operand.Op{
|
||||
operand.Mem{
|
||||
Base: reg.R9,
|
||||
Index: reg.R11,
|
||||
},
|
||||
},
|
||||
},
|
||||
Expect: []reg.Register{reg.R9, reg.R11},
|
||||
},
|
||||
}
|
||||
for _, c := range cases {
|
||||
if got := c.Inst.InputRegisters(); !reflect.DeepEqual(got, c.Expect) {
|
||||
t.Errorf("%s: got %v; expect %v", c.Inst.Opcode, got, c.Expect)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user