From: Josh Bleecher Snyder Date: Sun, 26 Feb 2017 23:25:57 +0000 (-0800) Subject: cmd/compile: ignore some dead code when deciding whether to inline X-Git-Tag: go1.9beta1~1421 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=566e72d0cedc593054dd36f9d3e91b588e849074;p=gostls13.git cmd/compile: ignore some dead code when deciding whether to inline Constant evaluation provides some rudimentary knowledge of dead code at inlining decision time. Use it. This CL addresses only dead code inside if statements. For statements are never inlined anyway, and dead code inside for statements is rare. Analyzing switch statements is worth doing, but it is more complicated, since we would have to evaluate each case; leave it for later. Fixes #9274 After this CL, the following functions in std+cmd can be newly inlined: cmd/internal/obj/x86/asm6.go:3122: can inline subreg cmd/vendor/golang.org/x/arch/x86/x86asm/decode.go:172: can inline instPrefix cmd/vendor/golang.org/x/arch/x86/x86asm/decode.go:202: can inline truncated go/constant/value.go:234: can inline makeFloat go/types/labels.go:52: can inline (*block).insert math/big/float.go:231: can inline (*Float).Sign math/bits/bits.go:57: can inline OnesCount net/http/server.go:597: can inline (*Server).newConn runtime/hashmap.go:1165: can inline reflect_maplen runtime/proc.go:207: can inline os_beforeExit runtime/signal_unix.go:55: can inline init.5 runtime/stack.go:1081: can inline gostartcallfn Change-Id: I4c92fb96aa0c3d33df7b3f2da548612e79b56b5b Reviewed-on: https://go-review.googlesource.com/37499 Reviewed-by: Matthew Dempsky --- diff --git a/src/cmd/compile/internal/gc/const.go b/src/cmd/compile/internal/gc/const.go index 48b98b798a..948d46d01f 100644 --- a/src/cmd/compile/internal/gc/const.go +++ b/src/cmd/compile/internal/gc/const.go @@ -115,11 +115,20 @@ type NilVal struct{} // n must be an integer or rune constant. func (n *Node) Int64() int64 { if !Isconst(n, CTINT) { - Fatalf("Int(%v)", n) + Fatalf("Int64(%v)", n) } return n.Val().U.(*Mpint).Int64() } +// Bool returns n as a bool. +// n must be a boolean constant. +func (n *Node) Bool() bool { + if !Isconst(n, CTBOOL) { + Fatalf("Bool(%v)", n) + } + return n.Val().U.(bool) +} + // truncate float literal fv to 32-bit or 64-bit precision // according to type; return truncated value. func truncfltlit(oldv *Mpflt, t *Type) *Mpflt { diff --git a/src/cmd/compile/internal/gc/inl.go b/src/cmd/compile/internal/gc/inl.go index 04e24c1ef2..a1fd20d637 100644 --- a/src/cmd/compile/internal/gc/inl.go +++ b/src/cmd/compile/internal/gc/inl.go @@ -277,6 +277,16 @@ func ishairy(n *Node, budget *int32, reason *string) bool { return true } + if n.Op == OIF && Isconst(n.Left, CTBOOL) { + var taken Nodes // statements for the branch that is always taken + if n.Left.Bool() { + taken = n.Nbody // then case + } else { + taken = n.Rlist // else case + } + return ishairylist(n.Ninit, budget, reason) || ishairylist(taken, budget, reason) + } + return ishairy(n.Left, budget, reason) || ishairy(n.Right, budget, reason) || ishairylist(n.List, budget, reason) || ishairylist(n.Rlist, budget, reason) || ishairylist(n.Ninit, budget, reason) || ishairylist(n.Nbody, budget, reason)