mirror of
https://github.com/golang/go
synced 2024-11-18 17:54:57 -07:00
cmd/compile: tweak OIF construction for binarySearch
When emitting base cases, previously we would emit: if c1 { s1 } if c2 { s2 } if c3 { s3 } With this CL, we instead emit: if c1 { s1 } else if c2 { s2 } else if c3 { s3 } Most of the time, this doesn't make a difference, because s1/s2/s3 are typically "goto" statements. But for type switches, we currently emit: if hash == 271 { if _, ok := iface.(T1); ok { goto t1case } } if hash == 314 { if _, ok := iface.(T2); ok { goto t2case } } That is, the if bodies can fallthrough, even though it's impossible for them to match any of the subsequent cases. Change-Id: I453d424d0b5e40060a703738bbb374523f1c403c Reviewed-on: https://go-review.googlesource.com/c/go/+/195339 Run-TryBot: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
parent
04fb929a5b
commit
1b2c794896
@ -397,14 +397,10 @@ func (s *exprSwitch) flush() {
|
|||||||
}
|
}
|
||||||
return le
|
return le
|
||||||
},
|
},
|
||||||
func(i int, out *Nodes) {
|
func(i int, nif *Node) {
|
||||||
c := &cc[i]
|
c := &cc[i]
|
||||||
|
nif.Left = c.test(s.exprname)
|
||||||
nif := nodl(c.pos, OIF, c.test(s.exprname), nil)
|
|
||||||
nif.Left = typecheck(nif.Left, ctxExpr)
|
|
||||||
nif.Left = defaultlit(nif.Left, nil)
|
|
||||||
nif.Nbody.Set1(c.jmp)
|
nif.Nbody.Set1(c.jmp)
|
||||||
out.Append(nif)
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -521,8 +517,8 @@ func walkTypeSwitch(sw *Node) {
|
|||||||
singleType := ncase.List.Len() == 1 && ncase.List.First().Op == OTYPE
|
singleType := ncase.List.Len() == 1 && ncase.List.First().Op == OTYPE
|
||||||
|
|
||||||
label := autolabel(".s")
|
label := autolabel(".s")
|
||||||
|
|
||||||
jmp := npos(ncase.Pos, nodSym(OGOTO, nil, label))
|
jmp := npos(ncase.Pos, nodSym(OGOTO, nil, label))
|
||||||
|
|
||||||
if ncase.List.Len() == 0 { // default:
|
if ncase.List.Len() == 0 { // default:
|
||||||
if defaultGoto != nil {
|
if defaultGoto != nil {
|
||||||
Fatalf("duplicate default case not detected during typechecking")
|
Fatalf("duplicate default case not detected during typechecking")
|
||||||
@ -672,16 +668,12 @@ func (s *typeSwitch) flush() {
|
|||||||
func(i int) *Node {
|
func(i int) *Node {
|
||||||
return nod(OLE, s.hashname, nodintconst(int64(cc[i-1].hash)))
|
return nod(OLE, s.hashname, nodintconst(int64(cc[i-1].hash)))
|
||||||
},
|
},
|
||||||
func(i int, out *Nodes) {
|
func(i int, nif *Node) {
|
||||||
// TODO(mdempsky): Omit hash equality check if
|
// TODO(mdempsky): Omit hash equality check if
|
||||||
// there's only one type.
|
// there's only one type.
|
||||||
c := cc[i]
|
c := cc[i]
|
||||||
a := nod(OIF, nil, nil)
|
nif.Left = nod(OEQ, s.hashname, nodintconst(int64(c.hash)))
|
||||||
a.Left = nod(OEQ, s.hashname, nodintconst(int64(c.hash)))
|
nif.Nbody.AppendNodes(&c.body)
|
||||||
a.Left = typecheck(a.Left, ctxExpr)
|
|
||||||
a.Left = defaultlit(a.Left, nil)
|
|
||||||
a.Nbody.AppendNodes(&c.body)
|
|
||||||
out.Append(a)
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -691,10 +683,11 @@ func (s *typeSwitch) flush() {
|
|||||||
// switch statements.
|
// switch statements.
|
||||||
//
|
//
|
||||||
// less(i) should return a boolean expression. If it evaluates true,
|
// less(i) should return a boolean expression. If it evaluates true,
|
||||||
// then cases [0, i) will be tested; otherwise, cases [i, n).
|
// then cases before i will be tested; otherwise, cases i and later.
|
||||||
//
|
//
|
||||||
// base(i, out) should append statements to out to test the i'th case.
|
// base(i, nif) should setup nif (an OIF node) to test case i. In
|
||||||
func binarySearch(n int, out *Nodes, less func(i int) *Node, base func(i int, out *Nodes)) {
|
// particular, it should set nif.Left and nif.Nbody.
|
||||||
|
func binarySearch(n int, out *Nodes, less func(i int) *Node, base func(i int, nif *Node)) {
|
||||||
const binarySearchMin = 4 // minimum number of cases for binary search
|
const binarySearchMin = 4 // minimum number of cases for binary search
|
||||||
|
|
||||||
var do func(lo, hi int, out *Nodes)
|
var do func(lo, hi int, out *Nodes)
|
||||||
@ -702,7 +695,12 @@ func binarySearch(n int, out *Nodes, less func(i int) *Node, base func(i int, ou
|
|||||||
n := hi - lo
|
n := hi - lo
|
||||||
if n < binarySearchMin {
|
if n < binarySearchMin {
|
||||||
for i := lo; i < hi; i++ {
|
for i := lo; i < hi; i++ {
|
||||||
base(i, out)
|
nif := nod(OIF, nil, nil)
|
||||||
|
base(i, nif)
|
||||||
|
nif.Left = typecheck(nif.Left, ctxExpr)
|
||||||
|
nif.Left = defaultlit(nif.Left, nil)
|
||||||
|
out.Append(nif)
|
||||||
|
out = &nif.Rlist
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user