From 566e72d0cedc593054dd36f9d3e91b588e849074 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Sun, 26 Feb 2017 15:25:57 -0800 Subject: [PATCH] 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 --- src/cmd/compile/internal/gc/const.go | 11 ++++++++++- src/cmd/compile/internal/gc/inl.go | 10 ++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) 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) -- 2.50.0