Commit b662e524 authored by Cherry Zhang's avatar Cherry Zhang

cmd/compile: use CBZ/CBNZ instrunctions on ARM64

These are conditional branches that takes a register instead of
flags as control value.

Reduce binary size by 0.7%, text size by 2.4% (cmd/go as an
exmaple).

Change-Id: I0020cfde745f9eab680b8b949ad28c87fe183afd
Reviewed-on: https://go-review.googlesource.com/30030Reviewed-by: default avatarDavid Chase <drchase@google.com>
parent 4c9a3729
...@@ -143,23 +143,25 @@ var progtable = [arm64.ALAST & obj.AMask]gc.ProgInfo{ ...@@ -143,23 +143,25 @@ var progtable = [arm64.ALAST & obj.AMask]gc.ProgInfo{
arm64.ASTLXR & obj.AMask: {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Move}, arm64.ASTLXR & obj.AMask: {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Move},
// Jumps // Jumps
arm64.AB & obj.AMask: {Flags: gc.Jump | gc.Break}, arm64.AB & obj.AMask: {Flags: gc.Jump | gc.Break},
arm64.ABL & obj.AMask: {Flags: gc.Call}, arm64.ABL & obj.AMask: {Flags: gc.Call},
arm64.ABEQ & obj.AMask: {Flags: gc.Cjmp}, arm64.ABEQ & obj.AMask: {Flags: gc.Cjmp},
arm64.ABNE & obj.AMask: {Flags: gc.Cjmp}, arm64.ABNE & obj.AMask: {Flags: gc.Cjmp},
arm64.ABGE & obj.AMask: {Flags: gc.Cjmp}, arm64.ABGE & obj.AMask: {Flags: gc.Cjmp},
arm64.ABLT & obj.AMask: {Flags: gc.Cjmp}, arm64.ABLT & obj.AMask: {Flags: gc.Cjmp},
arm64.ABGT & obj.AMask: {Flags: gc.Cjmp}, arm64.ABGT & obj.AMask: {Flags: gc.Cjmp},
arm64.ABLE & obj.AMask: {Flags: gc.Cjmp}, arm64.ABLE & obj.AMask: {Flags: gc.Cjmp},
arm64.ABLO & obj.AMask: {Flags: gc.Cjmp}, arm64.ABLO & obj.AMask: {Flags: gc.Cjmp},
arm64.ABLS & obj.AMask: {Flags: gc.Cjmp}, arm64.ABLS & obj.AMask: {Flags: gc.Cjmp},
arm64.ABHI & obj.AMask: {Flags: gc.Cjmp}, arm64.ABHI & obj.AMask: {Flags: gc.Cjmp},
arm64.ABHS & obj.AMask: {Flags: gc.Cjmp}, arm64.ABHS & obj.AMask: {Flags: gc.Cjmp},
arm64.ACBZ & obj.AMask: {Flags: gc.Cjmp}, arm64.ACBZ & obj.AMask: {Flags: gc.Cjmp},
arm64.ACBNZ & obj.AMask: {Flags: gc.Cjmp}, arm64.ACBNZ & obj.AMask: {Flags: gc.Cjmp},
obj.ARET: {Flags: gc.Break}, arm64.ACBZW & obj.AMask: {Flags: gc.Cjmp},
obj.ADUFFZERO: {Flags: gc.Call}, arm64.ACBNZW & obj.AMask: {Flags: gc.Cjmp},
obj.ADUFFCOPY: {Flags: gc.Call}, obj.ARET: {Flags: gc.Break},
obj.ADUFFZERO: {Flags: gc.Call},
obj.ADUFFCOPY: {Flags: gc.Call},
} }
func proginfo(p *obj.Prog) gc.ProgInfo { func proginfo(p *obj.Prog) gc.ProgInfo {
......
...@@ -761,6 +761,10 @@ var blockJump = map[ssa.BlockKind]struct { ...@@ -761,6 +761,10 @@ var blockJump = map[ssa.BlockKind]struct {
ssa.BlockARM64UGE: {arm64.ABHS, arm64.ABLO}, ssa.BlockARM64UGE: {arm64.ABHS, arm64.ABLO},
ssa.BlockARM64UGT: {arm64.ABHI, arm64.ABLS}, ssa.BlockARM64UGT: {arm64.ABHI, arm64.ABLS},
ssa.BlockARM64ULE: {arm64.ABLS, arm64.ABHI}, ssa.BlockARM64ULE: {arm64.ABLS, arm64.ABHI},
ssa.BlockARM64Z: {arm64.ACBZ, arm64.ACBNZ},
ssa.BlockARM64NZ: {arm64.ACBNZ, arm64.ACBZ},
ssa.BlockARM64ZW: {arm64.ACBZW, arm64.ACBNZW},
ssa.BlockARM64NZW: {arm64.ACBNZW, arm64.ACBZW},
} }
func ssaGenBlock(s *gc.SSAGenState, b, next *ssa.Block) { func ssaGenBlock(s *gc.SSAGenState, b, next *ssa.Block) {
...@@ -807,7 +811,9 @@ func ssaGenBlock(s *gc.SSAGenState, b, next *ssa.Block) { ...@@ -807,7 +811,9 @@ func ssaGenBlock(s *gc.SSAGenState, b, next *ssa.Block) {
ssa.BlockARM64LT, ssa.BlockARM64GE, ssa.BlockARM64LT, ssa.BlockARM64GE,
ssa.BlockARM64LE, ssa.BlockARM64GT, ssa.BlockARM64LE, ssa.BlockARM64GT,
ssa.BlockARM64ULT, ssa.BlockARM64UGT, ssa.BlockARM64ULT, ssa.BlockARM64UGT,
ssa.BlockARM64ULE, ssa.BlockARM64UGE: ssa.BlockARM64ULE, ssa.BlockARM64UGE,
ssa.BlockARM64Z, ssa.BlockARM64NZ,
ssa.BlockARM64ZW, ssa.BlockARM64NZW:
jmp := blockJump[b.Kind] jmp := blockJump[b.Kind]
var p *obj.Prog var p *obj.Prog
switch next { switch next {
...@@ -827,6 +833,10 @@ func ssaGenBlock(s *gc.SSAGenState, b, next *ssa.Block) { ...@@ -827,6 +833,10 @@ func ssaGenBlock(s *gc.SSAGenState, b, next *ssa.Block) {
q.To.Type = obj.TYPE_BRANCH q.To.Type = obj.TYPE_BRANCH
s.Branches = append(s.Branches, gc.Branch{P: q, B: b.Succs[1].Block()}) s.Branches = append(s.Branches, gc.Branch{P: q, B: b.Succs[1].Block()})
} }
if !b.Control.Type.IsFlags() {
p.From.Type = obj.TYPE_REG
p.From.Reg = b.Control.Reg()
}
default: default:
b.Fatalf("branch not implemented: %s. Control: %s", b.LongString(), b.Control.LongString()) b.Fatalf("branch not implemented: %s. Control: %s", b.LongString(), b.Control.LongString())
......
...@@ -476,7 +476,7 @@ ...@@ -476,7 +476,7 @@
(If (GreaterEqual cc) yes no) -> (GE cc yes no) (If (GreaterEqual cc) yes no) -> (GE cc yes no)
(If (GreaterEqualU cc) yes no) -> (UGE cc yes no) (If (GreaterEqualU cc) yes no) -> (UGE cc yes no)
(If cond yes no) -> (NE (CMPconst [0] cond) yes no) (If cond yes no) -> (NZ cond yes no)
// atomic intrinsics // atomic intrinsics
// Note: these ops do not accept offset. // Note: these ops do not accept offset.
...@@ -503,16 +503,21 @@ ...@@ -503,16 +503,21 @@
// Optimizations // Optimizations
// Absorb boolean tests into block // Absorb boolean tests into block
(NE (CMPconst [0] (Equal cc)) yes no) -> (EQ cc yes no) (NZ (Equal cc) yes no) -> (EQ cc yes no)
(NE (CMPconst [0] (NotEqual cc)) yes no) -> (NE cc yes no) (NZ (NotEqual cc) yes no) -> (NE cc yes no)
(NE (CMPconst [0] (LessThan cc)) yes no) -> (LT cc yes no) (NZ (LessThan cc) yes no) -> (LT cc yes no)
(NE (CMPconst [0] (LessThanU cc)) yes no) -> (ULT cc yes no) (NZ (LessThanU cc) yes no) -> (ULT cc yes no)
(NE (CMPconst [0] (LessEqual cc)) yes no) -> (LE cc yes no) (NZ (LessEqual cc) yes no) -> (LE cc yes no)
(NE (CMPconst [0] (LessEqualU cc)) yes no) -> (ULE cc yes no) (NZ (LessEqualU cc) yes no) -> (ULE cc yes no)
(NE (CMPconst [0] (GreaterThan cc)) yes no) -> (GT cc yes no) (NZ (GreaterThan cc) yes no) -> (GT cc yes no)
(NE (CMPconst [0] (GreaterThanU cc)) yes no) -> (UGT cc yes no) (NZ (GreaterThanU cc) yes no) -> (UGT cc yes no)
(NE (CMPconst [0] (GreaterEqual cc)) yes no) -> (GE cc yes no) (NZ (GreaterEqual cc) yes no) -> (GE cc yes no)
(NE (CMPconst [0] (GreaterEqualU cc)) yes no) -> (UGE cc yes no) (NZ (GreaterEqualU cc) yes no) -> (UGE cc yes no)
(EQ (CMPconst [0] x) yes no) -> (Z x yes no)
(NE (CMPconst [0] x) yes no) -> (NZ x yes no)
(EQ (CMPWconst [0] x) yes no) -> (ZW x yes no)
(NE (CMPWconst [0] x) yes no) -> (NZW x yes no)
// fold offset into address // fold offset into address
(ADDconst [off1] (MOVDaddr [off2] {sym} ptr)) -> (MOVDaddr [off1+off2] {sym} ptr) (ADDconst [off1] (MOVDaddr [off2] {sym} ptr)) -> (MOVDaddr [off1+off2] {sym} ptr)
...@@ -925,6 +930,15 @@ ...@@ -925,6 +930,15 @@
(UGE (FlagGT_ULT) yes no) -> (First nil no yes) (UGE (FlagGT_ULT) yes no) -> (First nil no yes)
(UGE (FlagGT_UGT) yes no) -> (First nil yes no) (UGE (FlagGT_UGT) yes no) -> (First nil yes no)
(Z (MOVDconst [0]) yes no) -> (First nil yes no)
(Z (MOVDconst [c]) yes no) && c != 0 -> (First nil no yes)
(NZ (MOVDconst [0]) yes no) -> (First nil no yes)
(NZ (MOVDconst [c]) yes no) && c != 0 -> (First nil yes no)
(ZW (MOVDconst [c]) yes no) && int32(c) == 0 -> (First nil yes no)
(ZW (MOVDconst [c]) yes no) && int32(c) != 0 -> (First nil no yes)
(NZW (MOVDconst [c]) yes no) && int32(c) == 0 -> (First nil no yes)
(NZW (MOVDconst [c]) yes no) && int32(c) != 0 -> (First nil yes no)
// absorb InvertFlags into branches // absorb InvertFlags into branches
(LT (InvertFlags cmp) yes no) -> (GT cmp yes no) (LT (InvertFlags cmp) yes no) -> (GT cmp yes no)
(GT (InvertFlags cmp) yes no) -> (LT cmp yes no) (GT (InvertFlags cmp) yes no) -> (LT cmp yes no)
......
...@@ -514,6 +514,10 @@ func init() { ...@@ -514,6 +514,10 @@ func init() {
{name: "ULE"}, {name: "ULE"},
{name: "UGT"}, {name: "UGT"},
{name: "UGE"}, {name: "UGE"},
{name: "Z"}, // Control == 0 (take a register instead of flags)
{name: "NZ"}, // Control != 0
{name: "ZW"}, // Control == 0, 32-bit
{name: "NZW"}, // Control != 0, 32-bit
} }
archs = append(archs, arch{ archs = append(archs, arch{
......
...@@ -67,6 +67,10 @@ const ( ...@@ -67,6 +67,10 @@ const (
BlockARM64ULE BlockARM64ULE
BlockARM64UGT BlockARM64UGT
BlockARM64UGE BlockARM64UGE
BlockARM64Z
BlockARM64NZ
BlockARM64ZW
BlockARM64NZW
BlockMIPS64EQ BlockMIPS64EQ
BlockMIPS64NE BlockMIPS64NE
...@@ -160,6 +164,10 @@ var blockString = [...]string{ ...@@ -160,6 +164,10 @@ var blockString = [...]string{
BlockARM64ULE: "ULE", BlockARM64ULE: "ULE",
BlockARM64UGT: "UGT", BlockARM64UGT: "UGT",
BlockARM64UGE: "UGE", BlockARM64UGE: "UGE",
BlockARM64Z: "Z",
BlockARM64NZ: "NZ",
BlockARM64ZW: "ZW",
BlockARM64NZW: "NZW",
BlockMIPS64EQ: "EQ", BlockMIPS64EQ: "EQ",
BlockMIPS64NE: "NE", BlockMIPS64NE: "NE",
......
...@@ -15070,6 +15070,46 @@ func rewriteValueARM64_OpZeroExt8to64(v *Value, config *Config) bool { ...@@ -15070,6 +15070,46 @@ func rewriteValueARM64_OpZeroExt8to64(v *Value, config *Config) bool {
func rewriteBlockARM64(b *Block, config *Config) bool { func rewriteBlockARM64(b *Block, config *Config) bool {
switch b.Kind { switch b.Kind {
case BlockARM64EQ: case BlockARM64EQ:
// match: (EQ (CMPconst [0] x) yes no)
// cond:
// result: (Z x yes no)
for {
v := b.Control
if v.Op != OpARM64CMPconst {
break
}
if v.AuxInt != 0 {
break
}
x := v.Args[0]
yes := b.Succs[0]
no := b.Succs[1]
b.Kind = BlockARM64Z
b.SetControl(x)
_ = yes
_ = no
return true
}
// match: (EQ (CMPWconst [0] x) yes no)
// cond:
// result: (ZW x yes no)
for {
v := b.Control
if v.Op != OpARM64CMPWconst {
break
}
if v.AuxInt != 0 {
break
}
x := v.Args[0]
yes := b.Succs[0]
no := b.Succs[1]
b.Kind = BlockARM64ZW
b.SetControl(x)
_ = yes
_ = no
return true
}
// match: (EQ (FlagEQ) yes no) // match: (EQ (FlagEQ) yes no)
// cond: // cond:
// result: (First nil yes no) // result: (First nil yes no)
...@@ -15545,18 +15585,15 @@ func rewriteBlockARM64(b *Block, config *Config) bool { ...@@ -15545,18 +15585,15 @@ func rewriteBlockARM64(b *Block, config *Config) bool {
} }
// match: (If cond yes no) // match: (If cond yes no)
// cond: // cond:
// result: (NE (CMPconst [0] cond) yes no) // result: (NZ cond yes no)
for { for {
v := b.Control v := b.Control
_ = v _ = v
cond := b.Control cond := b.Control
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockARM64NE b.Kind = BlockARM64NZ
v0 := b.NewValue0(v.Line, OpARM64CMPconst, TypeFlags) b.SetControl(cond)
v0.AuxInt = 0
v0.AddArg(cond)
b.SetControl(v0)
_ = yes _ = yes
_ = no _ = no
return true return true
...@@ -15763,9 +15800,9 @@ func rewriteBlockARM64(b *Block, config *Config) bool { ...@@ -15763,9 +15800,9 @@ func rewriteBlockARM64(b *Block, config *Config) bool {
return true return true
} }
case BlockARM64NE: case BlockARM64NE:
// match: (NE (CMPconst [0] (Equal cc)) yes no) // match: (NE (CMPconst [0] x) yes no)
// cond: // cond:
// result: (EQ cc yes no) // result: (NZ x yes no)
for { for {
v := b.Control v := b.Control
if v.Op != OpARM64CMPconst { if v.Op != OpARM64CMPconst {
...@@ -15774,107 +15811,211 @@ func rewriteBlockARM64(b *Block, config *Config) bool { ...@@ -15774,107 +15811,211 @@ func rewriteBlockARM64(b *Block, config *Config) bool {
if v.AuxInt != 0 { if v.AuxInt != 0 {
break break
} }
v_0 := v.Args[0] x := v.Args[0]
if v_0.Op != OpARM64Equal {
break
}
cc := v_0.Args[0]
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockARM64EQ b.Kind = BlockARM64NZ
b.SetControl(cc) b.SetControl(x)
_ = yes _ = yes
_ = no _ = no
return true return true
} }
// match: (NE (CMPconst [0] (NotEqual cc)) yes no) // match: (NE (CMPWconst [0] x) yes no)
// cond: // cond:
// result: (NE cc yes no) // result: (NZW x yes no)
for { for {
v := b.Control v := b.Control
if v.Op != OpARM64CMPconst { if v.Op != OpARM64CMPWconst {
break break
} }
if v.AuxInt != 0 { if v.AuxInt != 0 {
break break
} }
v_0 := v.Args[0] x := v.Args[0]
if v_0.Op != OpARM64NotEqual { yes := b.Succs[0]
no := b.Succs[1]
b.Kind = BlockARM64NZW
b.SetControl(x)
_ = yes
_ = no
return true
}
// match: (NE (FlagEQ) yes no)
// cond:
// result: (First nil no yes)
for {
v := b.Control
if v.Op != OpARM64FlagEQ {
break break
} }
cc := v_0.Args[0]
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockARM64NE b.Kind = BlockFirst
b.SetControl(cc) b.SetControl(nil)
b.swapSuccessors()
_ = no
_ = yes
return true
}
// match: (NE (FlagLT_ULT) yes no)
// cond:
// result: (First nil yes no)
for {
v := b.Control
if v.Op != OpARM64FlagLT_ULT {
break
}
yes := b.Succs[0]
no := b.Succs[1]
b.Kind = BlockFirst
b.SetControl(nil)
_ = yes _ = yes
_ = no _ = no
return true return true
} }
// match: (NE (CMPconst [0] (LessThan cc)) yes no) // match: (NE (FlagLT_UGT) yes no)
// cond: // cond:
// result: (LT cc yes no) // result: (First nil yes no)
for { for {
v := b.Control v := b.Control
if v.Op != OpARM64CMPconst { if v.Op != OpARM64FlagLT_UGT {
break break
} }
if v.AuxInt != 0 { yes := b.Succs[0]
no := b.Succs[1]
b.Kind = BlockFirst
b.SetControl(nil)
_ = yes
_ = no
return true
}
// match: (NE (FlagGT_ULT) yes no)
// cond:
// result: (First nil yes no)
for {
v := b.Control
if v.Op != OpARM64FlagGT_ULT {
break break
} }
v_0 := v.Args[0] yes := b.Succs[0]
if v_0.Op != OpARM64LessThan { no := b.Succs[1]
b.Kind = BlockFirst
b.SetControl(nil)
_ = yes
_ = no
return true
}
// match: (NE (FlagGT_UGT) yes no)
// cond:
// result: (First nil yes no)
for {
v := b.Control
if v.Op != OpARM64FlagGT_UGT {
break break
} }
cc := v_0.Args[0]
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockARM64LT b.Kind = BlockFirst
b.SetControl(cc) b.SetControl(nil)
_ = yes _ = yes
_ = no _ = no
return true return true
} }
// match: (NE (CMPconst [0] (LessThanU cc)) yes no) // match: (NE (InvertFlags cmp) yes no)
// cond: // cond:
// result: (ULT cc yes no) // result: (NE cmp yes no)
for { for {
v := b.Control v := b.Control
if v.Op != OpARM64CMPconst { if v.Op != OpARM64InvertFlags {
break break
} }
if v.AuxInt != 0 { cmp := v.Args[0]
yes := b.Succs[0]
no := b.Succs[1]
b.Kind = BlockARM64NE
b.SetControl(cmp)
_ = yes
_ = no
return true
}
case BlockARM64NZ:
// match: (NZ (Equal cc) yes no)
// cond:
// result: (EQ cc yes no)
for {
v := b.Control
if v.Op != OpARM64Equal {
break break
} }
v_0 := v.Args[0] cc := v.Args[0]
if v_0.Op != OpARM64LessThanU { yes := b.Succs[0]
no := b.Succs[1]
b.Kind = BlockARM64EQ
b.SetControl(cc)
_ = yes
_ = no
return true
}
// match: (NZ (NotEqual cc) yes no)
// cond:
// result: (NE cc yes no)
for {
v := b.Control
if v.Op != OpARM64NotEqual {
break break
} }
cc := v_0.Args[0] cc := v.Args[0]
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockARM64ULT b.Kind = BlockARM64NE
b.SetControl(cc) b.SetControl(cc)
_ = yes _ = yes
_ = no _ = no
return true return true
} }
// match: (NE (CMPconst [0] (LessEqual cc)) yes no) // match: (NZ (LessThan cc) yes no)
// cond: // cond:
// result: (LE cc yes no) // result: (LT cc yes no)
for { for {
v := b.Control v := b.Control
if v.Op != OpARM64CMPconst { if v.Op != OpARM64LessThan {
break break
} }
if v.AuxInt != 0 { cc := v.Args[0]
yes := b.Succs[0]
no := b.Succs[1]
b.Kind = BlockARM64LT
b.SetControl(cc)
_ = yes
_ = no
return true
}
// match: (NZ (LessThanU cc) yes no)
// cond:
// result: (ULT cc yes no)
for {
v := b.Control
if v.Op != OpARM64LessThanU {
break break
} }
v_0 := v.Args[0] cc := v.Args[0]
if v_0.Op != OpARM64LessEqual { yes := b.Succs[0]
no := b.Succs[1]
b.Kind = BlockARM64ULT
b.SetControl(cc)
_ = yes
_ = no
return true
}
// match: (NZ (LessEqual cc) yes no)
// cond:
// result: (LE cc yes no)
for {
v := b.Control
if v.Op != OpARM64LessEqual {
break break
} }
cc := v_0.Args[0] cc := v.Args[0]
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockARM64LE b.Kind = BlockARM64LE
...@@ -15883,22 +16024,15 @@ func rewriteBlockARM64(b *Block, config *Config) bool { ...@@ -15883,22 +16024,15 @@ func rewriteBlockARM64(b *Block, config *Config) bool {
_ = no _ = no
return true return true
} }
// match: (NE (CMPconst [0] (LessEqualU cc)) yes no) // match: (NZ (LessEqualU cc) yes no)
// cond: // cond:
// result: (ULE cc yes no) // result: (ULE cc yes no)
for { for {
v := b.Control v := b.Control
if v.Op != OpARM64CMPconst { if v.Op != OpARM64LessEqualU {
break
}
if v.AuxInt != 0 {
break
}
v_0 := v.Args[0]
if v_0.Op != OpARM64LessEqualU {
break break
} }
cc := v_0.Args[0] cc := v.Args[0]
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockARM64ULE b.Kind = BlockARM64ULE
...@@ -15907,22 +16041,15 @@ func rewriteBlockARM64(b *Block, config *Config) bool { ...@@ -15907,22 +16041,15 @@ func rewriteBlockARM64(b *Block, config *Config) bool {
_ = no _ = no
return true return true
} }
// match: (NE (CMPconst [0] (GreaterThan cc)) yes no) // match: (NZ (GreaterThan cc) yes no)
// cond: // cond:
// result: (GT cc yes no) // result: (GT cc yes no)
for { for {
v := b.Control v := b.Control
if v.Op != OpARM64CMPconst { if v.Op != OpARM64GreaterThan {
break
}
if v.AuxInt != 0 {
break
}
v_0 := v.Args[0]
if v_0.Op != OpARM64GreaterThan {
break break
} }
cc := v_0.Args[0] cc := v.Args[0]
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockARM64GT b.Kind = BlockARM64GT
...@@ -15931,22 +16058,15 @@ func rewriteBlockARM64(b *Block, config *Config) bool { ...@@ -15931,22 +16058,15 @@ func rewriteBlockARM64(b *Block, config *Config) bool {
_ = no _ = no
return true return true
} }
// match: (NE (CMPconst [0] (GreaterThanU cc)) yes no) // match: (NZ (GreaterThanU cc) yes no)
// cond: // cond:
// result: (UGT cc yes no) // result: (UGT cc yes no)
for { for {
v := b.Control v := b.Control
if v.Op != OpARM64CMPconst { if v.Op != OpARM64GreaterThanU {
break
}
if v.AuxInt != 0 {
break
}
v_0 := v.Args[0]
if v_0.Op != OpARM64GreaterThanU {
break break
} }
cc := v_0.Args[0] cc := v.Args[0]
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockARM64UGT b.Kind = BlockARM64UGT
...@@ -15955,22 +16075,15 @@ func rewriteBlockARM64(b *Block, config *Config) bool { ...@@ -15955,22 +16075,15 @@ func rewriteBlockARM64(b *Block, config *Config) bool {
_ = no _ = no
return true return true
} }
// match: (NE (CMPconst [0] (GreaterEqual cc)) yes no) // match: (NZ (GreaterEqual cc) yes no)
// cond: // cond:
// result: (GE cc yes no) // result: (GE cc yes no)
for { for {
v := b.Control v := b.Control
if v.Op != OpARM64CMPconst { if v.Op != OpARM64GreaterEqual {
break
}
if v.AuxInt != 0 {
break
}
v_0 := v.Args[0]
if v_0.Op != OpARM64GreaterEqual {
break break
} }
cc := v_0.Args[0] cc := v.Args[0]
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockARM64GE b.Kind = BlockARM64GE
...@@ -15979,22 +16092,15 @@ func rewriteBlockARM64(b *Block, config *Config) bool { ...@@ -15979,22 +16092,15 @@ func rewriteBlockARM64(b *Block, config *Config) bool {
_ = no _ = no
return true return true
} }
// match: (NE (CMPconst [0] (GreaterEqualU cc)) yes no) // match: (NZ (GreaterEqualU cc) yes no)
// cond: // cond:
// result: (UGE cc yes no) // result: (UGE cc yes no)
for { for {
v := b.Control v := b.Control
if v.Op != OpARM64CMPconst { if v.Op != OpARM64GreaterEqualU {
break
}
if v.AuxInt != 0 {
break
}
v_0 := v.Args[0]
if v_0.Op != OpARM64GreaterEqualU {
break break
} }
cc := v_0.Args[0] cc := v.Args[0]
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockARM64UGE b.Kind = BlockARM64UGE
...@@ -16003,12 +16109,15 @@ func rewriteBlockARM64(b *Block, config *Config) bool { ...@@ -16003,12 +16109,15 @@ func rewriteBlockARM64(b *Block, config *Config) bool {
_ = no _ = no
return true return true
} }
// match: (NE (FlagEQ) yes no) // match: (NZ (MOVDconst [0]) yes no)
// cond: // cond:
// result: (First nil no yes) // result: (First nil no yes)
for { for {
v := b.Control v := b.Control
if v.Op != OpARM64FlagEQ { if v.Op != OpARM64MOVDconst {
break
}
if v.AuxInt != 0 {
break break
} }
yes := b.Succs[0] yes := b.Succs[0]
...@@ -16020,83 +16129,64 @@ func rewriteBlockARM64(b *Block, config *Config) bool { ...@@ -16020,83 +16129,64 @@ func rewriteBlockARM64(b *Block, config *Config) bool {
_ = yes _ = yes
return true return true
} }
// match: (NE (FlagLT_ULT) yes no) // match: (NZ (MOVDconst [c]) yes no)
// cond: // cond: c != 0
// result: (First nil yes no) // result: (First nil yes no)
for { for {
v := b.Control v := b.Control
if v.Op != OpARM64FlagLT_ULT { if v.Op != OpARM64MOVDconst {
break break
} }
c := v.AuxInt
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockFirst if !(c != 0) {
b.SetControl(nil)
_ = yes
_ = no
return true
}
// match: (NE (FlagLT_UGT) yes no)
// cond:
// result: (First nil yes no)
for {
v := b.Control
if v.Op != OpARM64FlagLT_UGT {
break break
} }
yes := b.Succs[0]
no := b.Succs[1]
b.Kind = BlockFirst b.Kind = BlockFirst
b.SetControl(nil) b.SetControl(nil)
_ = yes _ = yes
_ = no _ = no
return true return true
} }
// match: (NE (FlagGT_ULT) yes no) case BlockARM64NZW:
// cond: // match: (NZW (MOVDconst [c]) yes no)
// result: (First nil yes no) // cond: int32(c) == 0
// result: (First nil no yes)
for { for {
v := b.Control v := b.Control
if v.Op != OpARM64FlagGT_ULT { if v.Op != OpARM64MOVDconst {
break break
} }
c := v.AuxInt
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
if !(int32(c) == 0) {
break
}
b.Kind = BlockFirst b.Kind = BlockFirst
b.SetControl(nil) b.SetControl(nil)
_ = yes b.swapSuccessors()
_ = no _ = no
_ = yes
return true return true
} }
// match: (NE (FlagGT_UGT) yes no) // match: (NZW (MOVDconst [c]) yes no)
// cond: // cond: int32(c) != 0
// result: (First nil yes no) // result: (First nil yes no)
for { for {
v := b.Control v := b.Control
if v.Op != OpARM64FlagGT_UGT { if v.Op != OpARM64MOVDconst {
break break
} }
c := v.AuxInt
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockFirst if !(int32(c) != 0) {
b.SetControl(nil)
_ = yes
_ = no
return true
}
// match: (NE (InvertFlags cmp) yes no)
// cond:
// result: (NE cmp yes no)
for {
v := b.Control
if v.Op != OpARM64InvertFlags {
break break
} }
cmp := v.Args[0] b.Kind = BlockFirst
yes := b.Succs[0] b.SetControl(nil)
no := b.Succs[1]
b.Kind = BlockARM64NE
b.SetControl(cmp)
_ = yes _ = yes
_ = no _ = no
return true return true
...@@ -16503,6 +16593,89 @@ func rewriteBlockARM64(b *Block, config *Config) bool { ...@@ -16503,6 +16593,89 @@ func rewriteBlockARM64(b *Block, config *Config) bool {
_ = no _ = no
return true return true
} }
case BlockARM64Z:
// match: (Z (MOVDconst [0]) yes no)
// cond:
// result: (First nil yes no)
for {
v := b.Control
if v.Op != OpARM64MOVDconst {
break
}
if v.AuxInt != 0 {
break
}
yes := b.Succs[0]
no := b.Succs[1]
b.Kind = BlockFirst
b.SetControl(nil)
_ = yes
_ = no
return true
}
// match: (Z (MOVDconst [c]) yes no)
// cond: c != 0
// result: (First nil no yes)
for {
v := b.Control
if v.Op != OpARM64MOVDconst {
break
}
c := v.AuxInt
yes := b.Succs[0]
no := b.Succs[1]
if !(c != 0) {
break
}
b.Kind = BlockFirst
b.SetControl(nil)
b.swapSuccessors()
_ = no
_ = yes
return true
}
case BlockARM64ZW:
// match: (ZW (MOVDconst [c]) yes no)
// cond: int32(c) == 0
// result: (First nil yes no)
for {
v := b.Control
if v.Op != OpARM64MOVDconst {
break
}
c := v.AuxInt
yes := b.Succs[0]
no := b.Succs[1]
if !(int32(c) == 0) {
break
}
b.Kind = BlockFirst
b.SetControl(nil)
_ = yes
_ = no
return true
}
// match: (ZW (MOVDconst [c]) yes no)
// cond: int32(c) != 0
// result: (First nil no yes)
for {
v := b.Control
if v.Op != OpARM64MOVDconst {
break
}
c := v.AuxInt
yes := b.Succs[0]
no := b.Succs[1]
if !(int32(c) != 0) {
break
}
b.Kind = BlockFirst
b.SetControl(nil)
b.swapSuccessors()
_ = no
_ = yes
return true
}
} }
return false return false
} }
...@@ -481,6 +481,10 @@ func relinv(a obj.As) obj.As { ...@@ -481,6 +481,10 @@ func relinv(a obj.As) obj.As {
return ACBNZ return ACBNZ
case ACBNZ: case ACBNZ:
return ACBZ return ACBZ
case ACBZW:
return ACBNZW
case ACBNZW:
return ACBZW
} }
log.Fatalf("unknown relation: %s", Anames[a-obj.ABaseARM64]) log.Fatalf("unknown relation: %s", Anames[a-obj.ABaseARM64])
......
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