Commit d8181d5d authored by Cherry Zhang's avatar Cherry Zhang

[dev.ssa] cmd/compile: simplify MOVWreg on ARM

For register-register move, if there is only one use, allocate it in
the same register so we don't need to emit an instruction.

Updates #15365.

Change-Id: Iad41843854a506c521d577ad93fcbe73e8de8065
Reviewed-on: https://go-review.googlesource.com/25059
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarDavid Chase <drchase@google.com>
parent 7b9873b9
...@@ -194,6 +194,11 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { ...@@ -194,6 +194,11 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
p.From.Reg = x p.From.Reg = x
p.To.Type = obj.TYPE_REG p.To.Type = obj.TYPE_REG
p.To.Reg = y p.To.Reg = y
case ssa.OpARMMOVWnop:
if gc.SSARegNum(v) != gc.SSARegNum(v.Args[0]) {
v.Fatalf("input[0] and output not in same register %s", v.LongString())
}
// nothing to do
case ssa.OpLoadReg: case ssa.OpLoadReg:
if v.Type.IsFlags() { if v.Type.IsFlags() {
v.Unimplementedf("load flags not implemented: %v", v.LongString()) v.Unimplementedf("load flags not implemented: %v", v.LongString())
...@@ -636,7 +641,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { ...@@ -636,7 +641,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
ssa.OpARMMOVHreg, ssa.OpARMMOVHreg,
ssa.OpARMMOVHUreg: ssa.OpARMMOVHUreg:
a := v.Args[0] a := v.Args[0]
for a.Op == ssa.OpCopy || a.Op == ssa.OpARMMOVWreg { for a.Op == ssa.OpCopy || a.Op == ssa.OpARMMOVWreg || a.Op == ssa.OpARMMOVWnop {
a = a.Args[0] a = a.Args[0]
} }
if a.Op == ssa.OpLoadReg { if a.Op == ssa.OpLoadReg {
......
...@@ -520,6 +520,10 @@ ...@@ -520,6 +520,10 @@
(MOVHstore [off] {sym} ptr (MOVHreg x) mem) -> (MOVHstore [off] {sym} ptr x mem) (MOVHstore [off] {sym} ptr (MOVHreg x) mem) -> (MOVHstore [off] {sym} ptr x mem)
(MOVHstore [off] {sym} ptr (MOVHUreg x) mem) -> (MOVHstore [off] {sym} ptr x mem) (MOVHstore [off] {sym} ptr (MOVHUreg x) mem) -> (MOVHstore [off] {sym} ptr x mem)
// if a register move has only 1 use, just use the same register without emitting instruction
// MOVWnop doesn't emit instruction, only for ensuring the type.
(MOVWreg x) && x.Uses == 1 -> (MOVWnop x)
// mul by constant // mul by constant
(MUL x (MOVWconst [c])) && int32(c) == -1 -> (RSBconst [0] x) (MUL x (MOVWconst [c])) && int32(c) == -1 -> (RSBconst [0] x)
(MUL _ (MOVWconst [0])) -> (MOVWconst [0]) (MUL _ (MOVWconst [0])) -> (MOVWconst [0])
......
...@@ -344,6 +344,8 @@ func init() { ...@@ -344,6 +344,8 @@ func init() {
{name: "MOVHUreg", argLength: 1, reg: gp11, asm: "MOVHU"}, // move from arg0, unsign-extended from half {name: "MOVHUreg", argLength: 1, reg: gp11, asm: "MOVHU"}, // move from arg0, unsign-extended from half
{name: "MOVWreg", argLength: 1, reg: gp11, asm: "MOVW"}, // move from arg0 {name: "MOVWreg", argLength: 1, reg: gp11, asm: "MOVW"}, // move from arg0
{name: "MOVWnop", argLength: 1, reg: regInfo{inputs: []regMask{gp}, outputs: []regMask{gp}}, resultInArg0: true}, // nop, return arg0 in same register
{name: "MOVWF", argLength: 1, reg: gpfp, asm: "MOVWF"}, // int32 -> float32 {name: "MOVWF", argLength: 1, reg: gpfp, asm: "MOVWF"}, // int32 -> float32
{name: "MOVWD", argLength: 1, reg: gpfp, asm: "MOVWD"}, // int32 -> float64 {name: "MOVWD", argLength: 1, reg: gpfp, asm: "MOVWD"}, // int32 -> float64
{name: "MOVWUF", argLength: 1, reg: gpfp, asm: "MOVWF"}, // uint32 -> float32, set U bit in the instruction {name: "MOVWUF", argLength: 1, reg: gpfp, asm: "MOVWF"}, // uint32 -> float32, set U bit in the instruction
......
...@@ -729,6 +729,7 @@ const ( ...@@ -729,6 +729,7 @@ const (
OpARMMOVHreg OpARMMOVHreg
OpARMMOVHUreg OpARMMOVHUreg
OpARMMOVWreg OpARMMOVWreg
OpARMMOVWnop
OpARMMOVWF OpARMMOVWF
OpARMMOVWD OpARMMOVWD
OpARMMOVWUF OpARMMOVWUF
...@@ -9328,6 +9329,19 @@ var opcodeTable = [...]opInfo{ ...@@ -9328,6 +9329,19 @@ var opcodeTable = [...]opInfo{
}, },
}, },
}, },
{
name: "MOVWnop",
argLen: 1,
resultInArg0: true,
reg: regInfo{
inputs: []inputInfo{
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
outputs: []outputInfo{
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{ {
name: "MOVWF", name: "MOVWF",
argLen: 1, argLen: 1,
......
...@@ -8804,6 +8804,18 @@ func rewriteValueARM_OpARMMOVWloadshiftRL(v *Value, config *Config) bool { ...@@ -8804,6 +8804,18 @@ func rewriteValueARM_OpARMMOVWloadshiftRL(v *Value, config *Config) bool {
func rewriteValueARM_OpARMMOVWreg(v *Value, config *Config) bool { func rewriteValueARM_OpARMMOVWreg(v *Value, config *Config) bool {
b := v.Block b := v.Block
_ = b _ = b
// match: (MOVWreg x)
// cond: x.Uses == 1
// result: (MOVWnop x)
for {
x := v.Args[0]
if !(x.Uses == 1) {
break
}
v.reset(OpARMMOVWnop)
v.AddArg(x)
return true
}
// match: (MOVWreg (MOVWconst [c])) // match: (MOVWreg (MOVWconst [c]))
// cond: // cond:
// result: (MOVWconst [c]) // result: (MOVWconst [c])
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment