| package main |
| |
| // This is a regression test for a bug (#69929) in |
| // the SSA interpreter in which it would not execute phis in parallel. |
| // |
| // The insert function below has interdependent phi nodes: |
| // |
| // entry: |
| // t0 = *root // t0 is x or y before loop |
| // jump test |
| // body: |
| // print(t5) // t5 is x at loop entry |
| // t3 = t5.Child // t3 is x after loop |
| // jump test |
| // test: |
| // t5 = phi(t0, t3) // t5 is x at loop entry |
| // t6 = phi(t0, t5) // t6 is y at loop entry |
| // if t5 != nil goto body else done |
| // done: |
| // print(t6) |
| // return |
| // |
| // The two phis: |
| // |
| // t5 = phi(t0, t3) |
| // t6 = phi(t0, t5) |
| // |
| // must be executed in parallel as if they were written in Go |
| // as: |
| // |
| // t5, t6 = phi(t0, t3), phi(t0, t5) |
| // |
| // with the second phi node observing the original, not |
| // updated, value of t5. (In more complex examples, the phi |
| // nodes may be mutually recursive, breaking partial solutions |
| // based on simple reordering of the phi instructions. See the |
| // Briggs paper for detail.) |
| // |
| // The correct behavior is print(1, root); print(2, root); print(3, root). |
| // The previous incorrect behavior had print(2, nil). |
| |
| func main() { |
| insert() |
| print(3, root) |
| } |
| |
| var root = new(node) |
| |
| type node struct{ child *node } |
| |
| func insert() { |
| x := root |
| y := x |
| for x != nil { |
| y = x |
| print(1, y) |
| x = x.child |
| } |
| print(2, y) |
| } |
| |
| func print(order int, ptr *node) { |
| println(order, ptr) |
| if ptr != root { |
| panic(ptr) |
| } |
| } |