]> Cypherpunks.ru repositories - gostls13.git/blobdiff - test/inline.go
cmd/compile/internal/inline: score call sites exposed by inlines
[gostls13.git] / test / inline.go
index bc23768d0161a87bd4f4ab398edda3c71362179b..fd14f25983355597230030735903f98b6a890268 100644 (file)
@@ -1,4 +1,6 @@
-// errorcheck -0 -m -d=inlfuncswithclosures=1
+// errorcheckwithauto -0 -m -d=inlfuncswithclosures=1
+
+//go:build !goexperiment.newinliner
 
 // Copyright 2015 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
@@ -10,6 +12,7 @@
 package foo
 
 import (
+       "errors"
        "runtime"
        "unsafe"
 )
@@ -49,12 +52,14 @@ func j(x int) int { // ERROR "can inline j"
        }
 }
 
-func _() int { // ERROR "can inline _"
+func f2() int { // ERROR "can inline f2"
        tmp1 := h
        tmp2 := tmp1
        return tmp2(0) // ERROR "inlining call to h"
 }
 
+var abc = errors.New("abc") // ERROR "inlining call to errors.New"
+
 var somethingWrong error
 
 // local closures can be inlined
@@ -112,11 +117,11 @@ func r(z int) int {
                return x + z
        }
        bar := func(x int) int { // ERROR "func literal does not escape" "can inline r.func2"
-               return x + func(y int) int { // ERROR "can inline r.func2.1" "can inline r.func3"
+               return x + func(y int) int { // ERROR "can inline r.func2.1" "can inline r.r.func2.func3"
                        return 2*y + x*z
                }(x) // ERROR "inlining call to r.func2.1"
        }
-       return foo(42) + bar(42) // ERROR "inlining call to r.func1" "inlining call to r.func2" "inlining call to r.func3"
+       return foo(42) + bar(42) // ERROR "inlining call to r.func1" "inlining call to r.func2" "inlining call to r.r.func2.func3"
 }
 
 func s0(x int) int { // ERROR "can inline s0"
@@ -135,8 +140,7 @@ func s1(x int) int { // ERROR "can inline s1"
        return foo() // ERROR "inlining call to s1.func1"
 }
 
-// can't currently inline functions with a break statement
-func switchBreak(x, y int) int {
+func switchBreak(x, y int) int { // ERROR "can inline switchBreak"
        var n int
        switch x {
        case 0:
@@ -161,14 +165,87 @@ func switchType(x interface{}) int { // ERROR "can inline switchType" "x does no
        }
 }
 
+// Test that switches on constant things, with constant cases, only cost anything for
+// the case that matches. See issue 50253.
+func switchConst1(p func(string)) { // ERROR "can inline switchConst" "p does not escape"
+       const c = 1
+       switch c {
+       case 0:
+               p("zero")
+       case 1:
+               p("one")
+       case 2:
+               p("two")
+       default:
+               p("other")
+       }
+}
+
+func switchConst2() string { // ERROR "can inline switchConst2"
+       switch runtime.GOOS {
+       case "linux":
+               return "Leenooks"
+       case "windows":
+               return "Windoze"
+       case "darwin":
+               return "MackBone"
+       case "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "100":
+               return "Numbers"
+       default:
+               return "oh nose!"
+       }
+}
+func switchConst3() string { // ERROR "can inline switchConst3"
+       switch runtime.GOOS {
+       case "Linux":
+               panic("Linux")
+       case "Windows":
+               panic("Windows")
+       case "Darwin":
+               panic("Darwin")
+       case "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "100":
+               panic("Numbers")
+       default:
+               return "oh nose!"
+       }
+}
+func switchConst4() { // ERROR "can inline switchConst4"
+       const intSize = 32 << (^uint(0) >> 63)
+       want := func() string { // ERROR "can inline switchConst4.func1"
+               switch intSize {
+               case 32:
+                       return "32"
+               case 64:
+                       return "64"
+               default:
+                       panic("unreachable")
+               }
+       }() // ERROR "inlining call to switchConst4.func1"
+       _ = want
+}
+
+func inlineRangeIntoMe(data []int) { // ERROR "can inline inlineRangeIntoMe" "data does not escape"
+       rangeFunc(data, 12) // ERROR "inlining call to rangeFunc"
+}
+
+func rangeFunc(xs []int, b int) int { // ERROR "can inline rangeFunc" "xs does not escape"
+       for i, x := range xs {
+               if x == b {
+                       return i
+               }
+       }
+       return -1
+}
+
 type T struct{}
 
 func (T) meth(int, int) {} // ERROR "can inline T.meth"
 
 func k() (T, int, int) { return T{}, 0, 0 } // ERROR "can inline k"
 
-func _() { // ERROR "can inline _"
+func f3() { // ERROR "can inline f3"
        T.meth(k()) // ERROR "inlining call to k" "inlining call to T.meth"
+       // ERRORAUTO "inlining call to T.meth"
 }
 
 func small1() { // ERROR "can inline small1"
@@ -197,13 +274,13 @@ func ff(x int) { // ERROR "can inline ff"
        if x < 0 {
                return
        }
-       gg(x - 1)
+       gg(x - 1) // ERROR "inlining call to gg" "inlining call to hh"
 }
 func gg(x int) { // ERROR "can inline gg"
-       hh(x - 1)
+       hh(x - 1) // ERROR "inlining call to hh" "inlining call to ff"
 }
 func hh(x int) { // ERROR "can inline hh"
-       ff(x - 1) // ERROR "inlining call to ff"  // ERROR "inlining call to gg"
+       ff(x - 1) // ERROR "inlining call to ff" "inlining call to gg"
 }
 
 // Issue #14768 - make sure we can inline for loops.
@@ -217,8 +294,7 @@ func for1(fn func() bool) { // ERROR "can inline for1" "fn does not escape"
        }
 }
 
-// BAD: for2 should be inlineable too.
-func for2(fn func() bool) { // ERROR "fn does not escape"
+func for2(fn func() bool) { // ERROR "can inline for2" "fn does not escape"
 Loop:
        for {
                if fn() {
@@ -232,12 +308,13 @@ Loop:
 // Issue #18493 - make sure we can do inlining of functions with a method value
 type T1 struct{}
 
-func (a T1) meth(val int) int { // ERROR "can inline T1.meth" "inlining call to T1.meth"
+func (a T1) meth(val int) int { // ERROR "can inline T1.meth"
        return val + 5
 }
 
 func getMeth(t1 T1) func(int) int { // ERROR "can inline getMeth"
        return t1.meth // ERROR "t1.meth escapes to heap"
+       // ERRORAUTO "inlining call to T1.meth"
 }
 
 func ii() { // ERROR "can inline ii"
@@ -290,3 +367,61 @@ func conv2(v uint64) uint64 { // ERROR "can inline conv2"
 func conv1(v uint64) uint64 { // ERROR "can inline conv1"
        return uint64(uint64(uint64(uint64(uint64(uint64(uint64(uint64(uint64(uint64(uint64(v)))))))))))
 }
+
+func select1(x, y chan bool) int { // ERROR "can inline select1" "x does not escape" "y does not escape"
+       select {
+       case <-x:
+               return 1
+       case <-y:
+               return 2
+       }
+}
+
+func select2(x, y chan bool) { // ERROR "can inline select2" "x does not escape" "y does not escape"
+loop: // test that labeled select can be inlined.
+       select {
+       case <-x:
+               break loop
+       case <-y:
+       }
+}
+
+func inlineSelect2(x, y chan bool) { // ERROR "can inline inlineSelect2" ERROR "x does not escape" "y does not escape"
+loop:
+       for i := 0; i < 5; i++ {
+               if i == 3 {
+                       break loop
+               }
+               select2(x, y) // ERROR "inlining call to select2"
+       }
+}
+
+// Issue #62211: inlining a function with unreachable "return"
+// statements could trip up phi insertion.
+func issue62211(x bool) { // ERROR "can inline issue62211"
+       if issue62211F(x) { // ERROR "inlining call to issue62211F"
+       }
+       if issue62211G(x) { // ERROR "inlining call to issue62211G"
+       }
+
+       // Initial fix CL caused a "non-monotonic scope positions" failure
+       // on code like this.
+       if z := 0; false {
+               panic(z)
+       }
+}
+
+func issue62211F(x bool) bool { // ERROR "can inline issue62211F"
+       if x || true {
+               return true
+       }
+       return true
+}
+
+func issue62211G(x bool) bool { // ERROR "can inline issue62211G"
+       if x || true {
+               return true
+       } else {
+               return true
+       }
+}