// least weight 2. (Note: appends in loops have weight >= 2.)
appendWeight int
+ // Loop depth at declaration point.
+ // Use for heuristics only, it is not guaranteed to be correct
+ // in the presence of gotos.
+ declDepth int
+
// Whether we ever do cap(s), or other operations that use cap(s)
// (possibly implicitly), like s[i:j].
capUsed bool
i.s.Opt = nil
return
}
+ if loopDepth > i.declDepth {
+ // Conservatively, we disable this optimization when the
+ // transition is inside a loop. This can result in adding
+ // overhead unnecessarily in cases like:
+ // func f(n int, p *[]byte) {
+ // var s []byte
+ // for i := range n {
+ // *p = s
+ // s = append(s, 0)
+ // }
+ // }
+ i.s.Opt = nil
+ return
+ }
i.transition = loc
}
// s = append(s, ...) is ok
i.okUses += 2
i.appends = append(i.appends, y)
- i.appendWeight += 1 + loopDepth
+ i.appendWeight += 1 + (loopDepth - i.declDepth)
}
// TODO: s = append(nil, ...)?
}
n := n.(*ir.Decl)
if i := tracking(n.X); i != nil {
i.okUses++
+ i.declDepth = loopDepth
}
case ir.OINDEX:
n := n.(*ir.IndexExpr)
return r
}
+func Append18(n int, p *[]int) {
+ var r []int
+ for i := range n {
+ // amd64:-`.*moveSliceNoCapNoScan`
+ *p = r
+ // amd64:`.*growslice`
+ r = append(r, i)
+ }
+}
+
+func Append19(n int, p [][]int) {
+ for j := range p {
+ var r []int
+ for i := range n {
+ // amd64:`.*growslice`
+ r = append(r, i)
+ }
+ // amd64:`.*moveSliceNoCapNoScan`
+ p[j] = r
+ }
+}
+
+func Append20(n int, p [][]int) {
+ for j := range p {
+ var r []int
+ // amd64:`.*growslice`
+ r = append(r, 0)
+ // amd64:-`.*moveSliceNoCapNoScan`
+ p[j] = r
+ }
+}
+
//go:noinline
func useSlice(s []int) {
}