1
0
mirror of https://github.com/golang/go synced 2024-10-04 17:21:20 -06:00

[dev.ssa] cmd/compile: handle boolean values for SSA on ARM

Fix hardcoded flag register mask in ssa/flagalloc.go by auto-generating
the mask.

Also fix a mistake (in previous CL) about conditional branches.

Progress on SSA backend for ARM. Still not complete. Now "container/ring"
package compiles and tests passed.

Updates #15365.

Change-Id: Id7c8805c30dbb8107baedb485ed0f71f59ed6ea8
Reviewed-on: https://go-review.googlesource.com/23093
Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
Cherry Zhang 2016-05-13 11:25:07 -04:00
parent e2848de9ef
commit ccaed50c7b
11 changed files with 616 additions and 49 deletions

View File

@ -193,7 +193,8 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
case ssa.OpARMMOVBreg,
ssa.OpARMMOVBUreg,
ssa.OpARMMOVHreg,
ssa.OpARMMOVHUreg:
ssa.OpARMMOVHUreg,
ssa.OpARMMVN:
if v.Type.IsMemory() {
v.Fatalf("memory operand for %s", v.LongString())
}
@ -270,12 +271,37 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
ssa.OpARMLessEqualU,
ssa.OpARMGreaterThanU,
ssa.OpARMGreaterEqualU:
v.Fatalf("pseudo-op made it to output: %s", v.LongString())
// generate boolean values
// use conditional move
p := gc.Prog(arm.AMOVW)
p.From.Type = obj.TYPE_CONST
p.From.Offset = 0
p.To.Type = obj.TYPE_REG
p.To.Reg = gc.SSARegNum(v)
p = gc.Prog(arm.AMOVW)
p.Scond = condBits[v.Op]
p.From.Type = obj.TYPE_CONST
p.From.Offset = 1
p.To.Type = obj.TYPE_REG
p.To.Reg = gc.SSARegNum(v)
default:
v.Unimplementedf("genValue not implemented: %s", v.LongString())
}
}
var condBits = map[ssa.Op]uint8{
ssa.OpARMEqual: arm.C_SCOND_EQ,
ssa.OpARMNotEqual: arm.C_SCOND_NE,
ssa.OpARMLessThan: arm.C_SCOND_LT,
ssa.OpARMLessThanU: arm.C_SCOND_LO,
ssa.OpARMLessEqual: arm.C_SCOND_LE,
ssa.OpARMLessEqualU: arm.C_SCOND_LS,
ssa.OpARMGreaterThan: arm.C_SCOND_GT,
ssa.OpARMGreaterThanU: arm.C_SCOND_HI,
ssa.OpARMGreaterEqual: arm.C_SCOND_GE,
ssa.OpARMGreaterEqualU: arm.C_SCOND_HS,
}
var blockJump = map[ssa.BlockKind]struct {
asm, invasm obj.As
}{
@ -285,8 +311,8 @@ var blockJump = map[ssa.BlockKind]struct {
ssa.BlockARMGE: {arm.ABGE, arm.ABLT},
ssa.BlockARMLE: {arm.ABLE, arm.ABGT},
ssa.BlockARMGT: {arm.ABGT, arm.ABLE},
ssa.BlockARMULT: {arm.ABCS, arm.ABCC},
ssa.BlockARMUGE: {arm.ABCC, arm.ABCS},
ssa.BlockARMULT: {arm.ABLO, arm.ABHS},
ssa.BlockARMUGE: {arm.ABHS, arm.ABLO},
ssa.BlockARMUGT: {arm.ABHI, arm.ABLS},
ssa.BlockARMULE: {arm.ABLS, arm.ABHI},
}

View File

@ -1135,6 +1135,7 @@ var opToSSA = map[opAndType]ssa.Op{
opAndType{OEQ, TFUNC}: ssa.OpEqPtr,
opAndType{OEQ, TMAP}: ssa.OpEqPtr,
opAndType{OEQ, TCHAN}: ssa.OpEqPtr,
opAndType{OEQ, TPTR32}: ssa.OpEqPtr,
opAndType{OEQ, TPTR64}: ssa.OpEqPtr,
opAndType{OEQ, TUINTPTR}: ssa.OpEqPtr,
opAndType{OEQ, TUNSAFEPTR}: ssa.OpEqPtr,
@ -1155,6 +1156,7 @@ var opToSSA = map[opAndType]ssa.Op{
opAndType{ONE, TFUNC}: ssa.OpNeqPtr,
opAndType{ONE, TMAP}: ssa.OpNeqPtr,
opAndType{ONE, TCHAN}: ssa.OpNeqPtr,
opAndType{ONE, TPTR32}: ssa.OpNeqPtr,
opAndType{ONE, TPTR64}: ssa.OpNeqPtr,
opAndType{ONE, TUINTPTR}: ssa.OpNeqPtr,
opAndType{ONE, TUNSAFEPTR}: ssa.OpNeqPtr,

View File

@ -19,6 +19,7 @@ type Config struct {
lowerBlock func(*Block) bool // lowering function
lowerValue func(*Value, *Config) bool // lowering function
registers []Register // machine registers
flagRegMask regMask // flag register mask
fe Frontend // callbacks into compiler frontend
HTML *HTMLWriter // html writer, for debugging
ctxt *obj.Link // Generic arch information
@ -126,6 +127,7 @@ func NewConfig(arch string, fe Frontend, ctxt *obj.Link, optimize bool) *Config
c.lowerBlock = rewriteBlockAMD64
c.lowerValue = rewriteValueAMD64
c.registers = registersAMD64[:]
c.flagRegMask = flagRegMaskAMD64
case "386":
c.IntSize = 4
c.PtrSize = 4
@ -137,6 +139,7 @@ func NewConfig(arch string, fe Frontend, ctxt *obj.Link, optimize bool) *Config
c.lowerBlock = rewriteBlockARM
c.lowerValue = rewriteValueARM
c.registers = registersARM[:]
c.flagRegMask = flagRegMaskARM
default:
fe.Unimplementedf(0, "arch %s not implemented", arch)
}

View File

@ -4,8 +4,6 @@
package ssa
const flagRegMask = regMask(1) << 33 // TODO: arch-specific
// flagalloc allocates the flag register among all the flag-generating
// instructions. Flag values are recomputed if they need to be
// spilled/restored.
@ -33,7 +31,7 @@ func flagalloc(f *Func) {
if v == flag {
flag = nil
}
if opcodeTable[v.Op].reg.clobbers&flagRegMask != 0 {
if opcodeTable[v.Op].reg.clobbers&f.Config.flagRegMask != 0 {
flag = nil
}
for _, a := range v.Args {
@ -105,7 +103,7 @@ func flagalloc(f *Func) {
}
// Issue v.
b.Values = append(b.Values, v)
if opcodeTable[v.Op].reg.clobbers&flagRegMask != 0 {
if opcodeTable[v.Op].reg.clobbers&f.Config.flagRegMask != 0 {
flag = nil
}
if v.Type.IsFlags() {

View File

@ -551,5 +551,6 @@ func init() {
ops: AMD64ops,
blocks: AMD64blocks,
regnames: regNamesAMD64,
flagmask: flags,
})
}

View File

@ -2,11 +2,43 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
(AddPtr x y) -> (ADD x y)
(Add32 x y) -> (ADD x y)
(Add16 x y) -> (ADD x y)
(Add8 x y) -> (ADD x y)
(SubPtr x y) -> (SUB x y)
(Sub32 x y) -> (SUB x y)
(Sub16 x y) -> (SUB x y)
(Sub8 x y) -> (SUB x y)
(And32 x y) -> (AND x y)
(And16 x y) -> (AND x y)
(And8 x y) -> (AND x y)
(Or32 x y) -> (OR x y)
(Or16 x y) -> (OR x y)
(Or8 x y) -> (OR x y)
(Xor32 x y) -> (XOR x y)
(Xor16 x y) -> (XOR x y)
(Xor8 x y) -> (XOR x y)
// unary ops
(Neg32 x) -> (RSBconst [0] x)
(Neg16 x) -> (RSBconst [0] x)
(Neg8 x) -> (RSBconst [0] x)
(Com32 x) -> (MVN x)
(Com16 x) -> (MVN x)
(Com8 x) -> (MVN x)
// boolean ops -- booleans are represented with 0=false, 1=true
(AndB x y) -> (AND x y)
(OrB x y) -> (OR x y)
(EqB x y) -> (XORconst [1] (XOR <config.fe.TypeBool()> x y))
(NeqB x y) -> (XOR x y)
(Not x) -> (XORconst [1] x)
(Const8 [val]) -> (MOVWconst [val])
(Const16 [val]) -> (MOVWconst [val])
@ -29,10 +61,12 @@
(Eq8 x y) -> (Equal (CMP (ZeroExt8to32 x) (ZeroExt8to32 y)))
(Eq16 x y) -> (Equal (CMP (ZeroExt16to32 x) (ZeroExt16to32 y)))
(Eq32 x y) -> (Equal (CMP x y))
(EqPtr x y) -> (Equal (CMP x y))
(Neq8 x y) -> (NotEqual (CMP (ZeroExt8to32 x) (ZeroExt8to32 y)))
(Neq16 x y) -> (NotEqual (CMP (ZeroExt16to32 x) (ZeroExt16to32 y)))
(Neq32 x y) -> (NotEqual (CMP x y))
(NeqPtr x y) -> (NotEqual (CMP x y))
(Less8 x y) -> (LessThan (CMP (SignExt8to32 x) (SignExt8to32 y)))
(Less16 x y) -> (LessThan (CMP (SignExt16to32 x) (SignExt16to32 y)))
@ -89,6 +123,9 @@
// checks
(NilCheck ptr mem) -> (LoweredNilCheck ptr mem)
(IsNonNil ptr) -> (NotEqual (CMPconst [0] ptr))
(IsInBounds idx len) -> (LessThanU (CMP idx len))
(IsSliceInBounds idx len) -> (LessEqualU (CMP idx len))
// Absorb pseudo-ops into blocks.
(If (Equal cc) yes no) -> (EQ cc yes no)

View File

@ -80,12 +80,12 @@ func init() {
gp01 = regInfo{inputs: []regMask{}, outputs: []regMask{gp}}
gp11 = regInfo{inputs: []regMask{gp}, outputs: []regMask{gp}}
gp11sb = regInfo{inputs: []regMask{gpspsb}, outputs: []regMask{gp}}
gp11flags = regInfo{inputs: []regMask{gp}, outputs: []regMask{gp | flags}}
gp1flags = regInfo{inputs: []regMask{gp}, outputs: []regMask{flags}}
gp21 = regInfo{inputs: []regMask{gp, gp}, outputs: []regMask{gp}}
gp2flags = regInfo{inputs: []regMask{gp, gp}, outputs: []regMask{gp | flags}}
gp2flags = regInfo{inputs: []regMask{gp, gp}, outputs: []regMask{flags}}
gpload = regInfo{inputs: []regMask{gpspsb}, outputs: []regMask{gp}}
gpstore = regInfo{inputs: []regMask{gpspsb, gp}, outputs: []regMask{}}
flagsgp = regInfo{inputs: []regMask{gp | flags}, outputs: []regMask{gp}}
readflags = regInfo{inputs: []regMask{flags}, outputs: []regMask{gp}}
)
ops := []opData{
// binary ops
@ -105,14 +105,17 @@ func init() {
{name: "BIC", argLength: 2, reg: gp21, asm: "BIC"}, // arg0 &^ arg1
{name: "BICconst", argLength: 1, reg: gp11, asm: "BIC", aux: "Int32"}, // arg0 &^ auxInt
// unary ops
{name: "MVN", argLength: 1, reg: gp11, asm: "MVN"}, // ^arg0
{name: "CMP", argLength: 2, reg: gp2flags, asm: "CMP", typ: "Flags"}, // arg0 compare to arg1
{name: "CMPconst", argLength: 1, reg: gp11flags, asm: "CMP", aux: "Int32", typ: "Flags"}, // arg0 compare to auxInt
{name: "CMPconst", argLength: 1, reg: gp1flags, asm: "CMP", aux: "Int32", typ: "Flags"}, // arg0 compare to auxInt
{name: "CMN", argLength: 2, reg: gp2flags, asm: "CMN", typ: "Flags"}, // arg0 compare to -arg1
{name: "CMNconst", argLength: 1, reg: gp11flags, asm: "CMN", aux: "Int32", typ: "Flags"}, // arg0 compare to -auxInt
{name: "CMNconst", argLength: 1, reg: gp1flags, asm: "CMN", aux: "Int32", typ: "Flags"}, // arg0 compare to -auxInt
{name: "TST", argLength: 2, reg: gp2flags, asm: "TST", typ: "Flags", commutative: true}, // arg0 & arg1 compare to 0
{name: "TSTconst", argLength: 1, reg: gp11flags, asm: "TST", aux: "Int32", typ: "Flags"}, // arg0 & auxInt compare to 0
{name: "TSTconst", argLength: 1, reg: gp1flags, asm: "TST", aux: "Int32", typ: "Flags"}, // arg0 & auxInt compare to 0
{name: "TEQ", argLength: 2, reg: gp2flags, asm: "TEQ", typ: "Flags", commutative: true}, // arg0 ^ arg1 compare to 0
{name: "TEQconst", argLength: 1, reg: gp11flags, asm: "TEQ", aux: "Int32", typ: "Flags"}, // arg0 ^ auxInt compare to 0
{name: "TEQconst", argLength: 1, reg: gp1flags, asm: "TEQ", aux: "Int32", typ: "Flags"}, // arg0 ^ auxInt compare to 0
{name: "MOVWconst", argLength: 0, reg: gp01, aux: "Int32", asm: "MOVW", rematerializeable: true}, // 32 low bits of auxint
@ -140,16 +143,16 @@ func init() {
// pseudo-ops
{name: "LoweredNilCheck", argLength: 2, reg: regInfo{inputs: []regMask{gpsp}, clobbers: flags}}, // panic if arg0 is nil. arg1=mem.
{name: "Equal", argLength: 1, reg: flagsgp}, // bool, true flags encode x==y false otherwise.
{name: "NotEqual", argLength: 1, reg: flagsgp}, // bool, true flags encode x!=y false otherwise.
{name: "LessThan", argLength: 1, reg: flagsgp}, // bool, true flags encode signed x<y false otherwise.
{name: "LessEqual", argLength: 1, reg: flagsgp}, // bool, true flags encode signed x<=y false otherwise.
{name: "GreaterThan", argLength: 1, reg: flagsgp}, // bool, true flags encode signed x>y false otherwise.
{name: "GreaterEqual", argLength: 1, reg: flagsgp}, // bool, true flags encode signed x>=y false otherwise.
{name: "LessThanU", argLength: 1, reg: flagsgp}, // bool, true flags encode unsigned x<y false otherwise.
{name: "LessEqualU", argLength: 1, reg: flagsgp}, // bool, true flags encode unsigned x<=y false otherwise.
{name: "GreaterThanU", argLength: 1, reg: flagsgp}, // bool, true flags encode unsigned x>y false otherwise.
{name: "GreaterEqualU", argLength: 1, reg: flagsgp}, // bool, true flags encode unsigned x>=y false otherwise.
{name: "Equal", argLength: 1, reg: readflags}, // bool, true flags encode x==y false otherwise.
{name: "NotEqual", argLength: 1, reg: readflags}, // bool, true flags encode x!=y false otherwise.
{name: "LessThan", argLength: 1, reg: readflags}, // bool, true flags encode signed x<y false otherwise.
{name: "LessEqual", argLength: 1, reg: readflags}, // bool, true flags encode signed x<=y false otherwise.
{name: "GreaterThan", argLength: 1, reg: readflags}, // bool, true flags encode signed x>y false otherwise.
{name: "GreaterEqual", argLength: 1, reg: readflags}, // bool, true flags encode signed x>=y false otherwise.
{name: "LessThanU", argLength: 1, reg: readflags}, // bool, true flags encode unsigned x<y false otherwise.
{name: "LessEqualU", argLength: 1, reg: readflags}, // bool, true flags encode unsigned x<=y false otherwise.
{name: "GreaterThanU", argLength: 1, reg: readflags}, // bool, true flags encode unsigned x>y false otherwise.
{name: "GreaterEqualU", argLength: 1, reg: readflags}, // bool, true flags encode unsigned x>=y false otherwise.
}
blocks := []blockData{
@ -172,5 +175,6 @@ func init() {
ops: ops,
blocks: blocks,
regnames: regNamesARM,
flagmask: flags,
})
}

View File

@ -27,6 +27,7 @@ type arch struct {
ops []opData
blocks []blockData
regnames []string
flagmask regMask
generic bool
}
@ -223,6 +224,7 @@ func genOp() {
fmt.Fprintf(w, " {%d, \"%s\"},\n", i, r)
}
fmt.Fprintln(w, "}")
fmt.Fprintf(w, "var flagRegMask%s = regMask(%d)\n", a.name, a.flagmask)
}
// gofmt result

View File

@ -337,6 +337,7 @@ const (
OpARMXORconst
OpARMBIC
OpARMBICconst
OpARMMVN
OpARMCMP
OpARMCMPconst
OpARMCMN
@ -4040,6 +4041,19 @@ var opcodeTable = [...]opInfo{
},
},
},
{
name: "MVN",
argLen: 1,
asm: arm.AMVN,
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: "CMP",
argLen: 2,
@ -4050,7 +4064,7 @@ var opcodeTable = [...]opInfo{
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
outputs: []regMask{
70655, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 FLAGS
65536, // FLAGS
},
},
},
@ -4064,7 +4078,7 @@ var opcodeTable = [...]opInfo{
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
outputs: []regMask{
70655, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 FLAGS
65536, // FLAGS
},
},
},
@ -4078,7 +4092,7 @@ var opcodeTable = [...]opInfo{
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
outputs: []regMask{
70655, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 FLAGS
65536, // FLAGS
},
},
},
@ -4092,7 +4106,7 @@ var opcodeTable = [...]opInfo{
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
outputs: []regMask{
70655, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 FLAGS
65536, // FLAGS
},
},
},
@ -4107,7 +4121,7 @@ var opcodeTable = [...]opInfo{
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
outputs: []regMask{
70655, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 FLAGS
65536, // FLAGS
},
},
},
@ -4121,7 +4135,7 @@ var opcodeTable = [...]opInfo{
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
outputs: []regMask{
70655, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 FLAGS
65536, // FLAGS
},
},
},
@ -4136,7 +4150,7 @@ var opcodeTable = [...]opInfo{
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
outputs: []regMask{
70655, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 FLAGS
65536, // FLAGS
},
},
},
@ -4150,7 +4164,7 @@ var opcodeTable = [...]opInfo{
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
outputs: []regMask{
70655, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 FLAGS
65536, // FLAGS
},
},
},
@ -4386,7 +4400,7 @@ var opcodeTable = [...]opInfo{
argLen: 1,
reg: regInfo{
inputs: []inputInfo{
{0, 70655}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 FLAGS
{0, 65536}, // FLAGS
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
@ -4398,7 +4412,7 @@ var opcodeTable = [...]opInfo{
argLen: 1,
reg: regInfo{
inputs: []inputInfo{
{0, 70655}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 FLAGS
{0, 65536}, // FLAGS
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
@ -4410,7 +4424,7 @@ var opcodeTable = [...]opInfo{
argLen: 1,
reg: regInfo{
inputs: []inputInfo{
{0, 70655}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 FLAGS
{0, 65536}, // FLAGS
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
@ -4422,7 +4436,7 @@ var opcodeTable = [...]opInfo{
argLen: 1,
reg: regInfo{
inputs: []inputInfo{
{0, 70655}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 FLAGS
{0, 65536}, // FLAGS
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
@ -4434,7 +4448,7 @@ var opcodeTable = [...]opInfo{
argLen: 1,
reg: regInfo{
inputs: []inputInfo{
{0, 70655}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 FLAGS
{0, 65536}, // FLAGS
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
@ -4446,7 +4460,7 @@ var opcodeTable = [...]opInfo{
argLen: 1,
reg: regInfo{
inputs: []inputInfo{
{0, 70655}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 FLAGS
{0, 65536}, // FLAGS
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
@ -4458,7 +4472,7 @@ var opcodeTable = [...]opInfo{
argLen: 1,
reg: regInfo{
inputs: []inputInfo{
{0, 70655}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 FLAGS
{0, 65536}, // FLAGS
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
@ -4470,7 +4484,7 @@ var opcodeTable = [...]opInfo{
argLen: 1,
reg: regInfo{
inputs: []inputInfo{
{0, 70655}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 FLAGS
{0, 65536}, // FLAGS
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
@ -4482,7 +4496,7 @@ var opcodeTable = [...]opInfo{
argLen: 1,
reg: regInfo{
inputs: []inputInfo{
{0, 70655}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 FLAGS
{0, 65536}, // FLAGS
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
@ -4494,7 +4508,7 @@ var opcodeTable = [...]opInfo{
argLen: 1,
reg: regInfo{
inputs: []inputInfo{
{0, 70655}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 FLAGS
{0, 65536}, // FLAGS
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
@ -6027,6 +6041,7 @@ var registersAMD64 = [...]Register{
{32, "SB"},
{33, "FLAGS"},
}
var flagRegMaskAMD64 = regMask(8589934592)
var registersARM = [...]Register{
{0, "R0"},
{1, "R1"},
@ -6047,3 +6062,4 @@ var registersARM = [...]Register{
{16, "FLAGS"},
{17, "SB"},
}
var flagRegMaskARM = regMask(65536)

View File

@ -985,7 +985,7 @@ func (s *regAllocState) regalloc(f *Func) {
args = append(args[:0], v.Args...)
for _, i := range regspec.inputs {
mask := i.regs
if mask == flagRegMask {
if mask == f.Config.flagRegMask {
// TODO: remove flag input from regspec.inputs.
continue
}

View File

@ -10,14 +10,32 @@ func rewriteValueARM(v *Value, config *Config) bool {
switch v.Op {
case OpARMADD:
return rewriteValueARM_OpARMADD(v, config)
case OpAdd16:
return rewriteValueARM_OpAdd16(v, config)
case OpAdd32:
return rewriteValueARM_OpAdd32(v, config)
case OpAdd8:
return rewriteValueARM_OpAdd8(v, config)
case OpAddPtr:
return rewriteValueARM_OpAddPtr(v, config)
case OpAddr:
return rewriteValueARM_OpAddr(v, config)
case OpAnd16:
return rewriteValueARM_OpAnd16(v, config)
case OpAnd32:
return rewriteValueARM_OpAnd32(v, config)
case OpAnd8:
return rewriteValueARM_OpAnd8(v, config)
case OpAndB:
return rewriteValueARM_OpAndB(v, config)
case OpClosureCall:
return rewriteValueARM_OpClosureCall(v, config)
case OpCom16:
return rewriteValueARM_OpCom16(v, config)
case OpCom32:
return rewriteValueARM_OpCom32(v, config)
case OpCom8:
return rewriteValueARM_OpCom8(v, config)
case OpConst16:
return rewriteValueARM_OpConst16(v, config)
case OpConst32:
@ -36,6 +54,10 @@ func rewriteValueARM(v *Value, config *Config) bool {
return rewriteValueARM_OpEq32(v, config)
case OpEq8:
return rewriteValueARM_OpEq8(v, config)
case OpEqB:
return rewriteValueARM_OpEqB(v, config)
case OpEqPtr:
return rewriteValueARM_OpEqPtr(v, config)
case OpGeq16:
return rewriteValueARM_OpGeq16(v, config)
case OpGeq16U:
@ -64,6 +86,12 @@ func rewriteValueARM(v *Value, config *Config) bool {
return rewriteValueARM_OpGreater8U(v, config)
case OpInterCall:
return rewriteValueARM_OpInterCall(v, config)
case OpIsInBounds:
return rewriteValueARM_OpIsInBounds(v, config)
case OpIsNonNil:
return rewriteValueARM_OpIsNonNil(v, config)
case OpIsSliceInBounds:
return rewriteValueARM_OpIsSliceInBounds(v, config)
case OpLeq16:
return rewriteValueARM_OpLeq16(v, config)
case OpLeq16U:
@ -106,18 +134,36 @@ func rewriteValueARM(v *Value, config *Config) bool {
return rewriteValueARM_OpARMMOVWload(v, config)
case OpARMMOVWstore:
return rewriteValueARM_OpARMMOVWstore(v, config)
case OpNeg16:
return rewriteValueARM_OpNeg16(v, config)
case OpNeg32:
return rewriteValueARM_OpNeg32(v, config)
case OpNeg8:
return rewriteValueARM_OpNeg8(v, config)
case OpNeq16:
return rewriteValueARM_OpNeq16(v, config)
case OpNeq32:
return rewriteValueARM_OpNeq32(v, config)
case OpNeq8:
return rewriteValueARM_OpNeq8(v, config)
case OpNeqB:
return rewriteValueARM_OpNeqB(v, config)
case OpNeqPtr:
return rewriteValueARM_OpNeqPtr(v, config)
case OpNilCheck:
return rewriteValueARM_OpNilCheck(v, config)
case OpNot:
return rewriteValueARM_OpNot(v, config)
case OpOffPtr:
return rewriteValueARM_OpOffPtr(v, config)
case OpOr16:
return rewriteValueARM_OpOr16(v, config)
case OpOr32:
return rewriteValueARM_OpOr32(v, config)
case OpOr8:
return rewriteValueARM_OpOr8(v, config)
case OpOrB:
return rewriteValueARM_OpOrB(v, config)
case OpSignExt16to32:
return rewriteValueARM_OpSignExt16to32(v, config)
case OpSignExt8to16:
@ -128,16 +174,26 @@ func rewriteValueARM(v *Value, config *Config) bool {
return rewriteValueARM_OpStaticCall(v, config)
case OpStore:
return rewriteValueARM_OpStore(v, config)
case OpSub16:
return rewriteValueARM_OpSub16(v, config)
case OpSub32:
return rewriteValueARM_OpSub32(v, config)
case OpSub8:
return rewriteValueARM_OpSub8(v, config)
case OpSubPtr:
return rewriteValueARM_OpSubPtr(v, config)
case OpTrunc16to8:
return rewriteValueARM_OpTrunc16to8(v, config)
case OpTrunc32to16:
return rewriteValueARM_OpTrunc32to16(v, config)
case OpTrunc32to8:
return rewriteValueARM_OpTrunc32to8(v, config)
case OpXor16:
return rewriteValueARM_OpXor16(v, config)
case OpXor32:
return rewriteValueARM_OpXor32(v, config)
case OpXor8:
return rewriteValueARM_OpXor8(v, config)
case OpZeroExt16to32:
return rewriteValueARM_OpZeroExt16to32(v, config)
case OpZeroExt8to16:
@ -182,6 +238,21 @@ func rewriteValueARM_OpARMADD(v *Value, config *Config) bool {
}
return false
}
func rewriteValueARM_OpAdd16(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (Add16 x y)
// cond:
// result: (ADD x y)
for {
x := v.Args[0]
y := v.Args[1]
v.reset(OpARMADD)
v.AddArg(x)
v.AddArg(y)
return true
}
}
func rewriteValueARM_OpAdd32(v *Value, config *Config) bool {
b := v.Block
_ = b
@ -197,6 +268,36 @@ func rewriteValueARM_OpAdd32(v *Value, config *Config) bool {
return true
}
}
func rewriteValueARM_OpAdd8(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (Add8 x y)
// cond:
// result: (ADD x y)
for {
x := v.Args[0]
y := v.Args[1]
v.reset(OpARMADD)
v.AddArg(x)
v.AddArg(y)
return true
}
}
func rewriteValueARM_OpAddPtr(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (AddPtr x y)
// cond:
// result: (ADD x y)
for {
x := v.Args[0]
y := v.Args[1]
v.reset(OpARMADD)
v.AddArg(x)
v.AddArg(y)
return true
}
}
func rewriteValueARM_OpAddr(v *Value, config *Config) bool {
b := v.Block
_ = b
@ -212,6 +313,21 @@ func rewriteValueARM_OpAddr(v *Value, config *Config) bool {
return true
}
}
func rewriteValueARM_OpAnd16(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (And16 x y)
// cond:
// result: (AND x y)
for {
x := v.Args[0]
y := v.Args[1]
v.reset(OpARMAND)
v.AddArg(x)
v.AddArg(y)
return true
}
}
func rewriteValueARM_OpAnd32(v *Value, config *Config) bool {
b := v.Block
_ = b
@ -227,6 +343,36 @@ func rewriteValueARM_OpAnd32(v *Value, config *Config) bool {
return true
}
}
func rewriteValueARM_OpAnd8(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (And8 x y)
// cond:
// result: (AND x y)
for {
x := v.Args[0]
y := v.Args[1]
v.reset(OpARMAND)
v.AddArg(x)
v.AddArg(y)
return true
}
}
func rewriteValueARM_OpAndB(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (AndB x y)
// cond:
// result: (AND x y)
for {
x := v.Args[0]
y := v.Args[1]
v.reset(OpARMAND)
v.AddArg(x)
v.AddArg(y)
return true
}
}
func rewriteValueARM_OpClosureCall(v *Value, config *Config) bool {
b := v.Block
_ = b
@ -246,6 +392,45 @@ func rewriteValueARM_OpClosureCall(v *Value, config *Config) bool {
return true
}
}
func rewriteValueARM_OpCom16(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (Com16 x)
// cond:
// result: (MVN x)
for {
x := v.Args[0]
v.reset(OpARMMVN)
v.AddArg(x)
return true
}
}
func rewriteValueARM_OpCom32(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (Com32 x)
// cond:
// result: (MVN x)
for {
x := v.Args[0]
v.reset(OpARMMVN)
v.AddArg(x)
return true
}
}
func rewriteValueARM_OpCom8(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (Com8 x)
// cond:
// result: (MVN x)
for {
x := v.Args[0]
v.reset(OpARMMVN)
v.AddArg(x)
return true
}
}
func rewriteValueARM_OpConst16(v *Value, config *Config) bool {
b := v.Block
_ = b
@ -384,6 +569,41 @@ func rewriteValueARM_OpEq8(v *Value, config *Config) bool {
return true
}
}
func rewriteValueARM_OpEqB(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (EqB x y)
// cond:
// result: (XORconst [1] (XOR <config.fe.TypeBool()> x y))
for {
x := v.Args[0]
y := v.Args[1]
v.reset(OpARMXORconst)
v.AuxInt = 1
v0 := b.NewValue0(v.Line, OpARMXOR, config.fe.TypeBool())
v0.AddArg(x)
v0.AddArg(y)
v.AddArg(v0)
return true
}
}
func rewriteValueARM_OpEqPtr(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (EqPtr x y)
// cond:
// result: (Equal (CMP x y))
for {
x := v.Args[0]
y := v.Args[1]
v.reset(OpARMEqual)
v0 := b.NewValue0(v.Line, OpARMCMP, TypeFlags)
v0.AddArg(x)
v0.AddArg(y)
v.AddArg(v0)
return true
}
}
func rewriteValueARM_OpGeq16(v *Value, config *Config) bool {
b := v.Block
_ = b
@ -652,6 +872,56 @@ func rewriteValueARM_OpInterCall(v *Value, config *Config) bool {
return true
}
}
func rewriteValueARM_OpIsInBounds(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (IsInBounds idx len)
// cond:
// result: (LessThanU (CMP idx len))
for {
idx := v.Args[0]
len := v.Args[1]
v.reset(OpARMLessThanU)
v0 := b.NewValue0(v.Line, OpARMCMP, TypeFlags)
v0.AddArg(idx)
v0.AddArg(len)
v.AddArg(v0)
return true
}
}
func rewriteValueARM_OpIsNonNil(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (IsNonNil ptr)
// cond:
// result: (NotEqual (CMPconst [0] ptr))
for {
ptr := v.Args[0]
v.reset(OpARMNotEqual)
v0 := b.NewValue0(v.Line, OpARMCMPconst, TypeFlags)
v0.AuxInt = 0
v0.AddArg(ptr)
v.AddArg(v0)
return true
}
}
func rewriteValueARM_OpIsSliceInBounds(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (IsSliceInBounds idx len)
// cond:
// result: (LessEqualU (CMP idx len))
for {
idx := v.Args[0]
len := v.Args[1]
v.reset(OpARMLessEqualU)
v0 := b.NewValue0(v.Line, OpARMCMP, TypeFlags)
v0.AddArg(idx)
v0.AddArg(len)
v.AddArg(v0)
return true
}
}
func rewriteValueARM_OpLeq16(v *Value, config *Config) bool {
b := v.Block
_ = b
@ -1221,6 +1491,48 @@ func rewriteValueARM_OpARMMOVWstore(v *Value, config *Config) bool {
}
return false
}
func rewriteValueARM_OpNeg16(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (Neg16 x)
// cond:
// result: (RSBconst [0] x)
for {
x := v.Args[0]
v.reset(OpARMRSBconst)
v.AuxInt = 0
v.AddArg(x)
return true
}
}
func rewriteValueARM_OpNeg32(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (Neg32 x)
// cond:
// result: (RSBconst [0] x)
for {
x := v.Args[0]
v.reset(OpARMRSBconst)
v.AuxInt = 0
v.AddArg(x)
return true
}
}
func rewriteValueARM_OpNeg8(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (Neg8 x)
// cond:
// result: (RSBconst [0] x)
for {
x := v.Args[0]
v.reset(OpARMRSBconst)
v.AuxInt = 0
v.AddArg(x)
return true
}
}
func rewriteValueARM_OpNeq16(v *Value, config *Config) bool {
b := v.Block
_ = b
@ -1280,6 +1592,38 @@ func rewriteValueARM_OpNeq8(v *Value, config *Config) bool {
return true
}
}
func rewriteValueARM_OpNeqB(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (NeqB x y)
// cond:
// result: (XOR x y)
for {
x := v.Args[0]
y := v.Args[1]
v.reset(OpARMXOR)
v.AddArg(x)
v.AddArg(y)
return true
}
}
func rewriteValueARM_OpNeqPtr(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (NeqPtr x y)
// cond:
// result: (NotEqual (CMP x y))
for {
x := v.Args[0]
y := v.Args[1]
v.reset(OpARMNotEqual)
v0 := b.NewValue0(v.Line, OpARMCMP, TypeFlags)
v0.AddArg(x)
v0.AddArg(y)
v.AddArg(v0)
return true
}
}
func rewriteValueARM_OpNilCheck(v *Value, config *Config) bool {
b := v.Block
_ = b
@ -1295,6 +1639,20 @@ func rewriteValueARM_OpNilCheck(v *Value, config *Config) bool {
return true
}
}
func rewriteValueARM_OpNot(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (Not x)
// cond:
// result: (XORconst [1] x)
for {
x := v.Args[0]
v.reset(OpARMXORconst)
v.AuxInt = 1
v.AddArg(x)
return true
}
}
func rewriteValueARM_OpOffPtr(v *Value, config *Config) bool {
b := v.Block
_ = b
@ -1312,6 +1670,21 @@ func rewriteValueARM_OpOffPtr(v *Value, config *Config) bool {
return true
}
}
func rewriteValueARM_OpOr16(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (Or16 x y)
// cond:
// result: (OR x y)
for {
x := v.Args[0]
y := v.Args[1]
v.reset(OpARMOR)
v.AddArg(x)
v.AddArg(y)
return true
}
}
func rewriteValueARM_OpOr32(v *Value, config *Config) bool {
b := v.Block
_ = b
@ -1327,6 +1700,36 @@ func rewriteValueARM_OpOr32(v *Value, config *Config) bool {
return true
}
}
func rewriteValueARM_OpOr8(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (Or8 x y)
// cond:
// result: (OR x y)
for {
x := v.Args[0]
y := v.Args[1]
v.reset(OpARMOR)
v.AddArg(x)
v.AddArg(y)
return true
}
}
func rewriteValueARM_OpOrB(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (OrB x y)
// cond:
// result: (OR x y)
for {
x := v.Args[0]
y := v.Args[1]
v.reset(OpARMOR)
v.AddArg(x)
v.AddArg(y)
return true
}
}
func rewriteValueARM_OpSignExt16to32(v *Value, config *Config) bool {
b := v.Block
_ = b
@ -1436,6 +1839,21 @@ func rewriteValueARM_OpStore(v *Value, config *Config) bool {
}
return false
}
func rewriteValueARM_OpSub16(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (Sub16 x y)
// cond:
// result: (SUB x y)
for {
x := v.Args[0]
y := v.Args[1]
v.reset(OpARMSUB)
v.AddArg(x)
v.AddArg(y)
return true
}
}
func rewriteValueARM_OpSub32(v *Value, config *Config) bool {
b := v.Block
_ = b
@ -1451,6 +1869,36 @@ func rewriteValueARM_OpSub32(v *Value, config *Config) bool {
return true
}
}
func rewriteValueARM_OpSub8(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (Sub8 x y)
// cond:
// result: (SUB x y)
for {
x := v.Args[0]
y := v.Args[1]
v.reset(OpARMSUB)
v.AddArg(x)
v.AddArg(y)
return true
}
}
func rewriteValueARM_OpSubPtr(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (SubPtr x y)
// cond:
// result: (SUB x y)
for {
x := v.Args[0]
y := v.Args[1]
v.reset(OpARMSUB)
v.AddArg(x)
v.AddArg(y)
return true
}
}
func rewriteValueARM_OpTrunc16to8(v *Value, config *Config) bool {
b := v.Block
_ = b
@ -1493,6 +1941,21 @@ func rewriteValueARM_OpTrunc32to8(v *Value, config *Config) bool {
return true
}
}
func rewriteValueARM_OpXor16(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (Xor16 x y)
// cond:
// result: (XOR x y)
for {
x := v.Args[0]
y := v.Args[1]
v.reset(OpARMXOR)
v.AddArg(x)
v.AddArg(y)
return true
}
}
func rewriteValueARM_OpXor32(v *Value, config *Config) bool {
b := v.Block
_ = b
@ -1508,6 +1971,21 @@ func rewriteValueARM_OpXor32(v *Value, config *Config) bool {
return true
}
}
func rewriteValueARM_OpXor8(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (Xor8 x y)
// cond:
// result: (XOR x y)
for {
x := v.Args[0]
y := v.Args[1]
v.reset(OpARMXOR)
v.AddArg(x)
v.AddArg(y)
return true
}
}
func rewriteValueARM_OpZeroExt16to32(v *Value, config *Config) bool {
b := v.Block
_ = b