From: Josh Bleecher Snyder Date: Wed, 1 Jun 2016 22:21:56 +0000 (-0700) Subject: cmd/compile: eliminate switch case kinds X-Git-Tag: go1.8beta1~1707 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=b046786528d6c802ae007f001a60341fd0d9c9d4;p=gostls13.git cmd/compile: eliminate switch case kinds We used to have separate kinds for the default case and the nil type case. Now that those are gone, we can use a simple bool instead. Change-Id: I65488e945df68178e893cddd2e091ebb6e32ef4d Reviewed-on: https://go-review.googlesource.com/26763 Run-TryBot: Josh Bleecher Snyder Reviewed-by: Matthew Dempsky --- diff --git a/src/cmd/compile/internal/gc/swt.go b/src/cmd/compile/internal/gc/swt.go index 3662758bd4..cf26475f7c 100644 --- a/src/cmd/compile/internal/gc/swt.go +++ b/src/cmd/compile/internal/gc/swt.go @@ -16,16 +16,6 @@ const ( switchKindType // switch a.(type) {...} ) -const ( - // expression switch - caseKindExprConst = iota // case 5: - caseKindExprVar // case x: - - // type switch - caseKindTypeConst // case time.Time: (concrete type, has type hash) - caseKindTypeVar // case io.Reader: (interface type) -) - const binarySearchMin = 4 // minimum number of cases for binary search // An exprSwitch walks an expression switch. @@ -46,7 +36,11 @@ type caseClause struct { node *Node // points at case statement ordinal int // position in switch hash uint32 // hash of a type switch - typ uint8 // type of case + // isconst indicates whether this case clause is a constant, + // for the purposes of the switch code generation. + // For expression switches, that's generally literals (case 5:, not case x:). + // For type switches, that's concrete types (case time.Time:), not interfaces (case io.Reader:). + isconst bool } // caseClauses are all the case clauses in a switch statement. @@ -260,7 +254,7 @@ func (s *exprSwitch) walk(sw *Node) { // handle the cases in order for len(cc) > 0 { // deal with expressions one at a time - if !okforcmp[t.Etype] || cc[0].typ != caseKindExprConst { + if !okforcmp[t.Etype] || !cc[0].isconst { a := s.walkCases(cc[:1]) cas = append(cas, a) cc = cc[1:] @@ -269,7 +263,7 @@ func (s *exprSwitch) walk(sw *Node) { // do binary search on runs of constants var run int - for run = 1; run < len(cc) && cc[run].typ == caseKindExprConst; run++ { + for run = 1; run < len(cc) && cc[run].isconst; run++ { } // sort and compile constants @@ -448,20 +442,13 @@ func genCaseClauses(sw *Node, kind int) caseClauses { c := caseClause{node: n, ordinal: len(cc.list)} if kind == switchKindType { // type switch - switch { - case n.Left.Type.IsInterface(): - c.typ = caseKindTypeVar - default: - c.typ = caseKindTypeConst - } + c.isconst = !n.Left.Type.IsInterface() c.hash = typehash(n.Left.Type) } else { // expression switch switch consttype(n.Left) { case CTFLT, CTINT, CTRUNE, CTSTR: - c.typ = caseKindExprConst - default: - c.typ = caseKindExprVar + c.isconst = true } } cc.list = append(cc.list, c) @@ -619,18 +606,12 @@ func (s *typeSwitch) walk(sw *Node) { // insert type equality check into each case block for _, c := range cc { - n := c.node - switch c.typ { - case caseKindTypeVar, caseKindTypeConst: - n.Right = s.typeone(n) - default: - Fatalf("typeSwitch with bad kind: %d", c.typ) - } + c.node.Right = s.typeone(c.node) } // generate list of if statements, binary search for constant sequences for len(cc) > 0 { - if cc[0].typ != caseKindTypeConst { + if !cc[0].isconst { n := cc[0].node cas = append(cas, n.Right) cc = cc[1:] @@ -639,7 +620,7 @@ func (s *typeSwitch) walk(sw *Node) { // identify run of constants var run int - for run = 1; run < len(cc) && cc[run].typ == caseKindTypeConst; run++ { + for run = 1; run < len(cc) && cc[run].isconst; run++ { } // sort by hash @@ -716,7 +697,7 @@ func (s *typeSwitch) walkCases(cc []caseClause) *Node { var cas []*Node for _, c := range cc { n := c.node - if c.typ != caseKindTypeConst { + if !c.isconst { Fatalf("typeSwitch walkCases") } a := Nod(OIF, nil, nil) @@ -754,10 +735,10 @@ func (x caseClauseByExpr) Less(i, j int) bool { func exprcmp(c1, c2 caseClause) int { // sort non-constants last - if c1.typ != caseKindExprConst { + if !c1.isconst { return +1 } - if c2.typ != caseKindExprConst { + if !c2.isconst { return -1 } diff --git a/src/cmd/compile/internal/gc/swt_test.go b/src/cmd/compile/internal/gc/swt_test.go index 4e5dbcae50..332433d31d 100644 --- a/src/cmd/compile/internal/gc/swt_test.go +++ b/src/cmd/compile/internal/gc/swt_test.go @@ -16,120 +16,120 @@ func TestExprcmp(t *testing.T) { }{ // Non-constants. { - caseClause{node: Nod(OXXX, nil, nil), typ: caseKindExprVar}, - caseClause{node: Nod(OXXX, nil, nil), typ: caseKindExprConst}, + caseClause{node: Nod(OXXX, nil, nil)}, + caseClause{node: Nod(OXXX, nil, nil), isconst: true}, +1, }, { - caseClause{node: Nod(OXXX, nil, nil), typ: caseKindExprConst}, - caseClause{node: Nod(OXXX, nil, nil), typ: caseKindExprVar}, + caseClause{node: Nod(OXXX, nil, nil), isconst: true}, + caseClause{node: Nod(OXXX, nil, nil)}, -1, }, // Type switches { - caseClause{node: Nod(OXXX, Nodintconst(0), nil), typ: caseKindExprConst}, - caseClause{node: Nod(OXXX, Nodbool(true), nil), typ: caseKindExprConst}, + caseClause{node: Nod(OXXX, Nodintconst(0), nil), isconst: true}, + caseClause{node: Nod(OXXX, Nodbool(true), nil), isconst: true}, -1, }, { - caseClause{node: Nod(OXXX, Nodbool(true), nil), typ: caseKindExprConst}, - caseClause{node: Nod(OXXX, Nodintconst(1), nil), typ: caseKindExprConst}, + caseClause{node: Nod(OXXX, Nodbool(true), nil), isconst: true}, + caseClause{node: Nod(OXXX, Nodintconst(1), nil), isconst: true}, +1, }, { - caseClause{node: Nod(OXXX, &Node{Type: &Type{Etype: TBOOL, Vargen: 1}}, nil), typ: caseKindExprConst}, - caseClause{node: Nod(OXXX, &Node{Type: &Type{Etype: TINT, Vargen: 0}}, nil), typ: caseKindExprConst}, + caseClause{node: Nod(OXXX, &Node{Type: &Type{Etype: TBOOL, Vargen: 1}}, nil), isconst: true}, + caseClause{node: Nod(OXXX, &Node{Type: &Type{Etype: TINT, Vargen: 0}}, nil), isconst: true}, +1, }, { - caseClause{node: Nod(OXXX, &Node{Type: &Type{Etype: TBOOL, Vargen: 1}}, nil), typ: caseKindExprConst}, - caseClause{node: Nod(OXXX, &Node{Type: &Type{Etype: TINT, Vargen: 1}}, nil), typ: caseKindExprConst}, + caseClause{node: Nod(OXXX, &Node{Type: &Type{Etype: TBOOL, Vargen: 1}}, nil), isconst: true}, + caseClause{node: Nod(OXXX, &Node{Type: &Type{Etype: TINT, Vargen: 1}}, nil), isconst: true}, -1, }, { - caseClause{node: Nod(OXXX, &Node{Type: &Type{Etype: TBOOL, Vargen: 0}}, nil), typ: caseKindExprConst}, - caseClause{node: Nod(OXXX, &Node{Type: &Type{Etype: TINT, Vargen: 1}}, nil), typ: caseKindExprConst}, + caseClause{node: Nod(OXXX, &Node{Type: &Type{Etype: TBOOL, Vargen: 0}}, nil), isconst: true}, + caseClause{node: Nod(OXXX, &Node{Type: &Type{Etype: TINT, Vargen: 1}}, nil), isconst: true}, -1, }, // Constant values. // CTFLT { - caseClause{node: Nod(OXXX, nodlit(Val{&Mpflt{Val: *big.NewFloat(0.1)}}), nil), typ: caseKindExprConst}, - caseClause{node: Nod(OXXX, nodlit(Val{&Mpflt{Val: *big.NewFloat(0.2)}}), nil), typ: caseKindExprConst}, + caseClause{node: Nod(OXXX, nodlit(Val{&Mpflt{Val: *big.NewFloat(0.1)}}), nil), isconst: true}, + caseClause{node: Nod(OXXX, nodlit(Val{&Mpflt{Val: *big.NewFloat(0.2)}}), nil), isconst: true}, -1, }, { - caseClause{node: Nod(OXXX, nodlit(Val{&Mpflt{Val: *big.NewFloat(0.1)}}), nil), typ: caseKindExprConst}, - caseClause{node: Nod(OXXX, nodlit(Val{&Mpflt{Val: *big.NewFloat(0.1)}}), nil), typ: caseKindExprConst}, + caseClause{node: Nod(OXXX, nodlit(Val{&Mpflt{Val: *big.NewFloat(0.1)}}), nil), isconst: true}, + caseClause{node: Nod(OXXX, nodlit(Val{&Mpflt{Val: *big.NewFloat(0.1)}}), nil), isconst: true}, 0, }, { - caseClause{node: Nod(OXXX, nodlit(Val{&Mpflt{Val: *big.NewFloat(0.2)}}), nil), typ: caseKindExprConst}, - caseClause{node: Nod(OXXX, nodlit(Val{&Mpflt{Val: *big.NewFloat(0.1)}}), nil), typ: caseKindExprConst}, + caseClause{node: Nod(OXXX, nodlit(Val{&Mpflt{Val: *big.NewFloat(0.2)}}), nil), isconst: true}, + caseClause{node: Nod(OXXX, nodlit(Val{&Mpflt{Val: *big.NewFloat(0.1)}}), nil), isconst: true}, +1, }, // CTINT { - caseClause{node: Nod(OXXX, Nodintconst(0), nil), typ: caseKindExprConst}, - caseClause{node: Nod(OXXX, Nodintconst(1), nil), typ: caseKindExprConst}, + caseClause{node: Nod(OXXX, Nodintconst(0), nil), isconst: true}, + caseClause{node: Nod(OXXX, Nodintconst(1), nil), isconst: true}, -1, }, { - caseClause{node: Nod(OXXX, Nodintconst(1), nil), typ: caseKindExprConst}, - caseClause{node: Nod(OXXX, Nodintconst(1), nil), typ: caseKindExprConst}, + caseClause{node: Nod(OXXX, Nodintconst(1), nil), isconst: true}, + caseClause{node: Nod(OXXX, Nodintconst(1), nil), isconst: true}, 0, }, { - caseClause{node: Nod(OXXX, Nodintconst(1), nil), typ: caseKindExprConst}, - caseClause{node: Nod(OXXX, Nodintconst(0), nil), typ: caseKindExprConst}, + caseClause{node: Nod(OXXX, Nodintconst(1), nil), isconst: true}, + caseClause{node: Nod(OXXX, Nodintconst(0), nil), isconst: true}, +1, }, // CTRUNE { - caseClause{node: Nod(OXXX, nodlit(Val{&Mpint{Val: *big.NewInt('a'), Rune: true}}), nil), typ: caseKindExprConst}, - caseClause{node: Nod(OXXX, nodlit(Val{&Mpint{Val: *big.NewInt('b'), Rune: true}}), nil), typ: caseKindExprConst}, + caseClause{node: Nod(OXXX, nodlit(Val{&Mpint{Val: *big.NewInt('a'), Rune: true}}), nil), isconst: true}, + caseClause{node: Nod(OXXX, nodlit(Val{&Mpint{Val: *big.NewInt('b'), Rune: true}}), nil), isconst: true}, -1, }, { - caseClause{node: Nod(OXXX, nodlit(Val{&Mpint{Val: *big.NewInt('b'), Rune: true}}), nil), typ: caseKindExprConst}, - caseClause{node: Nod(OXXX, nodlit(Val{&Mpint{Val: *big.NewInt('b'), Rune: true}}), nil), typ: caseKindExprConst}, + caseClause{node: Nod(OXXX, nodlit(Val{&Mpint{Val: *big.NewInt('b'), Rune: true}}), nil), isconst: true}, + caseClause{node: Nod(OXXX, nodlit(Val{&Mpint{Val: *big.NewInt('b'), Rune: true}}), nil), isconst: true}, 0, }, { - caseClause{node: Nod(OXXX, nodlit(Val{&Mpint{Val: *big.NewInt('b'), Rune: true}}), nil), typ: caseKindExprConst}, - caseClause{node: Nod(OXXX, nodlit(Val{&Mpint{Val: *big.NewInt('a'), Rune: true}}), nil), typ: caseKindExprConst}, + caseClause{node: Nod(OXXX, nodlit(Val{&Mpint{Val: *big.NewInt('b'), Rune: true}}), nil), isconst: true}, + caseClause{node: Nod(OXXX, nodlit(Val{&Mpint{Val: *big.NewInt('a'), Rune: true}}), nil), isconst: true}, +1, }, // CTSTR { - caseClause{node: Nod(OXXX, nodlit(Val{"ab"}), nil), typ: caseKindExprConst}, - caseClause{node: Nod(OXXX, nodlit(Val{"abc"}), nil), typ: caseKindExprConst}, + caseClause{node: Nod(OXXX, nodlit(Val{"ab"}), nil), isconst: true}, + caseClause{node: Nod(OXXX, nodlit(Val{"abc"}), nil), isconst: true}, -1, }, { - caseClause{node: Nod(OXXX, nodlit(Val{"abc"}), nil), typ: caseKindExprConst}, - caseClause{node: Nod(OXXX, nodlit(Val{"xyz"}), nil), typ: caseKindExprConst}, + caseClause{node: Nod(OXXX, nodlit(Val{"abc"}), nil), isconst: true}, + caseClause{node: Nod(OXXX, nodlit(Val{"xyz"}), nil), isconst: true}, -1, }, { - caseClause{node: Nod(OXXX, nodlit(Val{"abc"}), nil), typ: caseKindExprConst}, - caseClause{node: Nod(OXXX, nodlit(Val{"abc"}), nil), typ: caseKindExprConst}, + caseClause{node: Nod(OXXX, nodlit(Val{"abc"}), nil), isconst: true}, + caseClause{node: Nod(OXXX, nodlit(Val{"abc"}), nil), isconst: true}, 0, }, { - caseClause{node: Nod(OXXX, nodlit(Val{"abc"}), nil), typ: caseKindExprConst}, - caseClause{node: Nod(OXXX, nodlit(Val{"ab"}), nil), typ: caseKindExprConst}, + caseClause{node: Nod(OXXX, nodlit(Val{"abc"}), nil), isconst: true}, + caseClause{node: Nod(OXXX, nodlit(Val{"ab"}), nil), isconst: true}, +1, }, { - caseClause{node: Nod(OXXX, nodlit(Val{"xyz"}), nil), typ: caseKindExprConst}, - caseClause{node: Nod(OXXX, nodlit(Val{"abc"}), nil), typ: caseKindExprConst}, + caseClause{node: Nod(OXXX, nodlit(Val{"xyz"}), nil), isconst: true}, + caseClause{node: Nod(OXXX, nodlit(Val{"abc"}), nil), isconst: true}, +1, }, // Everything else should compare equal. { - caseClause{node: Nod(OXXX, nodnil(), nil), typ: caseKindExprConst}, - caseClause{node: Nod(OXXX, nodnil(), nil), typ: caseKindExprConst}, + caseClause{node: Nod(OXXX, nodnil(), nil), isconst: true}, + caseClause{node: Nod(OXXX, nodnil(), nil), isconst: true}, 0, }, } @@ -137,8 +137,8 @@ func TestExprcmp(t *testing.T) { got := exprcmp(d.a, d.b) if d.want != got { t.Errorf("%d: exprcmp(a, b) = %d; want %d", i, got, d.want) - t.Logf("\ta = caseClause{node: %#v, typ: %#v}", d.a.node, d.a.typ) - t.Logf("\tb = caseClause{node: %#v, typ: %#v}", d.b.node, d.b.typ) + t.Logf("\ta = caseClause{node: %#v, isconst: %v}", d.a.node, d.a.isconst) + t.Logf("\tb = caseClause{node: %#v, isconst: %v}", d.b.node, d.b.isconst) } } }