Skip to content

Commit

Permalink
cmd/gc: eliminate dead code in switch statements
Browse files Browse the repository at this point in the history
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 golang#9608.

Change-Id: Ic23a05dfbb1ad91d5f62a6506b35a13e51b33e38
Reviewed-on: https://go-review.googlesource.com/3980
Reviewed-by: Keith Randall <[email protected]>
  • Loading branch information
josharian committed Feb 6, 2015
1 parent 82a761b commit 4ce06f4
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 4 deletions.
11 changes: 7 additions & 4 deletions src/cmd/gc/swt.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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);
Expand Down
73 changes: 73 additions & 0 deletions test/fixedbugs/issue9608.dir/issue9608.go
Original file line number Diff line number Diff line change
@@ -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() {
}
14 changes: 14 additions & 0 deletions test/fixedbugs/issue9608.go
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 4ce06f4

Please sign in to comment.