]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/gc: eliminate dead code in switch statements
authorJosh Bleecher Snyder <josharian@gmail.com>
Thu, 5 Feb 2015 23:38:53 +0000 (15:38 -0800)
committerJosh Bleecher Snyder <josharian@gmail.com>
Fri, 6 Feb 2015 19:05:47 +0000 (19:05 +0000)
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>
src/cmd/gc/swt.c
test/fixedbugs/issue9608.dir/issue9608.go [new file with mode: 0644]
test/fixedbugs/issue9608.go [new file with mode: 0644]

index ca5455d4790143829be8bbdcd2a88ab82ae495b1..e75971d477214a568dd6f50e52ed55b475729bcc 100644 (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);
diff --git a/test/fixedbugs/issue9608.dir/issue9608.go b/test/fixedbugs/issue9608.dir/issue9608.go
new file mode 100644 (file)
index 0000000..56b52cc
--- /dev/null
@@ -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() {
+}
diff --git a/test/fixedbugs/issue9608.go b/test/fixedbugs/issue9608.go
new file mode 100644 (file)
index 0000000..92592d7
--- /dev/null
@@ -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