cmd/compile: call fninit earlier

This allows the global initializers function to go through normal
mid-end optimizations (e.g., inlining, escape analysis) like any other
function.

Updates #33485.

Change-Id: I9bcfe98b8628d1aca09b4c238d8d3b74c69010a5
Reviewed-on: https://go-review.googlesource.com/c/go/+/254839
Reviewed-by: Keith Randall <khr@golang.org>
Trust: Matthew Dempsky <mdempsky@google.com>
diff --git a/src/cmd/compile/internal/gc/init.go b/src/cmd/compile/internal/gc/init.go
index 94cbcf9..ec9cc4b 100644
--- a/src/cmd/compile/internal/gc/init.go
+++ b/src/cmd/compile/internal/gc/init.go
@@ -59,7 +59,7 @@
 		Curfn = fn
 		typecheckslice(nf, ctxStmt)
 		Curfn = nil
-		funccompile(fn)
+		xtop = append(xtop, fn)
 		fns = append(fns, initializers.Linksym())
 	}
 	if dummyInitFn.Func.Dcl != nil {
@@ -68,16 +68,14 @@
 		// something's weird if we get here.
 		Fatalf("dummyInitFn still has declarations")
 	}
+	dummyInitFn = nil
 
 	// Record user init functions.
 	for i := 0; i < renameinitgen; i++ {
 		s := lookupN("init.", i)
 		fn := asNode(s.Def).Name.Defn
 		// Skip init functions with empty bodies.
-		// noder.go doesn't allow external init functions, and
-		// order.go has already removed any OEMPTY nodes, so
-		// checking Len() == 0 is sufficient here.
-		if fn.Nbody.Len() == 0 {
+		if fn.Nbody.Len() == 1 && fn.Nbody.First().Op == OEMPTY {
 			continue
 		}
 		fns = append(fns, s.Linksym())
diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go
index 9bce6cf..8783cb4 100644
--- a/src/cmd/compile/internal/gc/main.go
+++ b/src/cmd/compile/internal/gc/main.go
@@ -642,6 +642,8 @@
 		errorexit()
 	}
 
+	fninit(xtop)
+
 	// Phase 4: Decide how to capture closed variables.
 	// This needs to run before escape analysis,
 	// because variables captured by value do not escape.
@@ -751,10 +753,6 @@
 	}
 	timings.AddEvent(fcount, "funcs")
 
-	if nsavederrors+nerrors == 0 {
-		fninit(xtop)
-	}
-
 	compileFunctions()
 
 	if nowritebarrierrecCheck != nil {
diff --git a/test/inline.go b/test/inline.go
index 0b3ad55..1c5c1bc 100644
--- a/test/inline.go
+++ b/test/inline.go
@@ -50,7 +50,7 @@
 	}
 }
 
-var somethingWrong error = errors.New("something went wrong")
+var somethingWrong error = errors.New("something went wrong") // ERROR "can inline init" "inlining call to errors.New" "errors.errorString.* escapes to heap"
 
 // local closures can be inlined
 func l(x, y int) (int, int, error) {