// A constant bound allows this to be stack-allocated. 64 is
// enough to cover almost every storeOrder call.
stores := make([]*Value, 0, 64)
+ var vardefs map[interface{}]*Value // OpAddr must depend on Vardef for Node
hasNilCheck := false
sset.clear() // sset is the set of stores that are used in other values
for _, v := range values {
if v.Op == OpNilCheck {
hasNilCheck = true
}
+ if v.Op == OpVarDef {
+ if vardefs == nil { // Lazy init, not all blocks have vardefs
+ vardefs = make(map[interface{}]*Value)
+ }
+ vardefs[v.Aux] = v
+ }
}
if len(stores) == 0 || !hasNilCheck && f.pass.name == "nilcheckelim" {
// there is no store, the order does not matter
stack = stack[:len(stack)-1]
continue
}
-
+ if w.Op == OpAddr {
+ // OpAddr depends only on relevant VarDef
+ vn := int32(0)
+ if vardefs != nil {
+ if a := vardefs[w.Aux]; a != nil { // if nil, it is in some other block, or global or arg
+ vn = storeNumber[a.ID]
+ }
+ }
+ vn += 2
+ storeNumber[w.ID] = vn
+ count[vn]++
+ stack = stack[:len(stack)-1]
+ continue
+ }
max := int32(0) // latest store dependency
argsdone := true
for _, a := range w.Args {
--- /dev/null
+// compile
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Triggers a bug in writebarrier, which inserts one
+// between (first block) OpAddr x and (second block) a VarDef x,
+// which are then in the wrong order and unable to be
+// properly scheduled.
+
+package q
+
+var S interface{}
+
+func F(n int) {
+ fun := func(x int) int {
+ S = 1
+ return n
+ }
+ i := fun(([]int{})[n])
+
+ var fc [2]chan int
+ S = (([1][2]chan int{fc})[i][i])
+}