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: 's avatarDavid Chase <drchase@google.com>
parent 4c9a3729
......@@ -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},
// Jumps
arm64.AB & obj.AMask: {Flags: gc.Jump | gc.Break},
arm64.ABL & obj.AMask: {Flags: gc.Call},
arm64.ABEQ & obj.AMask: {Flags: gc.Cjmp},
arm64.ABNE & obj.AMask: {Flags: gc.Cjmp},
arm64.ABGE & obj.AMask: {Flags: gc.Cjmp},
arm64.ABLT & obj.AMask: {Flags: gc.Cjmp},
arm64.ABGT & obj.AMask: {Flags: gc.Cjmp},
arm64.ABLE & obj.AMask: {Flags: gc.Cjmp},
arm64.ABLO & obj.AMask: {Flags: gc.Cjmp},
arm64.ABLS & obj.AMask: {Flags: gc.Cjmp},
arm64.ABHI & obj.AMask: {Flags: gc.Cjmp},
arm64.ABHS & obj.AMask: {Flags: gc.Cjmp},
arm64.ACBZ & obj.AMask: {Flags: gc.Cjmp},
arm64.ACBNZ & obj.AMask: {Flags: gc.Cjmp},
obj.ARET: {Flags: gc.Break},
obj.ADUFFZERO: {Flags: gc.Call},
obj.ADUFFCOPY: {Flags: gc.Call},
arm64.AB & obj.AMask: {Flags: gc.Jump | gc.Break},
arm64.ABL & obj.AMask: {Flags: gc.Call},
arm64.ABEQ & obj.AMask: {Flags: gc.Cjmp},
arm64.ABNE & obj.AMask: {Flags: gc.Cjmp},
arm64.ABGE & obj.AMask: {Flags: gc.Cjmp},
arm64.ABLT & obj.AMask: {Flags: gc.Cjmp},
arm64.ABGT & obj.AMask: {Flags: gc.Cjmp},
arm64.ABLE & obj.AMask: {Flags: gc.Cjmp},
arm64.ABLO & obj.AMask: {Flags: gc.Cjmp},
arm64.ABLS & obj.AMask: {Flags: gc.Cjmp},
arm64.ABHI & obj.AMask: {Flags: gc.Cjmp},
arm64.ABHS & obj.AMask: {Flags: gc.Cjmp},
arm64.ACBZ & obj.AMask: {Flags: gc.Cjmp},
arm64.ACBNZ & obj.AMask: {Flags: gc.Cjmp},
arm64.ACBZW & obj.AMask: {Flags: gc.Cjmp},
arm64.ACBNZW & obj.AMask: {Flags: gc.Cjmp},
obj.ARET: {Flags: gc.Break},
obj.ADUFFZERO: {Flags: gc.Call},
obj.ADUFFCOPY: {Flags: gc.Call},
}
func proginfo(p *obj.Prog) gc.ProgInfo {
......
......@@ -761,6 +761,10 @@ var blockJump = map[ssa.BlockKind]struct {
ssa.BlockARM64UGE: {arm64.ABHS, arm64.ABLO},
ssa.BlockARM64UGT: {arm64.ABHI, arm64.ABLS},
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) {
......@@ -807,7 +811,9 @@ func ssaGenBlock(s *gc.SSAGenState, b, next *ssa.Block) {
ssa.BlockARM64LT, ssa.BlockARM64GE,
ssa.BlockARM64LE, ssa.BlockARM64GT,
ssa.BlockARM64ULT, ssa.BlockARM64UGT,
ssa.BlockARM64ULE, ssa.BlockARM64UGE:
ssa.BlockARM64ULE, ssa.BlockARM64UGE,
ssa.BlockARM64Z, ssa.BlockARM64NZ,
ssa.BlockARM64ZW, ssa.BlockARM64NZW:
jmp := blockJump[b.Kind]
var p *obj.Prog
switch next {
......@@ -827,6 +833,10 @@ func ssaGenBlock(s *gc.SSAGenState, b, next *ssa.Block) {
q.To.Type = obj.TYPE_BRANCH
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:
b.Fatalf("branch not implemented: %s. Control: %s", b.LongString(), b.Control.LongString())
......
......@@ -476,7 +476,7 @@
(If (GreaterEqual cc) yes no) -> (GE 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
// Note: these ops do not accept offset.
......@@ -503,16 +503,21 @@
// Optimizations
// Absorb boolean tests into block
(NE (CMPconst [0] (Equal cc)) yes no) -> (EQ cc yes no)
(NE (CMPconst [0] (NotEqual cc)) yes no) -> (NE cc yes no)
(NE (CMPconst [0] (LessThan cc)) yes no) -> (LT cc yes no)
(NE (CMPconst [0] (LessThanU cc)) yes no) -> (ULT cc yes no)
(NE (CMPconst [0] (LessEqual cc)) yes no) -> (LE cc yes no)
(NE (CMPconst [0] (LessEqualU cc)) yes no) -> (ULE cc yes no)
(NE (CMPconst [0] (GreaterThan cc)) yes no) -> (GT cc yes no)
(NE (CMPconst [0] (GreaterThanU cc)) yes no) -> (UGT cc yes no)
(NE (CMPconst [0] (GreaterEqual cc)) yes no) -> (GE cc yes no)
(NE (CMPconst [0] (GreaterEqualU cc)) yes no) -> (UGE cc yes no)
(NZ (Equal cc) yes no) -> (EQ cc yes no)
(NZ (NotEqual cc) yes no) -> (NE cc yes no)
(NZ (LessThan cc) yes no) -> (LT cc yes no)
(NZ (LessThanU cc) yes no) -> (ULT cc yes no)
(NZ (LessEqual cc) yes no) -> (LE cc yes no)
(NZ (LessEqualU cc) yes no) -> (ULE cc yes no)
(NZ (GreaterThan cc) yes no) -> (GT cc yes no)
(NZ (GreaterThanU cc) yes no) -> (UGT cc yes no)
(NZ (GreaterEqual cc) yes no) -> (GE 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
(ADDconst [off1] (MOVDaddr [off2] {sym} ptr)) -> (MOVDaddr [off1+off2] {sym} ptr)
......@@ -925,6 +930,15 @@
(UGE (FlagGT_ULT) yes no) -> (First nil no yes)
(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
(LT (InvertFlags cmp) yes no) -> (GT cmp yes no)
(GT (InvertFlags cmp) yes no) -> (LT cmp yes no)
......
......@@ -514,6 +514,10 @@ func init() {
{name: "ULE"},
{name: "UGT"},
{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{
......
......@@ -67,6 +67,10 @@ const (
BlockARM64ULE
BlockARM64UGT
BlockARM64UGE
BlockARM64Z
BlockARM64NZ
BlockARM64ZW
BlockARM64NZW
BlockMIPS64EQ
BlockMIPS64NE
......@@ -160,6 +164,10 @@ var blockString = [...]string{
BlockARM64ULE: "ULE",
BlockARM64UGT: "UGT",
BlockARM64UGE: "UGE",
BlockARM64Z: "Z",
BlockARM64NZ: "NZ",
BlockARM64ZW: "ZW",
BlockARM64NZW: "NZW",
BlockMIPS64EQ: "EQ",
BlockMIPS64NE: "NE",
......
......@@ -481,6 +481,10 @@ func relinv(a obj.As) obj.As {
return ACBNZ
case ACBNZ:
return ACBZ
case ACBZW:
return ACBNZW
case ACBNZW:
return ACBZW
}
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