Closed
Description
At some point in the distant past, it was (almost) always the case that OpPhi values, if present, were the first values in the block. And some passes appear to assume that. Here are two comments from the deadstore
pass:
for _, v := range b.Values {
if v.Op == OpPhi {
// Ignore phis - they will always be first and can't be eliminated
continue
}
/* ... */
// walk to previous store
if v.Op == OpPhi {
continue // At start of block. Move on to next block.
}
But it is definitely no longer the case that all phis are the at the beginning of the block. Among other reasons, the nilcheck
and writebarrier
passes call storeOrder
, which re-orders values in a way that would move some phis away from the beginning.
I tried to test this by adding code that randomizes value order before all passes prior to scheduling and running toolstash, but register selection changes made that unhelpful before I could detect anything substantive. Sample:
inconsistent log line:
/var/folders/1t/n61cbvls5bl293bbb0zyypqw0000gn/T/go-build711603550/runtime.a.log:30617:
obj: 00154 (/var/folders/1t/n61cbvls5bl293bbb0zyypqw0000gn/T/toolstash-check-240465411/go/src/runtime/mbitmap.go:1533) ANDQ R14, R11
/var/folders/1t/n61cbvls5bl293bbb0zyypqw0000gn/T/go-build711603550/runtime.a.stash.log:30617:
obj: 00154 (/var/folders/1t/n61cbvls5bl293bbb0zyypqw0000gn/T/toolstash-check-240465411/go/src/runtime/mbitmap.go:1533) ANDQ R11, R14
2017/04/29 14:53:10 exit status 2
Let's:
- decide if/when we want to assume that OpPhis are always first, and if we ever do, add an ssa internal check for it
- fix up any code that depends on faulty assumptions
- make the schedule pass more fully deterministic
- do some randomization-based testing to make sure that any assumptions about value order are safe/correct (perhaps always when ssa/check is on, somehow?)