cmd/compile: get rid of "volatile" in SSA

A value is "volatile" if it is a pointer to the argument region
on stack which will be clobbered by function call. This is used
to make sure the value is safe when inserting write barrier calls.
The writebarrier pass can tell whether a value is such a pointer.
Therefore no need to mark it when building SSA and thread this
information through.

Passes "toolstash -cmp" on std.

Updates #17583.

Change-Id: Idc5fc0d710152b94b3c504ce8db55ea9ff5b5195
Reviewed-on: https://go-review.googlesource.com/36835
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
Cherry Zhang 2017-02-02 19:47:59 -05:00
parent 4775b7feb1
commit 5bfd1ef036
4 changed files with 69 additions and 81 deletions

View file

@ -35,12 +35,12 @@ func writebarrier(f *Func) {
hasStore := false
for _, v := range b.Values {
switch v.Op {
case OpStoreWB, OpMoveWB, OpMoveWBVolatile, OpZeroWB:
case OpStoreWB, OpMoveWB, OpZeroWB:
if IsStackAddr(v.Args[0]) {
switch v.Op {
case OpStoreWB:
v.Op = OpStore
case OpMoveWB, OpMoveWBVolatile:
case OpMoveWB:
v.Op = OpMove
v.Aux = nil
case OpZeroWB:
@ -103,7 +103,7 @@ func writebarrier(f *Func) {
values := b.Values
for i := len(values) - 1; i >= 0; i-- {
w := values[i]
if w.Op == OpStoreWB || w.Op == OpMoveWB || w.Op == OpMoveWBVolatile || w.Op == OpZeroWB {
if w.Op == OpStoreWB || w.Op == OpMoveWB || w.Op == OpZeroWB {
if last == nil {
last = w
end = i + 1
@ -159,7 +159,7 @@ func writebarrier(f *Func) {
var val *Value
ptr := w.Args[0]
siz := w.AuxInt
typ := w.Aux // only non-nil for MoveWB, MoveWBVolatile, ZeroWB
typ := w.Aux // only non-nil for MoveWB, ZeroWB
pos = w.Pos
var op Op
@ -169,7 +169,7 @@ func writebarrier(f *Func) {
op = OpStore
fn = writebarrierptr
val = w.Args[1]
case OpMoveWB, OpMoveWBVolatile:
case OpMoveWB:
op = OpMove
fn = typedmemmove
val = w.Args[1]
@ -179,7 +179,8 @@ func writebarrier(f *Func) {
}
// then block: emit write barrier call
memThen = wbcall(pos, bThen, fn, typ, ptr, val, memThen, sp, sb, w.Op == OpMoveWBVolatile)
volatile := w.Op == OpMoveWB && isVolatile(val)
memThen = wbcall(pos, bThen, fn, typ, ptr, val, memThen, sp, sb, volatile)
// else block: normal store
if op == OpZero {
@ -223,7 +224,7 @@ func writebarrier(f *Func) {
// if we have more stores in this block, do this block again
for _, w := range b.Values {
if w.Op == OpStoreWB || w.Op == OpMoveWB || w.Op == OpMoveWBVolatile || w.Op == OpZeroWB {
if w.Op == OpStoreWB || w.Op == OpMoveWB || w.Op == OpZeroWB {
goto again
}
}
@ -303,3 +304,12 @@ func IsStackAddr(v *Value) bool {
}
return false
}
// isVolatile returns whether v is a pointer to argument region on stack which
// will be clobbered by a function call.
func isVolatile(v *Value) bool {
for v.Op == OpOffPtr || v.Op == OpAddPtr || v.Op == OpPtrIndex || v.Op == OpCopy {
v = v.Args[0]
}
return v.Op == OpSP
}