]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: propagate len([]T{}) to make builtin to allow stack allocation
authorMateusz Poliwczak <mpoliwczak34@gmail.com>
Fri, 26 Sep 2025 18:47:45 +0000 (20:47 +0200)
committerGopher Robot <gobot@golang.org>
Thu, 2 Oct 2025 18:02:07 +0000 (11:02 -0700)
Updates #75620

Change-Id: I6a6a6964af4512e30eb4806e1dc7b0fd0835744f
Reviewed-on: https://go-review.googlesource.com/c/go/+/707255
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Keith Randall <khr@golang.org>
Reviewed-by: Carlos Amedee <carlos@golang.org>
src/cmd/compile/internal/escape/escape.go
test/escape_make_non_const.go

index 6b34830b3dd5e6c8fa78327af4ec2a3bec083d98..59250edfef00783d89d1ded7fc974ae006674a58 100644 (file)
@@ -563,7 +563,10 @@ func (b *batch) rewriteWithLiterals(n ir.Node, fn *ir.Func) {
                        if ro == nil {
                                base.Fatalf("no ReassignOracle for function %v with closure parent %v", fn, fn.ClosureParent)
                        }
-                       if s := ro.StaticValue(*r); s.Op() == ir.OLITERAL {
+
+                       s := ro.StaticValue(*r)
+                       switch s.Op() {
+                       case ir.OLITERAL:
                                lit, ok := s.(*ir.BasicLit)
                                if !ok || lit.Val().Kind() != constant.Int {
                                        base.Fatalf("unexpected BasicLit Kind")
@@ -577,6 +580,14 @@ func (b *batch) rewriteWithLiterals(n ir.Node, fn *ir.Func) {
                                        assignTemp(n.Pos(), *r, n.PtrInit())
                                        *r = ir.NewBasicLit(n.Pos(), (*r).Type(), lit.Val())
                                }
+                       case ir.OLEN:
+                               x := ro.StaticValue(s.(*ir.UnaryExpr).X)
+                               if x.Op() == ir.OSLICELIT {
+                                       x := x.(*ir.CompLitExpr)
+                                       // Preserve any side effects of the original expression, then update the value.
+                                       assignTemp(n.Pos(), *r, n.PtrInit())
+                                       *r = ir.NewBasicLit(n.Pos(), types.Types[types.TINT], constant.MakeInt64(x.Len))
+                               }
                        }
                }
        case ir.OCONVIFACE:
index 7a9b28d5e37a7e6a517c445b58ab5fd882c0eeea..11854ac4f4731a18614cd391e86c7a7945bc0334 100644 (file)
@@ -106,3 +106,18 @@ type m struct {
 func newM(l int) m { // ERROR "can inline"
        return m{make(map[string]int, l)} // ERROR "make.*escapes to heap"
 }
+
+//go:noinline
+func testLenOfSliceLit() {
+       ints := []int{0, 1, 2, 3, 4, 5} // ERROR "\[\]int\{\.\.\.\} does not escape"'
+       _ = make([]int, len(ints))      // ERROR "make\(\[\]int, 6\) does not escape"
+       _ = allocLenOf(ints)            // ERROR "inlining call", "make\(\[\]int, 6\) does not escape"
+
+       _ = make([]int, 2, len(ints))  // ERROR "make\(\[\]int, 2, 6\) does not escape"
+       _ = make([]int, len(ints), 2)  // ERROR "make\(\[\]int, len\(ints\), 2\) does not escape"
+       _ = make([]int, 10, len(ints)) // ERROR "make\(\[\]int, 10, 6\) does not escape"
+}
+
+func allocLenOf(s []int) []int { // ERROR "can inline" "s does not escape"
+       return make([]int, len(s)) // ERROR "escapes to heap"
+}