Commit 8599fdd9 authored by Cherry Zhang's avatar Cherry Zhang

[dev.ssa] cmd/compile: add some ARM optimization rewriting rules

Mostly constant folding rules, analogous to AMD64 ones. Along with
some simplifications.

Updates #15365.

Change-Id: If83bc1188bb05acb982ef3a1c21704c187e3eb24
Reviewed-on: https://go-review.googlesource.com/24210
Run-TryBot: David Chase <drchase@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarDavid Chase <drchase@google.com>
parent 42181ad8
...@@ -117,7 +117,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { ...@@ -117,7 +117,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
// input args need no code // input args need no code
case ssa.OpSP, ssa.OpSB, ssa.OpGetG: case ssa.OpSP, ssa.OpSB, ssa.OpGetG:
// nothing to do // nothing to do
case ssa.OpCopy, ssa.OpARMMOVWconvert: case ssa.OpCopy, ssa.OpARMMOVWconvert, ssa.OpARMMOVWreg:
if v.Type.IsMemory() { if v.Type.IsMemory() {
return return
} }
...@@ -290,8 +290,11 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { ...@@ -290,8 +290,11 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
p.To.Type = obj.TYPE_REG p.To.Type = obj.TYPE_REG
p.To.Reg = r p.To.Reg = r
case ssa.OpARMADDconst, case ssa.OpARMADDconst,
ssa.OpARMADCconst,
ssa.OpARMSUBconst, ssa.OpARMSUBconst,
ssa.OpARMSBCconst,
ssa.OpARMRSBconst, ssa.OpARMRSBconst,
ssa.OpARMRSCconst,
ssa.OpARMANDconst, ssa.OpARMANDconst,
ssa.OpARMORconst, ssa.OpARMORconst,
ssa.OpARMXORconst, ssa.OpARMXORconst,
...@@ -305,6 +308,16 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { ...@@ -305,6 +308,16 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
p.Reg = gc.SSARegNum(v.Args[0]) p.Reg = gc.SSARegNum(v.Args[0])
p.To.Type = obj.TYPE_REG p.To.Type = obj.TYPE_REG
p.To.Reg = gc.SSARegNum(v) p.To.Reg = gc.SSARegNum(v)
case ssa.OpARMADDSconst,
ssa.OpARMSUBSconst,
ssa.OpARMRSBSconst:
p := gc.Prog(v.Op.Asm())
p.Scond = arm.C_SBIT
p.From.Type = obj.TYPE_CONST
p.From.Offset = v.AuxInt
p.Reg = gc.SSARegNum(v.Args[0])
p.To.Type = obj.TYPE_REG
p.To.Reg = gc.SSARegNum(v)
case ssa.OpARMSRRconst: case ssa.OpARMSRRconst:
p := gc.Prog(arm.AMOVW) p := gc.Prog(arm.AMOVW)
p.From.Type = obj.TYPE_SHIFT p.From.Type = obj.TYPE_SHIFT
...@@ -710,6 +723,14 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { ...@@ -710,6 +723,14 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
case ssa.OpARMLoweredGetClosurePtr: case ssa.OpARMLoweredGetClosurePtr:
// Closure pointer is R7 (arm.REGCTXT). // Closure pointer is R7 (arm.REGCTXT).
gc.CheckLoweredGetClosurePtr(v) gc.CheckLoweredGetClosurePtr(v)
case ssa.OpARMFlagEQ,
ssa.OpARMFlagLT_ULT,
ssa.OpARMFlagLT_UGT,
ssa.OpARMFlagGT_ULT,
ssa.OpARMFlagGT_UGT:
v.Fatalf("Flag* ops should never make it to codegen %v", v.LongString())
case ssa.OpARMInvertFlags:
v.Fatalf("InvertFlags should never make it to codegen %v", v.LongString())
default: default:
v.Unimplementedf("genValue not implemented: %s", v.LongString()) v.Unimplementedf("genValue not implemented: %s", v.LongString())
} }
......
This diff is collapsed.
...@@ -101,8 +101,10 @@ func init() { ...@@ -101,8 +101,10 @@ func init() {
var ( var (
gp01 = regInfo{inputs: []regMask{}, outputs: []regMask{gp}} gp01 = regInfo{inputs: []regMask{}, outputs: []regMask{gp}}
gp11 = regInfo{inputs: []regMask{gpg}, outputs: []regMask{gp}} gp11 = regInfo{inputs: []regMask{gpg}, outputs: []regMask{gp}}
gp11cf = regInfo{inputs: []regMask{gpg}, outputs: []regMask{gp}, clobbers: flags} // cf: clobbers flags
gp11sp = regInfo{inputs: []regMask{gpspg}, outputs: []regMask{gp}} gp11sp = regInfo{inputs: []regMask{gpspg}, outputs: []regMask{gp}}
gp1flags = regInfo{inputs: []regMask{gpg}, outputs: []regMask{flags}} gp1flags = regInfo{inputs: []regMask{gpg}, outputs: []regMask{flags}}
gp1flags1 = regInfo{inputs: []regMask{gp, flags}, outputs: []regMask{gp}}
gp21 = regInfo{inputs: []regMask{gpg, gpg}, outputs: []regMask{gp}} gp21 = regInfo{inputs: []regMask{gpg, gpg}, outputs: []regMask{gp}}
gp21cf = regInfo{inputs: []regMask{gpg, gpg}, outputs: []regMask{gp}, clobbers: flags} // cf: clobbers flags gp21cf = regInfo{inputs: []regMask{gpg, gpg}, outputs: []regMask{gp}, clobbers: flags} // cf: clobbers flags
gp2flags = regInfo{inputs: []regMask{gpg, gpg}, outputs: []regMask{flags}} gp2flags = regInfo{inputs: []regMask{gpg, gpg}, outputs: []regMask{flags}}
...@@ -137,9 +139,15 @@ func init() { ...@@ -137,9 +139,15 @@ func init() {
{name: "MODU", argLength: 2, reg: gp21cf, asm: "MODU"}, // arg0 % arg1, unsigned {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: "ADDSconst", argLength: 1, reg: gp11cf, asm: "ADD", aux: "Int32"}, // arg0 + auxInt, 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
{name: "ADCconst", argLength: 2, reg: gp1flags1, asm: "ADC", aux: "Int32"}, // arg0 + auxInt + carry, arg1=flags
{name: "SUBS", argLength: 2, reg: gp21cf, asm: "SUB"}, // arg0 - arg1, set carry flag {name: "SUBS", argLength: 2, reg: gp21cf, asm: "SUB"}, // arg0 - arg1, set carry flag
{name: "SUBSconst", argLength: 1, reg: gp11cf, asm: "SUB", aux: "Int32"}, // arg0 - auxInt, set carry flag
{name: "RSBSconst", argLength: 1, reg: gp11cf, asm: "RSB", aux: "Int32"}, // auxInt - arg0, set carry flag
{name: "SBC", argLength: 3, reg: gp2flags1, asm: "SBC"}, // arg0 - arg1 - carry, arg2=flags {name: "SBC", argLength: 3, reg: gp2flags1, asm: "SBC"}, // arg0 - arg1 - carry, arg2=flags
{name: "SBCconst", argLength: 2, reg: gp1flags1, asm: "SBC", aux: "Int32"}, // arg0 - auxInt - carry, arg1=flags
{name: "RSCconst", argLength: 2, reg: gp1flags1, asm: "RSC", aux: "Int32"}, // auxInt - arg0 - carry, arg1=flags
{name: "MULLU", argLength: 2, reg: regInfo{inputs: []regMask{gp, gp}, outputs: []regMask{gp &^ buildReg("R0")}, clobbers: buildReg("R0")}, asm: "MULLU", commutative: true}, // arg0 * arg1, results 64-bit, high 32-bit in R0 {name: "MULLU", argLength: 2, reg: regInfo{inputs: []regMask{gp, gp}, outputs: []regMask{gp &^ buildReg("R0")}, clobbers: buildReg("R0")}, asm: "MULLU", commutative: true}, // arg0 * arg1, results 64-bit, high 32-bit in R0
{name: "MULA", argLength: 3, reg: gp31, asm: "MULA"}, // arg0 * arg1 + arg2 {name: "MULA", argLength: 3, reg: gp31, asm: "MULA"}, // arg0 * arg1 + arg2
...@@ -211,6 +219,7 @@ func init() { ...@@ -211,6 +219,7 @@ func init() {
{name: "MOVBUreg", argLength: 1, reg: gp11, asm: "MOVBU"}, // move from arg0, unsign-extended from byte {name: "MOVBUreg", argLength: 1, reg: gp11, asm: "MOVBU"}, // move from arg0, unsign-extended from byte
{name: "MOVHreg", argLength: 1, reg: gp11, asm: "MOVHS"}, // move from arg0, sign-extended from half {name: "MOVHreg", argLength: 1, reg: gp11, asm: "MOVHS"}, // move from arg0, sign-extended from half
{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: "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
...@@ -366,6 +375,23 @@ func init() { ...@@ -366,6 +375,23 @@ func init() {
// gets correctly ordered with respect to GC safepoints. // gets correctly ordered with respect to GC safepoints.
// arg0=ptr/int arg1=mem, output=int/ptr // arg0=ptr/int arg1=mem, output=int/ptr
{name: "MOVWconvert", argLength: 2, reg: gp11, asm: "MOVW"}, {name: "MOVWconvert", argLength: 2, reg: gp11, asm: "MOVW"},
// Constant flag values. For any comparison, there are 5 possible
// outcomes: the three from the signed total order (<,==,>) and the
// three from the unsigned total order. The == cases overlap.
// Note: there's a sixth "unordered" outcome for floating-point
// comparisons, but we don't use such a beast yet.
// These ops are for temporary use by rewrite rules. They
// cannot appear in the generated assembly.
{name: "FlagEQ"}, // equal
{name: "FlagLT_ULT"}, // signed < and unsigned <
{name: "FlagLT_UGT"}, // signed < and unsigned >
{name: "FlagGT_UGT"}, // signed > and unsigned <
{name: "FlagGT_ULT"}, // signed > and unsigned >
// (InvertFlags (CMP a b)) == (CMP b a)
// InvertFlags is a pseudo-op which can't appear in assembly output.
{name: "InvertFlags", argLength: 1}, // reverse direction of arg0
} }
blocks := []blockData{ blocks := []blockData{
......
...@@ -156,7 +156,8 @@ func MakeSizeAndAlign(size, align int64) SizeAndAlign { ...@@ -156,7 +156,8 @@ func MakeSizeAndAlign(size, align int64) SizeAndAlign {
func (op Op) isTupleGenerator() bool { func (op Op) isTupleGenerator() bool {
switch op { switch op {
case OpAdd32carry, OpSub32carry, OpMul32uhilo, case OpAdd32carry, OpSub32carry, OpMul32uhilo,
OpARMADDS, OpARMSUBS, OpARMMULLU: OpARMADDS, OpARMSUBS, OpARMMULLU,
OpARMADDSconst, OpARMSUBSconst, OpARMRSBSconst:
return true return true
} }
return false return false
......
...@@ -360,9 +360,15 @@ const ( ...@@ -360,9 +360,15 @@ const (
OpARMMOD OpARMMOD
OpARMMODU OpARMMODU
OpARMADDS OpARMADDS
OpARMADDSconst
OpARMADC OpARMADC
OpARMADCconst
OpARMSUBS OpARMSUBS
OpARMSUBSconst
OpARMRSBSconst
OpARMSBC OpARMSBC
OpARMSBCconst
OpARMRSCconst
OpARMMULLU OpARMMULLU
OpARMMULA OpARMMULA
OpARMADDF OpARMADDF
...@@ -420,6 +426,7 @@ const ( ...@@ -420,6 +426,7 @@ const (
OpARMMOVBUreg OpARMMOVBUreg
OpARMMOVHreg OpARMMOVHreg
OpARMMOVHUreg OpARMMOVHUreg
OpARMMOVWreg
OpARMMOVWF OpARMMOVWF
OpARMMOVWD OpARMMOVWD
OpARMMOVWUF OpARMMOVWUF
...@@ -458,6 +465,12 @@ const ( ...@@ -458,6 +465,12 @@ const (
OpARMLoweredMoveU OpARMLoweredMoveU
OpARMLoweredGetClosurePtr OpARMLoweredGetClosurePtr
OpARMMOVWconvert OpARMMOVWconvert
OpARMFlagEQ
OpARMFlagLT_ULT
OpARMFlagLT_UGT
OpARMFlagGT_UGT
OpARMFlagGT_ULT
OpARMInvertFlags
OpPPC64ADD OpPPC64ADD
OpPPC64ADDconst OpPPC64ADDconst
...@@ -4212,6 +4225,21 @@ var opcodeTable = [...]opInfo{ ...@@ -4212,6 +4225,21 @@ var opcodeTable = [...]opInfo{
}, },
}, },
}, },
{
name: "ADDSconst",
auxType: auxInt32,
argLen: 1,
asm: arm.AADD,
reg: regInfo{
inputs: []inputInfo{
{0, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
},
clobbers: 4294967296, // FLAGS
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{ {
name: "ADC", name: "ADC",
argLen: 3, argLen: 3,
...@@ -4228,6 +4256,21 @@ var opcodeTable = [...]opInfo{ ...@@ -4228,6 +4256,21 @@ var opcodeTable = [...]opInfo{
}, },
}, },
}, },
{
name: "ADCconst",
auxType: auxInt32,
argLen: 2,
asm: arm.AADC,
reg: regInfo{
inputs: []inputInfo{
{1, 4294967296}, // FLAGS
{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: "SUBS", name: "SUBS",
argLen: 2, argLen: 2,
...@@ -4243,6 +4286,36 @@ var opcodeTable = [...]opInfo{ ...@@ -4243,6 +4286,36 @@ var opcodeTable = [...]opInfo{
}, },
}, },
}, },
{
name: "SUBSconst",
auxType: auxInt32,
argLen: 1,
asm: arm.ASUB,
reg: regInfo{
inputs: []inputInfo{
{0, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
},
clobbers: 4294967296, // FLAGS
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "RSBSconst",
auxType: auxInt32,
argLen: 1,
asm: arm.ARSB,
reg: regInfo{
inputs: []inputInfo{
{0, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
},
clobbers: 4294967296, // FLAGS
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{ {
name: "SBC", name: "SBC",
argLen: 3, argLen: 3,
...@@ -4258,6 +4331,36 @@ var opcodeTable = [...]opInfo{ ...@@ -4258,6 +4331,36 @@ var opcodeTable = [...]opInfo{
}, },
}, },
}, },
{
name: "SBCconst",
auxType: auxInt32,
argLen: 2,
asm: arm.ASBC,
reg: regInfo{
inputs: []inputInfo{
{1, 4294967296}, // FLAGS
{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: "RSCconst",
auxType: auxInt32,
argLen: 2,
asm: arm.ARSC,
reg: regInfo{
inputs: []inputInfo{
{1, 4294967296}, // FLAGS
{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: "MULLU", name: "MULLU",
argLen: 2, argLen: 2,
...@@ -5049,6 +5152,19 @@ var opcodeTable = [...]opInfo{ ...@@ -5049,6 +5152,19 @@ var opcodeTable = [...]opInfo{
}, },
}, },
}, },
{
name: "MOVWreg",
argLen: 1,
asm: arm.AMOVW,
reg: regInfo{
inputs: []inputInfo{
{0, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{ {
name: "MOVWF", name: "MOVWF",
argLen: 1, argLen: 1,
...@@ -5492,6 +5608,36 @@ var opcodeTable = [...]opInfo{ ...@@ -5492,6 +5608,36 @@ var opcodeTable = [...]opInfo{
}, },
}, },
}, },
{
name: "FlagEQ",
argLen: 0,
reg: regInfo{},
},
{
name: "FlagLT_ULT",
argLen: 0,
reg: regInfo{},
},
{
name: "FlagLT_UGT",
argLen: 0,
reg: regInfo{},
},
{
name: "FlagGT_UGT",
argLen: 0,
reg: regInfo{},
},
{
name: "FlagGT_ULT",
argLen: 0,
reg: regInfo{},
},
{
name: "InvertFlags",
argLen: 1,
reg: regInfo{},
},
{ {
name: "ADD", name: "ADD",
......
This diff is collapsed.
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