mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/compile: add x.Uses==1 test to load combiners
We need to make sure that when we combine loads, we only do so if there are no other uses of the load. We can't split one load into two because that can then lead to inconsistent loaded values in the presence of races. Add some aggressive copy removal code so that phantom "dead copy" uses of values are cleaned up promptly. This lets us use x.Uses==1 conditions reliably. Change-Id: I9037311db85665f3868dbeb3adb3de5c20728b38 Reviewed-on: https://go-review.googlesource.com/21853 Reviewed-by: Todd Neal <todd@tneal.org>
This commit is contained in:
parent
204b6f48c5
commit
cd85f711c0
7 changed files with 129 additions and 21 deletions
|
|
@ -40,9 +40,44 @@ func applyRewrite(f *Func, rb func(*Block) bool, rv func(*Value, *Config) bool)
|
|||
}
|
||||
curb = nil
|
||||
for _, v := range b.Values {
|
||||
change = copyelimValue(v) || change
|
||||
change = phielimValue(v) || change
|
||||
|
||||
// Eliminate copy inputs.
|
||||
// If any copy input becomes unused, mark it
|
||||
// as invalid and discard its argument. Repeat
|
||||
// recursively on the discarded argument.
|
||||
// This phase helps remove phantom "dead copy" uses
|
||||
// of a value so that a x.Uses==1 rule condition
|
||||
// fires reliably.
|
||||
for i, a := range v.Args {
|
||||
if a.Op != OpCopy {
|
||||
continue
|
||||
}
|
||||
x := a.Args[0]
|
||||
// Rewriting can generate OpCopy loops.
|
||||
// They are harmless (see removePredecessor),
|
||||
// but take care to stop if we find a cycle.
|
||||
slow := x // advances every other iteration
|
||||
var advance bool
|
||||
for x.Op == OpCopy {
|
||||
x = x.Args[0]
|
||||
if slow == x {
|
||||
break
|
||||
}
|
||||
if advance {
|
||||
slow = slow.Args[0]
|
||||
}
|
||||
advance = !advance
|
||||
}
|
||||
v.SetArg(i, x)
|
||||
change = true
|
||||
for a.Uses == 0 {
|
||||
b := a.Args[0]
|
||||
a.reset(OpInvalid)
|
||||
a = b
|
||||
}
|
||||
}
|
||||
|
||||
// apply rewrite function
|
||||
curv = v
|
||||
if rv(v, config) {
|
||||
|
|
@ -52,7 +87,28 @@ func applyRewrite(f *Func, rb func(*Block) bool, rv func(*Value, *Config) bool)
|
|||
}
|
||||
}
|
||||
if !change {
|
||||
return
|
||||
break
|
||||
}
|
||||
}
|
||||
// remove clobbered copies
|
||||
for _, b := range f.Blocks {
|
||||
j := 0
|
||||
for i, v := range b.Values {
|
||||
if v.Op == OpInvalid {
|
||||
f.freeValue(v)
|
||||
continue
|
||||
}
|
||||
if i != j {
|
||||
b.Values[j] = v
|
||||
}
|
||||
j++
|
||||
}
|
||||
if j != len(b.Values) {
|
||||
tail := b.Values[j:]
|
||||
for j := range tail {
|
||||
tail[j] = nil
|
||||
}
|
||||
b.Values = b.Values[:j]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue