]> Cypherpunks.ru repositories - gostls13.git/blobdiff - src/cmd/compile/internal/inline/inlheur/analyze_func_flags.go
cmd/compile/internal/inline: fix buglet in panic path scoring
[gostls13.git] / src / cmd / compile / internal / inline / inlheur / analyze_func_flags.go
index 15f5bd5f3574c4cb63850f40f19aebec79b2362d..588d2f4f598da746371bced9e863b11f1fb503e9 100644 (file)
@@ -40,8 +40,8 @@ func makeFuncFlagsAnalyzer(fn *ir.Func) *funcFlagsAnalyzer {
        }
 }
 
-// setResults transfers func flag results to 'fp'.
-func (ffa *funcFlagsAnalyzer) setResults(fp *FuncProps) {
+// setResults transfers func flag results to 'funcProps'.
+func (ffa *funcFlagsAnalyzer) setResults(funcProps *FuncProps) {
        var rv FuncPropBits
        if !ffa.noInfo && ffa.stateForList(ffa.fn.Body) == psCallsPanic {
                rv = FuncPropNeverReturns
@@ -63,7 +63,7 @@ func (ffa *funcFlagsAnalyzer) setResults(fp *FuncProps) {
        if isMainMain(ffa.fn) {
                rv &^= FuncPropNeverReturns
        }
-       fp.Flags = rv
+       funcProps.Flags = rv
 }
 
 func (ffa *funcFlagsAnalyzer) getstate(n ir.Node) pstate {
@@ -148,14 +148,28 @@ func branchCombine(p1, p2 pstate) pstate {
 // as updating disposition of intermediate nodes.
 func (ffa *funcFlagsAnalyzer) stateForList(list ir.Nodes) pstate {
        st := psTop
-       for i := range list {
+       // Walk the list backwards so that we can update the state for
+       // earlier list elements based on what we find out about their
+       // successors. Example:
+       //
+       //        if ... {
+       //  L10:    foo()
+       //  L11:    <stmt>
+       //  L12:    panic(...)
+       //        }
+       //
+       // After combining the dispositions for line 11 and 12, we want to
+       // update the state for the call at line 10 based on that combined
+       // disposition (if L11 has no path to "return", then the call at
+       // line 10 will be on a panic path).
+       for i := len(list) - 1; i >= 0; i-- {
                n := list[i]
                psi := ffa.getstate(n)
                if debugTrace&debugTraceFuncFlags != 0 {
                        fmt.Fprintf(os.Stderr, "=-= %v: stateForList n=%s ps=%s\n",
                                ir.Line(n), n.Op().String(), psi.String())
                }
-               st = blockCombine(st, psi)
+               st = blockCombine(psi, st)
                ffa.updatestate(n, st)
        }
        if st == psTop {
@@ -180,7 +194,7 @@ func isExitCall(n ir.Node) bool {
                return false
        }
        cx := n.(*ir.CallExpr)
-       name := ir.StaticCalleeName(cx.X)
+       name := ir.StaticCalleeName(cx.Fun)
        if name == nil {
                return false
        }
@@ -189,8 +203,8 @@ func isExitCall(n ir.Node) bool {
                isWellKnownFunc(s, "runtime", "throw") {
                return true
        }
-       if fp := propsForFunc(name.Func); fp != nil {
-               if fp.Flags&FuncPropNeverReturns != 0 {
+       if funcProps := propsForFunc(name.Func); funcProps != nil {
+               if funcProps.Flags&FuncPropNeverReturns != 0 {
                        return true
                }
        }
@@ -330,7 +344,7 @@ func (ffa *funcFlagsAnalyzer) nodeVisitPost(n ir.Node) {
        case ir.OFALL:
                // Not important.
        case ir.ODCLFUNC, ir.ORECOVER, ir.OAS, ir.OAS2, ir.OAS2FUNC, ir.OASOP,
-               ir.OPRINTN, ir.OPRINT, ir.OLABEL, ir.OCALLINTER, ir.ODEFER,
+               ir.OPRINTLN, ir.OPRINT, ir.OLABEL, ir.OCALLINTER, ir.ODEFER,
                ir.OSEND, ir.ORECV, ir.OSELRECV2, ir.OGO, ir.OAPPEND, ir.OAS2DOTTYPE,
                ir.OAS2MAPR, ir.OGETG, ir.ODELETE, ir.OINLMARK, ir.OAS2RECV,
                ir.OMIN, ir.OMAX, ir.OMAKE, ir.ORECOVERFP, ir.OGETCALLERSP: