]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/gc: avoid duplicate allocation during inlining
authorRuss Cox <rsc@golang.org>
Sun, 3 Feb 2013 04:17:25 +0000 (23:17 -0500)
committerRuss Cox <rsc@golang.org>
Sun, 3 Feb 2013 04:17:25 +0000 (23:17 -0500)
Fixes #4667.

R=ken2
CC=golang-dev
https://golang.org/cl/7275046

src/cmd/gc/gen.c
src/cmd/gc/inl.c
test/fixedbugs/issue4667.go [new file with mode: 0644]

index 8b2120253ee0042eba9502da137001c5a51108f3..8114448a105248a26ecf443cc76b87bf3c803e34 100644 (file)
@@ -266,6 +266,8 @@ gen(Node *n)
        Label *lab;
        int32 wasregalloc;
 
+//dump("gen", n);
+
        lno = setlineno(n);
        wasregalloc = anyregalloc();
 
index 2a61b9fecc8f02d5cac3b09ab23cf2a8e438705d..7b2a5ca6496e60284abd54c48be76d947d92d018 100644 (file)
@@ -553,6 +553,8 @@ mkinlcall1(Node **np, Node *fn, int isddd)
 
        ninit = n->ninit;
 
+//dumplist("ninit pre", ninit);
+
        if (fn->defn) // local function
                dcl = fn->defn->dcl;
        else // imported function
@@ -566,7 +568,8 @@ mkinlcall1(Node **np, Node *fn, int isddd)
                        ll->n->inlvar = inlvar(ll->n);
                        // Typecheck because inlvar is not necessarily a function parameter.
                        typecheck(&ll->n->inlvar, Erv);
-                       ninit = list(ninit, nod(ODCL, ll->n->inlvar, N));  // otherwise gen won't emit the allocations for heapallocs
+                       if ((ll->n->class&~PHEAP) != PAUTO)
+                               ninit = list(ninit, nod(ODCL, ll->n->inlvar, N));  // otherwise gen won't emit the allocations for heapallocs
                        if (ll->n->class == PPARAMOUT)  // we rely on the order being correct here
                                inlretvars = list(inlretvars, ll->n->inlvar);
                }
@@ -733,6 +736,7 @@ mkinlcall1(Node **np, Node *fn, int isddd)
        body = list(body, nod(OLABEL, inlretlabel, N));
 
        typechecklist(body, Etop);
+//dumplist("ninit post", ninit);
 
        call = nod(OINLCALL, N, N);
        call->ninit = ninit;
@@ -742,6 +746,7 @@ mkinlcall1(Node **np, Node *fn, int isddd)
        call->typecheck = 1;
 
        setlno(call, n->lineno);
+//dumplist("call body", body);
 
        *np = call;
 
diff --git a/test/fixedbugs/issue4667.go b/test/fixedbugs/issue4667.go
new file mode 100644 (file)
index 0000000..3a00a31
--- /dev/null
@@ -0,0 +1,37 @@
+// run
+
+// Copyright 2013 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
+
+import (
+       "fmt"
+       "os"
+       "testing"
+)
+
+var globl *int
+
+func G() {
+       F()
+}
+
+func F() {
+       var x int
+       globl = &x
+}
+
+func main() {
+       nf := testing.AllocsPerRun(100, F)
+       ng := testing.AllocsPerRun(100, G)
+       if int(nf) != 1 {
+               fmt.Printf("AllocsPerRun(100, F) = %v, want 1\n", nf)
+               os.Exit(1)
+       }
+       if int(ng) != 1 {
+               fmt.Printf("AllocsPerRun(100, G) = %v, want 1\n", ng)
+               os.Exit(1)
+       }
+}