diff --git a/src/cmd/compile/internal/gc/inl.go b/src/cmd/compile/internal/gc/inl.go index c8296971cd..e2456eb96f 100644 --- a/src/cmd/compile/internal/gc/inl.go +++ b/src/cmd/compile/internal/gc/inl.go @@ -344,6 +344,12 @@ func (v *hairyVisitor) visit(n *Node) bool { case ODCLCONST, OEMPTY, OFALL, OLABEL: // These nodes don't produce code; omit from inlining budget. return false + + case OIF: + if Isconst(n.Left, CTBOOL) { + // This if and the condition cost nothing. + return v.visitList(n.Nbody) || v.visitList(n.Rlist) + } } v.budget-- diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go index 7f1a702b35..75ecaa3d41 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -3919,11 +3919,14 @@ func deadcodeslice(nn Nodes) { if n == nil { continue } - if n.Op == OIF && Isconst(n.Left, CTBOOL) { - if n.Left.Bool() { - n.Rlist = Nodes{} - } else { - n.Nbody = Nodes{} + if n.Op == OIF { + n.Left = deadcodeexpr(n.Left) + if Isconst(n.Left, CTBOOL) { + if n.Left.Bool() { + n.Rlist = Nodes{} + } else { + n.Nbody = Nodes{} + } } } deadcodeslice(n.Ninit) @@ -3932,3 +3935,32 @@ func deadcodeslice(nn Nodes) { deadcodeslice(n.Rlist) } } + +func deadcodeexpr(n *Node) *Node { + // Perform dead-code elimination on short-circuited boolean + // expressions involving constants with the intent of + // producing a constant 'if' condition. + switch n.Op { + case OANDAND: + n.Left = deadcodeexpr(n.Left) + n.Right = deadcodeexpr(n.Right) + if Isconst(n.Left, CTBOOL) { + if n.Left.Bool() { + return n.Right // true && x => x + } else { + return n.Left // false && x => false + } + } + case OOROR: + n.Left = deadcodeexpr(n.Left) + n.Right = deadcodeexpr(n.Right) + if Isconst(n.Left, CTBOOL) { + if n.Left.Bool() { + return n.Left // true || x => true + } else { + return n.Right // false || x => x + } + } + } + return n +}