diff options
author | David Chase <drchase@google.com> | 2018-04-05 16:14:42 -0400 |
---|---|---|
committer | David Chase <drchase@google.com> | 2018-04-11 17:35:34 +0000 |
commit | ab48574bab55eec033c4fed7f7eb4cedfaef90aa (patch) | |
tree | d3925ff6f0b4ebea6b2c292b502e44c704141009 /src/cmd/compile/internal/x86 | |
parent | 2b239969390553726d5042e723b344f897bf810d (diff) | |
download | go-ab48574bab55eec033c4fed7f7eb4cedfaef90aa.tar.gz go-ab48574bab55eec033c4fed7f7eb4cedfaef90aa.zip |
cmd/compile: use Block.Likely to put likely branch first
When a neither of a conditional block's successors follows,
the block must end with a conditional branch followed by a
an unconditional branch. If the (conditional) branch is
"unlikely", invert it and swap successors to make it
likely instead.
This doesn't matter to most benchmarks on amd64, but in one
instance on amd64 it caused a 30% improvement, and it is
otherwise harmless. The problematic loop is
for i := 0; i < w; i++ {
if pw[i] != 0 {
return true
}
}
compiled under GOEXPERIMENT=preemptibleloops
This the very worst-case benchmark for that experiment.
Also in this CL is a commoning up of heavily-repeated
boilerplate, which made it much easier to see that the
changes were applied correctly. In the future this should
allow un-exporting of SSAGenState.Branches once the
boilerplate-replacement is done everywhere.
Change-Id: I0e5ded6eeb3ab1e3e0138e12d54c7e056bd99335
Reviewed-on: https://go-review.googlesource.com/104977
Run-TryBot: David Chase <drchase@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Diffstat (limited to 'src/cmd/compile/internal/x86')
-rw-r--r-- | src/cmd/compile/internal/x86/ssa.go | 23 |
1 files changed, 9 insertions, 14 deletions
diff --git a/src/cmd/compile/internal/x86/ssa.go b/src/cmd/compile/internal/x86/ssa.go index 91cf70ff89..1e0e1f9a70 100644 --- a/src/cmd/compile/internal/x86/ssa.go +++ b/src/cmd/compile/internal/x86/ssa.go @@ -863,25 +863,20 @@ func ssaGenBlock(s *gc.SSAGenState, b, next *ssa.Block) { ssa.Block386ULT, ssa.Block386UGT, ssa.Block386ULE, ssa.Block386UGE: jmp := blockJump[b.Kind] - var p *obj.Prog switch next { case b.Succs[0].Block(): - p = s.Prog(jmp.invasm) - p.To.Type = obj.TYPE_BRANCH - s.Branches = append(s.Branches, gc.Branch{P: p, B: b.Succs[1].Block()}) + s.Br(jmp.invasm, b.Succs[1].Block()) case b.Succs[1].Block(): - p = s.Prog(jmp.asm) - p.To.Type = obj.TYPE_BRANCH - s.Branches = append(s.Branches, gc.Branch{P: p, B: b.Succs[0].Block()}) + s.Br(jmp.asm, b.Succs[0].Block()) default: - p = s.Prog(jmp.asm) - p.To.Type = obj.TYPE_BRANCH - s.Branches = append(s.Branches, gc.Branch{P: p, B: b.Succs[0].Block()}) - q := s.Prog(obj.AJMP) - q.To.Type = obj.TYPE_BRANCH - s.Branches = append(s.Branches, gc.Branch{P: q, B: b.Succs[1].Block()}) + if b.Likely != ssa.BranchUnlikely { + s.Br(jmp.asm, b.Succs[0].Block()) + s.Br(obj.AJMP, b.Succs[1].Block()) + } else { + s.Br(jmp.invasm, b.Succs[1].Block()) + s.Br(obj.AJMP, b.Succs[0].Block()) + } } - default: b.Fatalf("branch not implemented: %s. Control: %s", b.LongString(), b.Control.LongString()) } |