cmd/gc: eliminate dead code in switch statements

Ordinary switch statements are rewritten
into a sequence of if statements.
Staticly dead cases were not being eliminated
because the rewrite introduced a temporary,
which hid the fact that the case was a constant.
Stop doing that.

This eliminates dead code in the standard library at:

runtime/cgocall.go:219
runtime/cgocall.go:269
debug/gosym/pclntab.go:175
debug/macho/file.go:208
math/big/nat.go:635
math/big/nat.go:850
math/big/nat.go:1058
cmd/pprof/internal/commands/commands.go:86
net/sock_bsd.go:19
cmd/go/build.go:2657
cmd/go/env.go:90

Fixes #9608.

Change-Id: Ic23a05dfbb1ad91d5f62a6506b35a13e51b33e38
Reviewed-on: https://go-review.googlesource.com/3980
Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
Josh Bleecher Snyder 2015-02-05 15:38:53 -08:00
parent 82a761b656
commit 4ce06f4b5c
3 changed files with 94 additions and 4 deletions

View file

@ -503,7 +503,7 @@ exprbsw(Case *c0, int ncase, int arg)
/*
* normal (expression) switch.
* rebulid case statements into if .. goto
* rebuild case statements into if .. goto
*/
static void
exprswitch(Node *sw)
@ -533,12 +533,15 @@ exprswitch(Node *sw)
*/
exprname = N;
cas = nil;
if(arg != Strue && arg != Sfalse) {
if(arg == Strue || arg == Sfalse)
exprname = nodbool(arg == Strue);
else if(consttype(sw->ntest) >= 0)
// leave constants to enable dead code elimination (issue 9608)
exprname = sw->ntest;
else {
exprname = temp(sw->ntest->type);
cas = list1(nod(OAS, exprname, sw->ntest));
typechecklist(cas, Etop);
} else {
exprname = nodbool(arg == Strue);
}
c0 = mkcaselist(sw, arg);

View file

@ -0,0 +1,73 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
func fail() // unimplemented, to test dead code elimination
// Test dead code elimination in if statements
func init() {
if false {
fail()
}
if 0 == 1 {
fail()
}
}
// Test dead code elimination in ordinary switch statements
func init() {
const x = 0
switch x {
case 1:
fail()
}
switch 1 {
case x:
fail()
}
switch {
case false:
fail()
}
const a = "a"
switch a {
case "b":
fail()
}
const snowman = '☃'
switch snowman {
case '☀':
fail()
}
const zero = float64(0.0)
const one = float64(1.0)
switch one {
case -1.0:
fail()
case zero:
fail()
}
switch 1.0i {
case 1:
fail()
case -1i:
fail()
}
const no = false
switch no {
case true:
fail()
}
}
func main() {
}

View file

@ -0,0 +1,14 @@
// rundir
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Issue 9608: dead code elimination in switch statements.
// This has to be done as a package rather than as a file,
// because run.go runs files with 'go run', which passes the
// -complete flag to compiler, causing it to complain about
// the intentionally unimplemented function fail.
package ignored