mirror of
https://github.com/golang/go
synced 2024-10-04 17:21:20 -06:00
[dev.ssa] cmd/compile: handle Div, Convert, GetClosurePtr etc. on ARM
This CL adds support of Div, Mod, Convert, GetClosurePtr and 64-bit indexing support to SSA backend for ARM. Add tests for 64-bit indexing to cmd/compile/internal/gc/testdata/string_ssa.go. Tests cmd/compile/internal/gc/testdata/*_ssa.go passed, except compound_ssa.go and fp_ssa.go. Progress on SSA for ARM. Still not complete. Essentially the only unsupported part is floating point. Updates #15365. Change-Id: I269e88b67f641c25e7a813d910c96d356d236bff Reviewed-on: https://go-review.googlesource.com/23542 Reviewed-by: David Chase <drchase@google.com>
This commit is contained in:
parent
4636d02244
commit
e78d90beeb
@ -84,7 +84,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
|||||||
// input args need no code
|
// input args need no code
|
||||||
case ssa.OpSP, ssa.OpSB:
|
case ssa.OpSP, ssa.OpSB:
|
||||||
// nothing to do
|
// nothing to do
|
||||||
case ssa.OpCopy:
|
case ssa.OpCopy, ssa.OpARMMOVWconvert:
|
||||||
if v.Type.IsMemory() {
|
if v.Type.IsMemory() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -148,6 +148,21 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
|||||||
} else {
|
} else {
|
||||||
p.To.Name = obj.NAME_AUTO
|
p.To.Name = obj.NAME_AUTO
|
||||||
}
|
}
|
||||||
|
case ssa.OpARMDIV,
|
||||||
|
ssa.OpARMDIVU,
|
||||||
|
ssa.OpARMMOD,
|
||||||
|
ssa.OpARMMODU:
|
||||||
|
// Note: for software division the assembler rewrite these
|
||||||
|
// instructions to sequence of instructions:
|
||||||
|
// - it puts numerator in R11 and denominator in g.m.divmod
|
||||||
|
// and call (say) _udiv
|
||||||
|
// - _udiv saves R0-R3 on stack and call udiv, restores R0-R3
|
||||||
|
// before return
|
||||||
|
// - udiv does the actual work
|
||||||
|
//TODO: set approperiate regmasks and call udiv directly?
|
||||||
|
// need to be careful for negative case
|
||||||
|
// Or, as soft div is already expensive, we don't care?
|
||||||
|
fallthrough
|
||||||
case ssa.OpARMADD,
|
case ssa.OpARMADD,
|
||||||
ssa.OpARMADC,
|
ssa.OpARMADC,
|
||||||
ssa.OpARMSUB,
|
ssa.OpARMSUB,
|
||||||
@ -552,6 +567,13 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
|||||||
ssa.OpARMLoweredSelect0,
|
ssa.OpARMLoweredSelect0,
|
||||||
ssa.OpARMLoweredSelect1:
|
ssa.OpARMLoweredSelect1:
|
||||||
// nothing to do
|
// nothing to do
|
||||||
|
case ssa.OpARMLoweredGetClosurePtr:
|
||||||
|
// Output is hardwired to R7 (arm.REGCTXT) only,
|
||||||
|
// and R7 contains the closure pointer on
|
||||||
|
// closure entry, and this "instruction"
|
||||||
|
// is scheduled to the very beginning
|
||||||
|
// of the entry block.
|
||||||
|
// nothing to do here.
|
||||||
default:
|
default:
|
||||||
v.Unimplementedf("genValue not implemented: %s", v.LongString())
|
v.Unimplementedf("genValue not implemented: %s", v.LongString())
|
||||||
}
|
}
|
||||||
|
@ -1945,7 +1945,7 @@ func (s *state) expr(n *Node) *ssa.Value {
|
|||||||
case n.Left.Type.IsString():
|
case n.Left.Type.IsString():
|
||||||
a := s.expr(n.Left)
|
a := s.expr(n.Left)
|
||||||
i := s.expr(n.Right)
|
i := s.expr(n.Right)
|
||||||
i = s.extendIndex(i)
|
i = s.extendIndex(i, Panicindex)
|
||||||
if !n.Bounded {
|
if !n.Bounded {
|
||||||
len := s.newValue1(ssa.OpStringLen, Types[TINT], a)
|
len := s.newValue1(ssa.OpStringLen, Types[TINT], a)
|
||||||
s.boundsCheck(i, len)
|
s.boundsCheck(i, len)
|
||||||
@ -2034,13 +2034,13 @@ func (s *state) expr(n *Node) *ssa.Value {
|
|||||||
var i, j, k *ssa.Value
|
var i, j, k *ssa.Value
|
||||||
low, high, max := n.SliceBounds()
|
low, high, max := n.SliceBounds()
|
||||||
if low != nil {
|
if low != nil {
|
||||||
i = s.extendIndex(s.expr(low))
|
i = s.extendIndex(s.expr(low), panicslice)
|
||||||
}
|
}
|
||||||
if high != nil {
|
if high != nil {
|
||||||
j = s.extendIndex(s.expr(high))
|
j = s.extendIndex(s.expr(high), panicslice)
|
||||||
}
|
}
|
||||||
if max != nil {
|
if max != nil {
|
||||||
k = s.extendIndex(s.expr(max))
|
k = s.extendIndex(s.expr(max), panicslice)
|
||||||
}
|
}
|
||||||
p, l, c := s.slice(n.Left.Type, v, i, j, k)
|
p, l, c := s.slice(n.Left.Type, v, i, j, k)
|
||||||
return s.newValue3(ssa.OpSliceMake, n.Type, p, l, c)
|
return s.newValue3(ssa.OpSliceMake, n.Type, p, l, c)
|
||||||
@ -2050,10 +2050,10 @@ func (s *state) expr(n *Node) *ssa.Value {
|
|||||||
var i, j *ssa.Value
|
var i, j *ssa.Value
|
||||||
low, high, _ := n.SliceBounds()
|
low, high, _ := n.SliceBounds()
|
||||||
if low != nil {
|
if low != nil {
|
||||||
i = s.extendIndex(s.expr(low))
|
i = s.extendIndex(s.expr(low), panicslice)
|
||||||
}
|
}
|
||||||
if high != nil {
|
if high != nil {
|
||||||
j = s.extendIndex(s.expr(high))
|
j = s.extendIndex(s.expr(high), panicslice)
|
||||||
}
|
}
|
||||||
p, l, _ := s.slice(n.Left.Type, v, i, j, nil)
|
p, l, _ := s.slice(n.Left.Type, v, i, j, nil)
|
||||||
return s.newValue2(ssa.OpStringMake, n.Type, p, l)
|
return s.newValue2(ssa.OpStringMake, n.Type, p, l)
|
||||||
@ -2743,7 +2743,7 @@ func (s *state) addr(n *Node, bounded bool) *ssa.Value {
|
|||||||
if n.Left.Type.IsSlice() {
|
if n.Left.Type.IsSlice() {
|
||||||
a := s.expr(n.Left)
|
a := s.expr(n.Left)
|
||||||
i := s.expr(n.Right)
|
i := s.expr(n.Right)
|
||||||
i = s.extendIndex(i)
|
i = s.extendIndex(i, Panicindex)
|
||||||
len := s.newValue1(ssa.OpSliceLen, Types[TINT], a)
|
len := s.newValue1(ssa.OpSliceLen, Types[TINT], a)
|
||||||
if !n.Bounded {
|
if !n.Bounded {
|
||||||
s.boundsCheck(i, len)
|
s.boundsCheck(i, len)
|
||||||
@ -2753,7 +2753,7 @@ func (s *state) addr(n *Node, bounded bool) *ssa.Value {
|
|||||||
} else { // array
|
} else { // array
|
||||||
a := s.addr(n.Left, bounded)
|
a := s.addr(n.Left, bounded)
|
||||||
i := s.expr(n.Right)
|
i := s.expr(n.Right)
|
||||||
i = s.extendIndex(i)
|
i = s.extendIndex(i, Panicindex)
|
||||||
len := s.constInt(Types[TINT], n.Left.Type.NumElem())
|
len := s.constInt(Types[TINT], n.Left.Type.NumElem())
|
||||||
if !n.Bounded {
|
if !n.Bounded {
|
||||||
s.boundsCheck(i, len)
|
s.boundsCheck(i, len)
|
||||||
@ -2894,12 +2894,11 @@ func (s *state) nilCheck(ptr *ssa.Value) {
|
|||||||
|
|
||||||
// boundsCheck generates bounds checking code. Checks if 0 <= idx < len, branches to exit if not.
|
// boundsCheck generates bounds checking code. Checks if 0 <= idx < len, branches to exit if not.
|
||||||
// Starts a new block on return.
|
// Starts a new block on return.
|
||||||
|
// idx is already converted to full int width.
|
||||||
func (s *state) boundsCheck(idx, len *ssa.Value) {
|
func (s *state) boundsCheck(idx, len *ssa.Value) {
|
||||||
if Debug['B'] != 0 {
|
if Debug['B'] != 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// TODO: convert index to full width?
|
|
||||||
// TODO: if index is 64-bit and we're compiling to 32-bit, check that high 32 bits are zero.
|
|
||||||
|
|
||||||
// bounds check
|
// bounds check
|
||||||
cmp := s.newValue2(ssa.OpIsInBounds, Types[TBOOL], idx, len)
|
cmp := s.newValue2(ssa.OpIsInBounds, Types[TBOOL], idx, len)
|
||||||
@ -2908,19 +2907,18 @@ func (s *state) boundsCheck(idx, len *ssa.Value) {
|
|||||||
|
|
||||||
// sliceBoundsCheck generates slice bounds checking code. Checks if 0 <= idx <= len, branches to exit if not.
|
// sliceBoundsCheck generates slice bounds checking code. Checks if 0 <= idx <= len, branches to exit if not.
|
||||||
// Starts a new block on return.
|
// Starts a new block on return.
|
||||||
|
// idx and len are already converted to full int width.
|
||||||
func (s *state) sliceBoundsCheck(idx, len *ssa.Value) {
|
func (s *state) sliceBoundsCheck(idx, len *ssa.Value) {
|
||||||
if Debug['B'] != 0 {
|
if Debug['B'] != 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// TODO: convert index to full width?
|
|
||||||
// TODO: if index is 64-bit and we're compiling to 32-bit, check that high 32 bits are zero.
|
|
||||||
|
|
||||||
// bounds check
|
// bounds check
|
||||||
cmp := s.newValue2(ssa.OpIsSliceInBounds, Types[TBOOL], idx, len)
|
cmp := s.newValue2(ssa.OpIsSliceInBounds, Types[TBOOL], idx, len)
|
||||||
s.check(cmp, panicslice)
|
s.check(cmp, panicslice)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If cmp (a bool) is true, panic using the given function.
|
// If cmp (a bool) is false, panic using the given function.
|
||||||
func (s *state) check(cmp *ssa.Value, fn *Node) {
|
func (s *state) check(cmp *ssa.Value, fn *Node) {
|
||||||
b := s.endBlock()
|
b := s.endBlock()
|
||||||
b.Kind = ssa.BlockIf
|
b.Kind = ssa.BlockIf
|
||||||
@ -4134,16 +4132,21 @@ func AddAux2(a *obj.Addr, v *ssa.Value, offset int64) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// extendIndex extends v to a full int width.
|
// extendIndex extends v to a full int width.
|
||||||
func (s *state) extendIndex(v *ssa.Value) *ssa.Value {
|
// panic using the given function if v does not fit in an int (only on 32-bit archs).
|
||||||
|
func (s *state) extendIndex(v *ssa.Value, panicfn *Node) *ssa.Value {
|
||||||
size := v.Type.Size()
|
size := v.Type.Size()
|
||||||
if size == s.config.IntSize {
|
if size == s.config.IntSize {
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
if size > s.config.IntSize {
|
if size > s.config.IntSize {
|
||||||
// TODO: truncate 64-bit indexes on 32-bit pointer archs. We'd need to test
|
// truncate 64-bit indexes on 32-bit pointer archs. Test the
|
||||||
// the high word and branch to out-of-bounds failure if it is not 0.
|
// high word and branch to out-of-bounds failure if it is not 0.
|
||||||
s.Unimplementedf("64->32 index truncation not implemented")
|
if Debug['B'] == 0 {
|
||||||
return v
|
hi := s.newValue1(ssa.OpInt64Hi, Types[TUINT32], v)
|
||||||
|
cmp := s.newValue2(ssa.OpEq32, Types[TBOOL], hi, s.constInt32(Types[TUINT32], 0))
|
||||||
|
s.check(cmp, panicfn)
|
||||||
|
}
|
||||||
|
return s.newValue1(ssa.OpTrunc64to32, Types[TINT], v)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extend value to the required size
|
// Extend value to the required size
|
||||||
|
@ -110,6 +110,67 @@ func testSmallIndexType() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//go:noinline
|
||||||
|
func testInt64Index_ssa(s string, i int64) byte {
|
||||||
|
return s[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:noinline
|
||||||
|
func testInt64Slice_ssa(s string, i, j int64) string {
|
||||||
|
return s[i:j]
|
||||||
|
}
|
||||||
|
|
||||||
|
func testInt64Index() {
|
||||||
|
tests := []struct {
|
||||||
|
i int64
|
||||||
|
j int64
|
||||||
|
b byte
|
||||||
|
s string
|
||||||
|
}{
|
||||||
|
{0, 5, 'B', "Below"},
|
||||||
|
{5, 10, 'E', "Exact"},
|
||||||
|
{10, 15, 'A', "Above"},
|
||||||
|
}
|
||||||
|
|
||||||
|
str := "BelowExactAbove"
|
||||||
|
for i, t := range tests {
|
||||||
|
if got := testInt64Index_ssa(str, t.i); got != t.b {
|
||||||
|
println("#", i, "got ", got, ", wanted", t.b)
|
||||||
|
failed = true
|
||||||
|
}
|
||||||
|
if got := testInt64Slice_ssa(str, t.i, t.j); got != t.s {
|
||||||
|
println("#", i, "got ", got, ", wanted", t.s)
|
||||||
|
failed = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testInt64IndexPanic() {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
println("paniced as expected")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
str := "foobar"
|
||||||
|
println("got ", testInt64Index_ssa(str, 1<<32+1))
|
||||||
|
println("expected to panic, but didn't")
|
||||||
|
failed = true
|
||||||
|
}
|
||||||
|
|
||||||
|
func testInt64SlicePanic() {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
println("paniced as expected")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
str := "foobar"
|
||||||
|
println("got ", testInt64Slice_ssa(str, 1<<32, 1<<32+1))
|
||||||
|
println("expected to panic, but didn't")
|
||||||
|
failed = true
|
||||||
|
}
|
||||||
|
|
||||||
//go:noinline
|
//go:noinline
|
||||||
func testStringElem_ssa(s string, i int) byte {
|
func testStringElem_ssa(s string, i int) byte {
|
||||||
return s[i]
|
return s[i]
|
||||||
@ -153,6 +214,9 @@ func main() {
|
|||||||
testSmallIndexType()
|
testSmallIndexType()
|
||||||
testStringElem()
|
testStringElem()
|
||||||
testStringElemConst()
|
testStringElemConst()
|
||||||
|
testInt64Index()
|
||||||
|
testInt64IndexPanic()
|
||||||
|
testInt64SlicePanic()
|
||||||
|
|
||||||
if failed {
|
if failed {
|
||||||
panic("failed")
|
panic("failed")
|
||||||
|
@ -31,6 +31,20 @@
|
|||||||
|
|
||||||
(Mul32uhilo x y) -> (MULLU x y)
|
(Mul32uhilo x y) -> (MULLU x y)
|
||||||
|
|
||||||
|
(Div32 x y) -> (DIV x y)
|
||||||
|
(Div32u x y) -> (DIVU x y)
|
||||||
|
(Div16 x y) -> (DIV (SignExt16to32 x) (SignExt16to32 y))
|
||||||
|
(Div16u x y) -> (DIVU (ZeroExt16to32 x) (ZeroExt16to32 y))
|
||||||
|
(Div8 x y) -> (DIV (SignExt8to32 x) (SignExt8to32 y))
|
||||||
|
(Div8u x y) -> (DIVU (ZeroExt8to32 x) (ZeroExt8to32 y))
|
||||||
|
|
||||||
|
(Mod32 x y) -> (MOD x y)
|
||||||
|
(Mod32u x y) -> (MODU x y)
|
||||||
|
(Mod16 x y) -> (MOD (SignExt16to32 x) (SignExt16to32 y))
|
||||||
|
(Mod16u x y) -> (MODU (ZeroExt16to32 x) (ZeroExt16to32 y))
|
||||||
|
(Mod8 x y) -> (MOD (SignExt8to32 x) (SignExt8to32 y))
|
||||||
|
(Mod8u x y) -> (MODU (ZeroExt8to32 x) (ZeroExt8to32 y))
|
||||||
|
|
||||||
(And32 x y) -> (AND x y)
|
(And32 x y) -> (AND x y)
|
||||||
(And16 x y) -> (AND x y)
|
(And16 x y) -> (AND x y)
|
||||||
(And8 x y) -> (AND x y)
|
(And8 x y) -> (AND x y)
|
||||||
@ -278,6 +292,9 @@
|
|||||||
(Select0 <t> x) && !t.IsFlags() -> (LoweredSelect0 x)
|
(Select0 <t> x) && !t.IsFlags() -> (LoweredSelect0 x)
|
||||||
(Select1 x) -> (LoweredSelect1 x)
|
(Select1 x) -> (LoweredSelect1 x)
|
||||||
|
|
||||||
|
(GetClosurePtr) -> (LoweredGetClosurePtr)
|
||||||
|
(Convert x mem) -> (MOVWconvert x mem)
|
||||||
|
|
||||||
// Absorb pseudo-ops into blocks.
|
// Absorb pseudo-ops into blocks.
|
||||||
(If (Equal cc) yes no) -> (EQ cc yes no)
|
(If (Equal cc) yes no) -> (EQ cc yes no)
|
||||||
(If (NotEqual cc) yes no) -> (NE cc yes no)
|
(If (NotEqual cc) yes no) -> (NE cc yes no)
|
||||||
|
@ -73,7 +73,7 @@ func init() {
|
|||||||
gpsp = gp | buildReg("SP")
|
gpsp = gp | buildReg("SP")
|
||||||
gpspsb = gpsp | buildReg("SB")
|
gpspsb = gpsp | buildReg("SB")
|
||||||
flags = buildReg("FLAGS")
|
flags = buildReg("FLAGS")
|
||||||
callerSave = gp
|
callerSave = gp | flags
|
||||||
)
|
)
|
||||||
// Common regInfo
|
// Common regInfo
|
||||||
var (
|
var (
|
||||||
@ -101,6 +101,10 @@ func init() {
|
|||||||
{name: "MUL", argLength: 2, reg: gp21, asm: "MUL", commutative: true}, // arg0 * arg1
|
{name: "MUL", argLength: 2, reg: gp21, asm: "MUL", commutative: true}, // arg0 * arg1
|
||||||
{name: "HMUL", argLength: 2, reg: gp21, asm: "MULL", commutative: true}, // (arg0 * arg1) >> 32, signed
|
{name: "HMUL", argLength: 2, reg: gp21, asm: "MULL", commutative: true}, // (arg0 * arg1) >> 32, signed
|
||||||
{name: "HMULU", argLength: 2, reg: gp21, asm: "MULLU", commutative: true}, // (arg0 * arg1) >> 32, unsigned
|
{name: "HMULU", argLength: 2, reg: gp21, asm: "MULLU", commutative: true}, // (arg0 * arg1) >> 32, unsigned
|
||||||
|
{name: "DIV", argLength: 2, reg: gp21cf, asm: "DIV"}, // arg0 / arg1, signed, soft div clobbers flags
|
||||||
|
{name: "DIVU", argLength: 2, reg: gp21cf, asm: "DIVU"}, // arg0 / arg1, unsighed
|
||||||
|
{name: "MOD", argLength: 2, reg: gp21cf, asm: "MOD"}, // arg0 % arg1, signed
|
||||||
|
{name: "MODU", argLength: 2, reg: gp21cf, asm: "MODU"}, // arg0 % arg1, unsigned
|
||||||
|
|
||||||
{name: "ADDS", argLength: 2, reg: gp21cf, asm: "ADD", commutative: true}, // arg0 + arg1, set carry flag
|
{name: "ADDS", argLength: 2, reg: gp21cf, asm: "ADD", commutative: true}, // arg0 + arg1, set carry flag
|
||||||
{name: "ADC", argLength: 3, reg: gp2flags1, asm: "ADC", commutative: true}, // arg0 + arg1 + carry, arg2=flags
|
{name: "ADC", argLength: 3, reg: gp2flags1, asm: "ADC", commutative: true}, // arg0 + arg1 + carry, arg2=flags
|
||||||
@ -251,6 +255,18 @@ func init() {
|
|||||||
clobbers: buildReg("R1 R2 FLAGS"),
|
clobbers: buildReg("R1 R2 FLAGS"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Scheduler ensures LoweredGetClosurePtr occurs only in entry block,
|
||||||
|
// and sorts it to the very beginning of the block to prevent other
|
||||||
|
// use of R7 (arm.REGCTXT, the closure pointer)
|
||||||
|
{name: "LoweredGetClosurePtr", reg: regInfo{outputs: []regMask{buildReg("R7")}}},
|
||||||
|
|
||||||
|
// MOVWconvert converts between pointers and integers.
|
||||||
|
// We have a special op for this so as to not confuse GC
|
||||||
|
// (particularly stack maps). It takes a memory arg so it
|
||||||
|
// gets correctly ordered with respect to GC safepoints.
|
||||||
|
// arg0=ptr/int arg1=mem, output=int/ptr
|
||||||
|
{name: "MOVWconvert", argLength: 2, reg: gp11, asm: "MOVW"},
|
||||||
}
|
}
|
||||||
|
|
||||||
blocks := []blockData{
|
blocks := []blockData{
|
||||||
|
@ -332,6 +332,10 @@ const (
|
|||||||
OpARMMUL
|
OpARMMUL
|
||||||
OpARMHMUL
|
OpARMHMUL
|
||||||
OpARMHMULU
|
OpARMHMULU
|
||||||
|
OpARMDIV
|
||||||
|
OpARMDIVU
|
||||||
|
OpARMMOD
|
||||||
|
OpARMMODU
|
||||||
OpARMADDS
|
OpARMADDS
|
||||||
OpARMADC
|
OpARMADC
|
||||||
OpARMSUBS
|
OpARMSUBS
|
||||||
@ -399,6 +403,8 @@ const (
|
|||||||
OpARMDUFFCOPY
|
OpARMDUFFCOPY
|
||||||
OpARMLoweredZero
|
OpARMLoweredZero
|
||||||
OpARMLoweredMove
|
OpARMLoweredMove
|
||||||
|
OpARMLoweredGetClosurePtr
|
||||||
|
OpARMMOVWconvert
|
||||||
|
|
||||||
OpAdd8
|
OpAdd8
|
||||||
OpAdd16
|
OpAdd16
|
||||||
@ -4008,6 +4014,66 @@ var opcodeTable = [...]opInfo{
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "DIV",
|
||||||
|
argLen: 2,
|
||||||
|
asm: arm.ADIV,
|
||||||
|
reg: regInfo{
|
||||||
|
inputs: []inputInfo{
|
||||||
|
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
|
||||||
|
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
|
||||||
|
},
|
||||||
|
clobbers: 65536, // FLAGS
|
||||||
|
outputs: []regMask{
|
||||||
|
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "DIVU",
|
||||||
|
argLen: 2,
|
||||||
|
asm: arm.ADIVU,
|
||||||
|
reg: regInfo{
|
||||||
|
inputs: []inputInfo{
|
||||||
|
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
|
||||||
|
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
|
||||||
|
},
|
||||||
|
clobbers: 65536, // FLAGS
|
||||||
|
outputs: []regMask{
|
||||||
|
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "MOD",
|
||||||
|
argLen: 2,
|
||||||
|
asm: arm.AMOD,
|
||||||
|
reg: regInfo{
|
||||||
|
inputs: []inputInfo{
|
||||||
|
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
|
||||||
|
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
|
||||||
|
},
|
||||||
|
clobbers: 65536, // FLAGS
|
||||||
|
outputs: []regMask{
|
||||||
|
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "MODU",
|
||||||
|
argLen: 2,
|
||||||
|
asm: arm.AMODU,
|
||||||
|
reg: regInfo{
|
||||||
|
inputs: []inputInfo{
|
||||||
|
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
|
||||||
|
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
|
||||||
|
},
|
||||||
|
clobbers: 65536, // FLAGS
|
||||||
|
outputs: []regMask{
|
||||||
|
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "ADDS",
|
name: "ADDS",
|
||||||
argLen: 2,
|
argLen: 2,
|
||||||
@ -4618,7 +4684,7 @@ var opcodeTable = [...]opInfo{
|
|||||||
auxType: auxSymOff,
|
auxType: auxSymOff,
|
||||||
argLen: 1,
|
argLen: 1,
|
||||||
reg: regInfo{
|
reg: regInfo{
|
||||||
clobbers: 5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
|
clobbers: 70655, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 FLAGS
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -4630,7 +4696,7 @@ var opcodeTable = [...]opInfo{
|
|||||||
{1, 128}, // R7
|
{1, 128}, // R7
|
||||||
{0, 13311}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 SP
|
{0, 13311}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 SP
|
||||||
},
|
},
|
||||||
clobbers: 5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
|
clobbers: 70655, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 FLAGS
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -4638,7 +4704,7 @@ var opcodeTable = [...]opInfo{
|
|||||||
auxType: auxInt64,
|
auxType: auxInt64,
|
||||||
argLen: 1,
|
argLen: 1,
|
||||||
reg: regInfo{
|
reg: regInfo{
|
||||||
clobbers: 5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
|
clobbers: 70655, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 FLAGS
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -4646,7 +4712,7 @@ var opcodeTable = [...]opInfo{
|
|||||||
auxType: auxInt64,
|
auxType: auxInt64,
|
||||||
argLen: 1,
|
argLen: 1,
|
||||||
reg: regInfo{
|
reg: regInfo{
|
||||||
clobbers: 5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
|
clobbers: 70655, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 FLAGS
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -4657,7 +4723,7 @@ var opcodeTable = [...]opInfo{
|
|||||||
inputs: []inputInfo{
|
inputs: []inputInfo{
|
||||||
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
|
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
|
||||||
},
|
},
|
||||||
clobbers: 5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
|
clobbers: 70655, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 FLAGS
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -4881,6 +4947,28 @@ var opcodeTable = [...]opInfo{
|
|||||||
clobbers: 65542, // R1 R2 FLAGS
|
clobbers: 65542, // R1 R2 FLAGS
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "LoweredGetClosurePtr",
|
||||||
|
argLen: 0,
|
||||||
|
reg: regInfo{
|
||||||
|
outputs: []regMask{
|
||||||
|
128, // R7
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "MOVWconvert",
|
||||||
|
argLen: 2,
|
||||||
|
asm: arm.AMOVW,
|
||||||
|
reg: regInfo{
|
||||||
|
inputs: []inputInfo{
|
||||||
|
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
|
||||||
|
},
|
||||||
|
outputs: []regMask{
|
||||||
|
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
name: "Add8",
|
name: "Add8",
|
||||||
|
@ -50,8 +50,22 @@ func rewriteValueARM(v *Value, config *Config) bool {
|
|||||||
return rewriteValueARM_OpConstBool(v, config)
|
return rewriteValueARM_OpConstBool(v, config)
|
||||||
case OpConstNil:
|
case OpConstNil:
|
||||||
return rewriteValueARM_OpConstNil(v, config)
|
return rewriteValueARM_OpConstNil(v, config)
|
||||||
|
case OpConvert:
|
||||||
|
return rewriteValueARM_OpConvert(v, config)
|
||||||
case OpDeferCall:
|
case OpDeferCall:
|
||||||
return rewriteValueARM_OpDeferCall(v, config)
|
return rewriteValueARM_OpDeferCall(v, config)
|
||||||
|
case OpDiv16:
|
||||||
|
return rewriteValueARM_OpDiv16(v, config)
|
||||||
|
case OpDiv16u:
|
||||||
|
return rewriteValueARM_OpDiv16u(v, config)
|
||||||
|
case OpDiv32:
|
||||||
|
return rewriteValueARM_OpDiv32(v, config)
|
||||||
|
case OpDiv32u:
|
||||||
|
return rewriteValueARM_OpDiv32u(v, config)
|
||||||
|
case OpDiv8:
|
||||||
|
return rewriteValueARM_OpDiv8(v, config)
|
||||||
|
case OpDiv8u:
|
||||||
|
return rewriteValueARM_OpDiv8u(v, config)
|
||||||
case OpEq16:
|
case OpEq16:
|
||||||
return rewriteValueARM_OpEq16(v, config)
|
return rewriteValueARM_OpEq16(v, config)
|
||||||
case OpEq32:
|
case OpEq32:
|
||||||
@ -74,6 +88,8 @@ func rewriteValueARM(v *Value, config *Config) bool {
|
|||||||
return rewriteValueARM_OpGeq8(v, config)
|
return rewriteValueARM_OpGeq8(v, config)
|
||||||
case OpGeq8U:
|
case OpGeq8U:
|
||||||
return rewriteValueARM_OpGeq8U(v, config)
|
return rewriteValueARM_OpGeq8U(v, config)
|
||||||
|
case OpGetClosurePtr:
|
||||||
|
return rewriteValueARM_OpGetClosurePtr(v, config)
|
||||||
case OpGoCall:
|
case OpGoCall:
|
||||||
return rewriteValueARM_OpGoCall(v, config)
|
return rewriteValueARM_OpGoCall(v, config)
|
||||||
case OpGreater16:
|
case OpGreater16:
|
||||||
@ -180,6 +196,18 @@ func rewriteValueARM(v *Value, config *Config) bool {
|
|||||||
return rewriteValueARM_OpARMMOVWload(v, config)
|
return rewriteValueARM_OpARMMOVWload(v, config)
|
||||||
case OpARMMOVWstore:
|
case OpARMMOVWstore:
|
||||||
return rewriteValueARM_OpARMMOVWstore(v, config)
|
return rewriteValueARM_OpARMMOVWstore(v, config)
|
||||||
|
case OpMod16:
|
||||||
|
return rewriteValueARM_OpMod16(v, config)
|
||||||
|
case OpMod16u:
|
||||||
|
return rewriteValueARM_OpMod16u(v, config)
|
||||||
|
case OpMod32:
|
||||||
|
return rewriteValueARM_OpMod32(v, config)
|
||||||
|
case OpMod32u:
|
||||||
|
return rewriteValueARM_OpMod32u(v, config)
|
||||||
|
case OpMod8:
|
||||||
|
return rewriteValueARM_OpMod8(v, config)
|
||||||
|
case OpMod8u:
|
||||||
|
return rewriteValueARM_OpMod8u(v, config)
|
||||||
case OpMove:
|
case OpMove:
|
||||||
return rewriteValueARM_OpMove(v, config)
|
return rewriteValueARM_OpMove(v, config)
|
||||||
case OpMul16:
|
case OpMul16:
|
||||||
@ -679,6 +707,21 @@ func rewriteValueARM_OpConstNil(v *Value, config *Config) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
func rewriteValueARM_OpConvert(v *Value, config *Config) bool {
|
||||||
|
b := v.Block
|
||||||
|
_ = b
|
||||||
|
// match: (Convert x mem)
|
||||||
|
// cond:
|
||||||
|
// result: (MOVWconvert x mem)
|
||||||
|
for {
|
||||||
|
x := v.Args[0]
|
||||||
|
mem := v.Args[1]
|
||||||
|
v.reset(OpARMMOVWconvert)
|
||||||
|
v.AddArg(x)
|
||||||
|
v.AddArg(mem)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
func rewriteValueARM_OpDeferCall(v *Value, config *Config) bool {
|
func rewriteValueARM_OpDeferCall(v *Value, config *Config) bool {
|
||||||
b := v.Block
|
b := v.Block
|
||||||
_ = b
|
_ = b
|
||||||
@ -694,6 +737,112 @@ func rewriteValueARM_OpDeferCall(v *Value, config *Config) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
func rewriteValueARM_OpDiv16(v *Value, config *Config) bool {
|
||||||
|
b := v.Block
|
||||||
|
_ = b
|
||||||
|
// match: (Div16 x y)
|
||||||
|
// cond:
|
||||||
|
// result: (DIV (SignExt16to32 x) (SignExt16to32 y))
|
||||||
|
for {
|
||||||
|
x := v.Args[0]
|
||||||
|
y := v.Args[1]
|
||||||
|
v.reset(OpARMDIV)
|
||||||
|
v0 := b.NewValue0(v.Line, OpSignExt16to32, config.fe.TypeInt32())
|
||||||
|
v0.AddArg(x)
|
||||||
|
v.AddArg(v0)
|
||||||
|
v1 := b.NewValue0(v.Line, OpSignExt16to32, config.fe.TypeInt32())
|
||||||
|
v1.AddArg(y)
|
||||||
|
v.AddArg(v1)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func rewriteValueARM_OpDiv16u(v *Value, config *Config) bool {
|
||||||
|
b := v.Block
|
||||||
|
_ = b
|
||||||
|
// match: (Div16u x y)
|
||||||
|
// cond:
|
||||||
|
// result: (DIVU (ZeroExt16to32 x) (ZeroExt16to32 y))
|
||||||
|
for {
|
||||||
|
x := v.Args[0]
|
||||||
|
y := v.Args[1]
|
||||||
|
v.reset(OpARMDIVU)
|
||||||
|
v0 := b.NewValue0(v.Line, OpZeroExt16to32, config.fe.TypeUInt32())
|
||||||
|
v0.AddArg(x)
|
||||||
|
v.AddArg(v0)
|
||||||
|
v1 := b.NewValue0(v.Line, OpZeroExt16to32, config.fe.TypeUInt32())
|
||||||
|
v1.AddArg(y)
|
||||||
|
v.AddArg(v1)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func rewriteValueARM_OpDiv32(v *Value, config *Config) bool {
|
||||||
|
b := v.Block
|
||||||
|
_ = b
|
||||||
|
// match: (Div32 x y)
|
||||||
|
// cond:
|
||||||
|
// result: (DIV x y)
|
||||||
|
for {
|
||||||
|
x := v.Args[0]
|
||||||
|
y := v.Args[1]
|
||||||
|
v.reset(OpARMDIV)
|
||||||
|
v.AddArg(x)
|
||||||
|
v.AddArg(y)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func rewriteValueARM_OpDiv32u(v *Value, config *Config) bool {
|
||||||
|
b := v.Block
|
||||||
|
_ = b
|
||||||
|
// match: (Div32u x y)
|
||||||
|
// cond:
|
||||||
|
// result: (DIVU x y)
|
||||||
|
for {
|
||||||
|
x := v.Args[0]
|
||||||
|
y := v.Args[1]
|
||||||
|
v.reset(OpARMDIVU)
|
||||||
|
v.AddArg(x)
|
||||||
|
v.AddArg(y)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func rewriteValueARM_OpDiv8(v *Value, config *Config) bool {
|
||||||
|
b := v.Block
|
||||||
|
_ = b
|
||||||
|
// match: (Div8 x y)
|
||||||
|
// cond:
|
||||||
|
// result: (DIV (SignExt8to32 x) (SignExt8to32 y))
|
||||||
|
for {
|
||||||
|
x := v.Args[0]
|
||||||
|
y := v.Args[1]
|
||||||
|
v.reset(OpARMDIV)
|
||||||
|
v0 := b.NewValue0(v.Line, OpSignExt8to32, config.fe.TypeInt32())
|
||||||
|
v0.AddArg(x)
|
||||||
|
v.AddArg(v0)
|
||||||
|
v1 := b.NewValue0(v.Line, OpSignExt8to32, config.fe.TypeInt32())
|
||||||
|
v1.AddArg(y)
|
||||||
|
v.AddArg(v1)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func rewriteValueARM_OpDiv8u(v *Value, config *Config) bool {
|
||||||
|
b := v.Block
|
||||||
|
_ = b
|
||||||
|
// match: (Div8u x y)
|
||||||
|
// cond:
|
||||||
|
// result: (DIVU (ZeroExt8to32 x) (ZeroExt8to32 y))
|
||||||
|
for {
|
||||||
|
x := v.Args[0]
|
||||||
|
y := v.Args[1]
|
||||||
|
v.reset(OpARMDIVU)
|
||||||
|
v0 := b.NewValue0(v.Line, OpZeroExt8to32, config.fe.TypeUInt32())
|
||||||
|
v0.AddArg(x)
|
||||||
|
v.AddArg(v0)
|
||||||
|
v1 := b.NewValue0(v.Line, OpZeroExt8to32, config.fe.TypeUInt32())
|
||||||
|
v1.AddArg(y)
|
||||||
|
v.AddArg(v1)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
func rewriteValueARM_OpEq16(v *Value, config *Config) bool {
|
func rewriteValueARM_OpEq16(v *Value, config *Config) bool {
|
||||||
b := v.Block
|
b := v.Block
|
||||||
_ = b
|
_ = b
|
||||||
@ -906,6 +1055,17 @@ func rewriteValueARM_OpGeq8U(v *Value, config *Config) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
func rewriteValueARM_OpGetClosurePtr(v *Value, config *Config) bool {
|
||||||
|
b := v.Block
|
||||||
|
_ = b
|
||||||
|
// match: (GetClosurePtr)
|
||||||
|
// cond:
|
||||||
|
// result: (LoweredGetClosurePtr)
|
||||||
|
for {
|
||||||
|
v.reset(OpARMLoweredGetClosurePtr)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
func rewriteValueARM_OpGoCall(v *Value, config *Config) bool {
|
func rewriteValueARM_OpGoCall(v *Value, config *Config) bool {
|
||||||
b := v.Block
|
b := v.Block
|
||||||
_ = b
|
_ = b
|
||||||
@ -2116,6 +2276,112 @@ func rewriteValueARM_OpARMMOVWstore(v *Value, config *Config) bool {
|
|||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
func rewriteValueARM_OpMod16(v *Value, config *Config) bool {
|
||||||
|
b := v.Block
|
||||||
|
_ = b
|
||||||
|
// match: (Mod16 x y)
|
||||||
|
// cond:
|
||||||
|
// result: (MOD (SignExt16to32 x) (SignExt16to32 y))
|
||||||
|
for {
|
||||||
|
x := v.Args[0]
|
||||||
|
y := v.Args[1]
|
||||||
|
v.reset(OpARMMOD)
|
||||||
|
v0 := b.NewValue0(v.Line, OpSignExt16to32, config.fe.TypeInt32())
|
||||||
|
v0.AddArg(x)
|
||||||
|
v.AddArg(v0)
|
||||||
|
v1 := b.NewValue0(v.Line, OpSignExt16to32, config.fe.TypeInt32())
|
||||||
|
v1.AddArg(y)
|
||||||
|
v.AddArg(v1)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func rewriteValueARM_OpMod16u(v *Value, config *Config) bool {
|
||||||
|
b := v.Block
|
||||||
|
_ = b
|
||||||
|
// match: (Mod16u x y)
|
||||||
|
// cond:
|
||||||
|
// result: (MODU (ZeroExt16to32 x) (ZeroExt16to32 y))
|
||||||
|
for {
|
||||||
|
x := v.Args[0]
|
||||||
|
y := v.Args[1]
|
||||||
|
v.reset(OpARMMODU)
|
||||||
|
v0 := b.NewValue0(v.Line, OpZeroExt16to32, config.fe.TypeUInt32())
|
||||||
|
v0.AddArg(x)
|
||||||
|
v.AddArg(v0)
|
||||||
|
v1 := b.NewValue0(v.Line, OpZeroExt16to32, config.fe.TypeUInt32())
|
||||||
|
v1.AddArg(y)
|
||||||
|
v.AddArg(v1)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func rewriteValueARM_OpMod32(v *Value, config *Config) bool {
|
||||||
|
b := v.Block
|
||||||
|
_ = b
|
||||||
|
// match: (Mod32 x y)
|
||||||
|
// cond:
|
||||||
|
// result: (MOD x y)
|
||||||
|
for {
|
||||||
|
x := v.Args[0]
|
||||||
|
y := v.Args[1]
|
||||||
|
v.reset(OpARMMOD)
|
||||||
|
v.AddArg(x)
|
||||||
|
v.AddArg(y)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func rewriteValueARM_OpMod32u(v *Value, config *Config) bool {
|
||||||
|
b := v.Block
|
||||||
|
_ = b
|
||||||
|
// match: (Mod32u x y)
|
||||||
|
// cond:
|
||||||
|
// result: (MODU x y)
|
||||||
|
for {
|
||||||
|
x := v.Args[0]
|
||||||
|
y := v.Args[1]
|
||||||
|
v.reset(OpARMMODU)
|
||||||
|
v.AddArg(x)
|
||||||
|
v.AddArg(y)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func rewriteValueARM_OpMod8(v *Value, config *Config) bool {
|
||||||
|
b := v.Block
|
||||||
|
_ = b
|
||||||
|
// match: (Mod8 x y)
|
||||||
|
// cond:
|
||||||
|
// result: (MOD (SignExt8to32 x) (SignExt8to32 y))
|
||||||
|
for {
|
||||||
|
x := v.Args[0]
|
||||||
|
y := v.Args[1]
|
||||||
|
v.reset(OpARMMOD)
|
||||||
|
v0 := b.NewValue0(v.Line, OpSignExt8to32, config.fe.TypeInt32())
|
||||||
|
v0.AddArg(x)
|
||||||
|
v.AddArg(v0)
|
||||||
|
v1 := b.NewValue0(v.Line, OpSignExt8to32, config.fe.TypeInt32())
|
||||||
|
v1.AddArg(y)
|
||||||
|
v.AddArg(v1)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func rewriteValueARM_OpMod8u(v *Value, config *Config) bool {
|
||||||
|
b := v.Block
|
||||||
|
_ = b
|
||||||
|
// match: (Mod8u x y)
|
||||||
|
// cond:
|
||||||
|
// result: (MODU (ZeroExt8to32 x) (ZeroExt8to32 y))
|
||||||
|
for {
|
||||||
|
x := v.Args[0]
|
||||||
|
y := v.Args[1]
|
||||||
|
v.reset(OpARMMODU)
|
||||||
|
v0 := b.NewValue0(v.Line, OpZeroExt8to32, config.fe.TypeUInt32())
|
||||||
|
v0.AddArg(x)
|
||||||
|
v.AddArg(v0)
|
||||||
|
v1 := b.NewValue0(v.Line, OpZeroExt8to32, config.fe.TypeUInt32())
|
||||||
|
v1.AddArg(y)
|
||||||
|
v.AddArg(v1)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
func rewriteValueARM_OpMove(v *Value, config *Config) bool {
|
func rewriteValueARM_OpMove(v *Value, config *Config) bool {
|
||||||
b := v.Block
|
b := v.Block
|
||||||
_ = b
|
_ = b
|
||||||
|
@ -99,7 +99,7 @@ func schedule(f *Func) {
|
|||||||
// Compute score. Larger numbers are scheduled closer to the end of the block.
|
// Compute score. Larger numbers are scheduled closer to the end of the block.
|
||||||
for _, v := range b.Values {
|
for _, v := range b.Values {
|
||||||
switch {
|
switch {
|
||||||
case v.Op == OpAMD64LoweredGetClosurePtr:
|
case v.Op == OpAMD64LoweredGetClosurePtr || v.Op == OpARMLoweredGetClosurePtr:
|
||||||
// We also score GetLoweredClosurePtr as early as possible to ensure that the
|
// We also score GetLoweredClosurePtr as early as possible to ensure that the
|
||||||
// context register is not stomped. GetLoweredClosurePtr should only appear
|
// context register is not stomped. GetLoweredClosurePtr should only appear
|
||||||
// in the entry block where there are no phi functions, so there is no
|
// in the entry block where there are no phi functions, so there is no
|
||||||
|
Loading…
Reference in New Issue
Block a user