]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.regabi] cmd/compile: use OSELRECV2 for all <-c variants
authorCuong Manh Le <cuong.manhle.vn@gmail.com>
Sun, 6 Dec 2020 20:24:04 +0000 (03:24 +0700)
committerCuong Manh Le <cuong.manhle.vn@gmail.com>
Thu, 17 Dec 2020 15:50:38 +0000 (15:50 +0000)
OSELRECV2 can represent all possible receive clauses that can appear
in a select statement, and it simplifies later code, so use it instead.

Follow up CL will remove OSELRECV.

Passes buildall w/ toolstash -cmp.

Change-Id: Ibbdae45287ffd888acd8dc89ca8d99e454277cd1
Reviewed-on: https://go-review.googlesource.com/c/go/+/275458
Trust: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Russ Cox <rsc@golang.org>
src/cmd/compile/internal/gc/escape.go
src/cmd/compile/internal/gc/order.go
src/cmd/compile/internal/gc/select.go

index d009a55a96b0db0d0af36f27bbd5e9cc3bee792f..5124af945efeaae75617d4ddfd3f15a92d7fee92 100644 (file)
@@ -399,9 +399,6 @@ func (e *Escape) stmt(n ir.Node) {
                        e.stmt(cas.Left())
                        e.block(cas.Body())
                }
-       case ir.OSELRECV:
-               n := n.(*ir.AssignStmt)
-               e.assign(n.Left(), n.Right(), "selrecv", n)
        case ir.OSELRECV2:
                n := n.(*ir.AssignListStmt)
                e.assign(n.List().First(), n.Rlist().First(), "selrecv", n)
index b0a9c9be3e1333e24566b3f667d1f0038bdadf45..0034556995b3bf815e2e077cf527606bdc050a4e 100644 (file)
@@ -872,15 +872,14 @@ func (o *Order) stmt(n ir.Node) {
        // give this away).
        case ir.OSELECT:
                t := o.markTemp()
-
-               for _, cas := range n.List().Slice() {
-                       cas := cas.(*ir.CaseStmt)
-                       r := cas.Left()
-                       setlineno(cas)
+               for _, ncas := range n.List().Slice() {
+                       ncas := ncas.(*ir.CaseStmt)
+                       r := ncas.Left()
+                       setlineno(ncas)
 
                        // Append any new body prologue to ninit.
                        // The next loop will insert ninit into nbody.
-                       if cas.Init().Len() != 0 {
+                       if ncas.Init().Len() != 0 {
                                base.Fatalf("order select ninit")
                        }
                        if r == nil {
@@ -891,84 +890,48 @@ func (o *Order) stmt(n ir.Node) {
                                ir.Dump("select case", r)
                                base.Fatalf("unknown op in select %v", r.Op())
 
-                       case ir.OSELRECV, ir.OSELRECV2:
-                               var dst, ok ir.Node
-                               var recv *ir.UnaryExpr
-                               var def bool
-                               if r.Op() == ir.OSELRECV {
-                                       // case x = <-c
-                                       // case <-c (dst is ir.BlankNode)
-                                       def, dst, ok, recv = r.Colas(), r.Left(), ir.BlankNode, r.Right().(*ir.UnaryExpr)
-                               } else {
-                                       r := r.(*ir.AssignListStmt)
-                                       // case x, ok = <-c
-                                       def, dst, ok, recv = r.Colas(), r.List().First(), r.List().Second(), r.Rlist().First().(*ir.UnaryExpr)
-                               }
-
-                               // If this is case x := <-ch or case x, y := <-ch, the case has
-                               // the ODCL nodes to declare x and y. We want to delay that
-                               // declaration (and possible allocation) until inside the case body.
-                               // Delete the ODCL nodes here and recreate them inside the body below.
-                               if def {
-                                       init := r.Init().Slice()
-                                       if len(init) > 0 && init[0].Op() == ir.ODCL && init[0].(*ir.Decl).Left() == dst {
-                                               init = init[1:]
-                                       }
-                                       if len(init) > 0 && init[0].Op() == ir.ODCL && init[0].(*ir.Decl).Left() == ok {
-                                               init = init[1:]
-                                       }
-                                       r.PtrInit().Set(init)
-                               }
-                               if r.Init().Len() != 0 {
-                                       ir.DumpList("ninit", r.Init())
-                                       base.Fatalf("ninit on select recv")
-                               }
-
+                       case ir.OSELRECV2:
+                               // case x, ok = <-c
+                               recv := r.Rlist().First().(*ir.UnaryExpr)
                                recv.SetLeft(o.expr(recv.Left(), nil))
                                if recv.Left().Op() != ir.ONAME {
                                        recv.SetLeft(o.copyExpr(recv.Left()))
                                }
-
-                               // Introduce temporary for receive and move actual copy into case body.
-                               // avoids problems with target being addressed, as usual.
-                               // NOTE: If we wanted to be clever, we could arrange for just one
-                               // temporary per distinct type, sharing the temp among all receives
-                               // with that temp. Similarly one ok bool could be shared among all
-                               // the x,ok receives. Not worth doing until there's a clear need.
-                               if !ir.IsBlank(dst) {
-                                       // use channel element type for temporary to avoid conversions,
-                                       // such as in case interfacevalue = <-intchan.
-                                       // the conversion happens in the OAS instead.
-                                       if def {
-                                               dcl := ir.Nod(ir.ODCL, dst, nil)
-                                               cas.PtrInit().Append(typecheck(dcl, ctxStmt))
+                               r := r.(*ir.AssignListStmt)
+                               init := r.PtrInit().Slice()
+                               r.PtrInit().Set(nil)
+
+                               colas := r.Colas()
+                               do := func(i int, t *types.Type) {
+                                       n := r.List().Index(i)
+                                       if ir.IsBlank(n) {
+                                               return
                                        }
-
-                                       tmp := o.newTemp(recv.Left().Type().Elem(), recv.Left().Type().Elem().HasPointers())
-                                       as := ir.Nod(ir.OAS, dst, tmp)
-                                       cas.PtrInit().Append(typecheck(as, ctxStmt))
-                                       dst = tmp
-                               }
-                               if !ir.IsBlank(ok) {
-                                       if def {
-                                               dcl := ir.Nod(ir.ODCL, ok, nil)
-                                               cas.PtrInit().Append(typecheck(dcl, ctxStmt))
+                                       // If this is case x := <-ch or case x, y := <-ch, the case has
+                                       // the ODCL nodes to declare x and y. We want to delay that
+                                       // declaration (and possible allocation) until inside the case body.
+                                       // Delete the ODCL nodes here and recreate them inside the body below.
+                                       if colas {
+                                               if len(init) > 0 && init[0].Op() == ir.ODCL && init[0].(*ir.Decl).Left() == n {
+                                                       init = init[1:]
+                                               }
+                                               dcl := ir.Nod(ir.ODCL, n, nil)
+                                               dcl = typecheck(dcl, ctxStmt)
+                                               ncas.PtrInit().Append(dcl)
                                        }
-
-                                       tmp := o.newTemp(types.Types[types.TBOOL], false)
-                                       as := ir.Nod(ir.OAS, ok, conv(tmp, ok.Type()))
-                                       cas.PtrInit().Append(typecheck(as, ctxStmt))
-                                       ok = tmp
+                                       tmp := o.newTemp(t, t.HasPointers())
+                                       as := ir.Nod(ir.OAS, n, conv(tmp, n.Type()))
+                                       as = typecheck(as, ctxStmt)
+                                       ncas.PtrInit().Append(as)
+                                       r.PtrList().SetIndex(i, tmp)
                                }
-
-                               if r.Op() == ir.OSELRECV {
-                                       r.SetLeft(dst)
-                               } else {
-                                       r := r.(*ir.AssignListStmt)
-                                       r.List().SetIndex(0, dst)
-                                       r.List().SetIndex(1, ok)
+                               do(0, recv.Left().Type().Elem())
+                               do(1, types.Types[types.TBOOL])
+                               if len(init) != 0 {
+                                       ir.DumpList("ninit", r.Init())
+                                       base.Fatalf("ninit on select recv")
                                }
-                               orderBlock(cas.PtrInit(), o.free)
+                               orderBlock(ncas.PtrInit(), o.free)
 
                        case ir.OSEND:
                                if r.Init().Len() != 0 {
index a3ce14128cb804b2ebf78925048d0357c2bdacbb..c017b8e29aa3198ee8a4e926e27cd0274fab09c3 100644 (file)
@@ -32,6 +32,14 @@ func typecheckselect(sel *ir.SelectStmt) {
                        n := ncase.List().First()
                        ncase.SetLeft(n)
                        ncase.PtrList().Set(nil)
+                       oselrecv2 := func(dst, recv ir.Node, colas bool) {
+                               n := ir.NodAt(n.Pos(), ir.OSELRECV2, nil, nil)
+                               n.PtrList().Set2(dst, ir.BlankNode)
+                               n.PtrRlist().Set1(recv)
+                               n.SetColas(colas)
+                               n.SetTypecheck(1)
+                               ncase.SetLeft(n)
+                       }
                        switch n.Op() {
                        default:
                                pos := n.Pos()
@@ -45,7 +53,7 @@ func typecheckselect(sel *ir.SelectStmt) {
                                base.ErrorfAt(pos, "select case must be receive, send or assign recv")
 
                        case ir.OAS:
-                               // convert x = <-c into OSELRECV(x, <-c).
+                               // convert x = <-c into x, _ = <-c
                                // remove implicit conversions; the eventual assignment
                                // will reintroduce them.
                                if r := n.Right(); r.Op() == ir.OCONVNOP || r.Op() == ir.OCONVIFACE {
@@ -57,10 +65,9 @@ func typecheckselect(sel *ir.SelectStmt) {
                                        base.ErrorfAt(n.Pos(), "select assignment must have receive on right hand side")
                                        break
                                }
-                               n.SetOp(ir.OSELRECV)
+                               oselrecv2(n.Left(), n.Right(), n.Colas())
 
                        case ir.OAS2RECV:
-                               // convert x, ok = <-c into OSELRECV2(x, <-c) with ntest=ok
                                if n.Rlist().First().Op() != ir.ORECV {
                                        base.ErrorfAt(n.Pos(), "select assignment must have receive on right hand side")
                                        break
@@ -68,12 +75,8 @@ func typecheckselect(sel *ir.SelectStmt) {
                                n.SetOp(ir.OSELRECV2)
 
                        case ir.ORECV:
-                               // convert <-c into OSELRECV(_, <-c)
-                               as := ir.NewAssignStmt(n.Pos(), ir.BlankNode, n)
-                               as.SetOp(ir.OSELRECV)
-                               as.SetTypecheck(1)
-                               n = as
-                               ncase.SetLeft(n)
+                               // convert <-c into _, _ = <-c
+                               oselrecv2(ir.BlankNode, n, false)
 
                        case ir.OSEND:
                                break
@@ -129,14 +132,6 @@ func walkselectcases(cases ir.Nodes) []ir.Node {
                        case ir.OSEND:
                                // already ok
 
-                       case ir.OSELRECV:
-                               r := n.(*ir.AssignStmt)
-                               if ir.IsBlank(r.Left()) {
-                                       n = r.Right()
-                                       break
-                               }
-                               r.SetOp(ir.OAS)
-
                        case ir.OSELRECV2:
                                r := n.(*ir.AssignListStmt)
                                if ir.IsBlank(r.List().First()) && ir.IsBlank(r.List().Second()) {
@@ -165,29 +160,11 @@ func walkselectcases(cases ir.Nodes) []ir.Node {
                        dflt = cas
                        continue
                }
-
-               // Lower x, _ = <-c to x = <-c.
-               if sel := n; sel.Op() == ir.OSELRECV2 {
-                       if ir.IsBlank(sel.List().Second()) {
-                               as := ir.NewAssignStmt(sel.Pos(), sel.List().First(), sel.Rlist().First())
-                               as.SetOp(ir.OSELRECV)
-                               as.SetTypecheck(1)
-                               n = as
-                               cas.SetLeft(n)
-                       }
-               }
-
                switch n.Op() {
                case ir.OSEND:
                        n.SetRight(nodAddr(n.Right()))
                        n.SetRight(typecheck(n.Right(), ctxExpr))
 
-               case ir.OSELRECV:
-                       if !ir.IsBlank(n.Left()) {
-                               n.SetLeft(nodAddr(n.Left()))
-                               n.SetLeft(typecheck(n.Left(), ctxExpr))
-                       }
-
                case ir.OSELRECV2:
                        if !ir.IsBlank(n.List().First()) {
                                n.List().SetIndex(0, nodAddr(n.List().First()))
@@ -217,26 +194,23 @@ func walkselectcases(cases ir.Nodes) []ir.Node {
                        ch := n.Left()
                        call = mkcall1(chanfn("selectnbsend", 2, ch.Type()), types.Types[types.TBOOL], r.PtrInit(), ch, n.Right())
 
-               case ir.OSELRECV:
-                       // if selectnbrecv(&v, c) { body } else { default body }
-                       recv := n.Right().(*ir.UnaryExpr)
-                       ch := recv.Left()
-                       elem := n.Left()
-                       if ir.IsBlank(elem) {
-                               elem = nodnil()
-                       }
-                       call = mkcall1(chanfn("selectnbrecv", 2, ch.Type()), types.Types[types.TBOOL], r.PtrInit(), elem, ch)
-
                case ir.OSELRECV2:
-                       // if selectnbrecv2(&v, &received, c) { body } else { default body }
                        recv := n.Rlist().First().(*ir.UnaryExpr)
                        ch := recv.Left()
                        elem := n.List().First()
                        if ir.IsBlank(elem) {
                                elem = nodnil()
                        }
-                       receivedp := typecheck(nodAddr(n.List().Second()), ctxExpr)
-                       call = mkcall1(chanfn("selectnbrecv2", 2, ch.Type()), types.Types[types.TBOOL], r.PtrInit(), elem, receivedp, ch)
+                       if ir.IsBlank(n.List().Second()) {
+                               // if selectnbrecv(&v, c) { body } else { default body }
+                               call = mkcall1(chanfn("selectnbrecv", 2, ch.Type()), types.Types[types.TBOOL], r.PtrInit(), elem, ch)
+                       } else {
+                               // TODO(cuonglm): make this use selectnbrecv()
+                               // if selectnbrecv2(&v, &received, c) { body } else { default body }
+                               receivedp := ir.Nod(ir.OADDR, n.List().Second(), nil)
+                               receivedp = typecheck(receivedp, ctxExpr)
+                               call = mkcall1(chanfn("selectnbrecv2", 2, ch.Type()), types.Types[types.TBOOL], r.PtrInit(), elem, receivedp, ch)
+                       }
                }
 
                r.SetLeft(typecheck(call, ctxExpr))
@@ -292,12 +266,6 @@ func walkselectcases(cases ir.Nodes) []ir.Node {
                        nsends++
                        c = n.Left()
                        elem = n.Right()
-               case ir.OSELRECV:
-                       nrecvs++
-                       i = ncas - nrecvs
-                       recv := n.Right().(*ir.UnaryExpr)
-                       c = recv.Left()
-                       elem = n.Left()
                case ir.OSELRECV2:
                        nrecvs++
                        i = ncas - nrecvs
@@ -355,7 +323,7 @@ func walkselectcases(cases ir.Nodes) []ir.Node {
 
                r := ir.Nod(ir.OIF, cond, nil)
 
-               if n := cas.Left(); n != nil && n.Op() == ir.OSELRECV2 {
+               if n := cas.Left(); n != nil && n.Op() == ir.OSELRECV2 && !ir.IsBlank(n.List().Second()) {
                        x := ir.Nod(ir.OAS, n.List().Second(), recvOK)
                        r.PtrBody().Append(typecheck(x, ctxStmt))
                }