Commit 5bfd1ef0 authored by Cherry Zhang's avatar Cherry Zhang

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: 's avatarKeith Randall <khr@golang.org>
parent 4775b7fe
This diff is collapsed.
...@@ -298,10 +298,9 @@ var genericOps = []opData{ ...@@ -298,10 +298,9 @@ var genericOps = []opData{
// Memory operations with write barriers. // Memory operations with write barriers.
// Expand to runtime calls. Write barrier will be removed if write on stack. // Expand to runtime calls. Write barrier will be removed if write on stack.
{name: "StoreWB", argLength: 3, typ: "Mem", aux: "Int64"}, // Store arg1 to arg0. arg2=memory, auxint=size. Returns memory. {name: "StoreWB", argLength: 3, typ: "Mem", aux: "Int64"}, // Store arg1 to arg0. arg2=memory, auxint=size. Returns memory.
{name: "MoveWB", argLength: 3, typ: "Mem", aux: "SymSizeAndAlign"}, // arg0=destptr, arg1=srcptr, arg2=mem, auxint=size+alignment, aux=symbol-of-type (for typedmemmove). Returns memory. {name: "MoveWB", argLength: 3, typ: "Mem", aux: "SymSizeAndAlign"}, // arg0=destptr, arg1=srcptr, arg2=mem, auxint=size+alignment, aux=symbol-of-type (for typedmemmove). Returns memory.
{name: "MoveWBVolatile", argLength: 3, typ: "Mem", aux: "SymSizeAndAlign"}, // arg0=destptr, arg1=srcptr, arg2=mem, auxint=size+alignment, aux=symbol-of-type (for typedmemmove). Returns memory. Src is volatile, i.e. needs to move to a temp space before calling typedmemmove. {name: "ZeroWB", argLength: 2, typ: "Mem", aux: "SymSizeAndAlign"}, // arg0=destptr, arg1=mem, auxint=size+alignment, aux=symbol-of-type. Returns memory.
{name: "ZeroWB", argLength: 2, typ: "Mem", aux: "SymSizeAndAlign"}, // arg0=destptr, arg1=mem, auxint=size+alignment, aux=symbol-of-type. Returns memory.
// Function calls. Arguments to the call have already been written to the stack. // Function calls. Arguments to the call have already been written to the stack.
// Return values appear on the stack. The method receiver, if any, is treated // Return values appear on the stack. The method receiver, if any, is treated
......
...@@ -1818,7 +1818,6 @@ const ( ...@@ -1818,7 +1818,6 @@ const (
OpZero OpZero
OpStoreWB OpStoreWB
OpMoveWB OpMoveWB
OpMoveWBVolatile
OpZeroWB OpZeroWB
OpClosureCall OpClosureCall
OpStaticCall OpStaticCall
...@@ -21623,12 +21622,6 @@ var opcodeTable = [...]opInfo{ ...@@ -21623,12 +21622,6 @@ var opcodeTable = [...]opInfo{
argLen: 3, argLen: 3,
generic: true, generic: true,
}, },
{
name: "MoveWBVolatile",
auxType: auxSymSizeAndAlign,
argLen: 3,
generic: true,
},
{ {
name: "ZeroWB", name: "ZeroWB",
auxType: auxSymSizeAndAlign, auxType: auxSymSizeAndAlign,
......
...@@ -35,12 +35,12 @@ func writebarrier(f *Func) { ...@@ -35,12 +35,12 @@ func writebarrier(f *Func) {
hasStore := false hasStore := false
for _, v := range b.Values { for _, v := range b.Values {
switch v.Op { switch v.Op {
case OpStoreWB, OpMoveWB, OpMoveWBVolatile, OpZeroWB: case OpStoreWB, OpMoveWB, OpZeroWB:
if IsStackAddr(v.Args[0]) { if IsStackAddr(v.Args[0]) {
switch v.Op { switch v.Op {
case OpStoreWB: case OpStoreWB:
v.Op = OpStore v.Op = OpStore
case OpMoveWB, OpMoveWBVolatile: case OpMoveWB:
v.Op = OpMove v.Op = OpMove
v.Aux = nil v.Aux = nil
case OpZeroWB: case OpZeroWB:
...@@ -103,7 +103,7 @@ func writebarrier(f *Func) { ...@@ -103,7 +103,7 @@ func writebarrier(f *Func) {
values := b.Values values := b.Values
for i := len(values) - 1; i >= 0; i-- { for i := len(values) - 1; i >= 0; i-- {
w := values[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 { if last == nil {
last = w last = w
end = i + 1 end = i + 1
...@@ -159,7 +159,7 @@ func writebarrier(f *Func) { ...@@ -159,7 +159,7 @@ func writebarrier(f *Func) {
var val *Value var val *Value
ptr := w.Args[0] ptr := w.Args[0]
siz := w.AuxInt 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 pos = w.Pos
var op Op var op Op
...@@ -169,7 +169,7 @@ func writebarrier(f *Func) { ...@@ -169,7 +169,7 @@ func writebarrier(f *Func) {
op = OpStore op = OpStore
fn = writebarrierptr fn = writebarrierptr
val = w.Args[1] val = w.Args[1]
case OpMoveWB, OpMoveWBVolatile: case OpMoveWB:
op = OpMove op = OpMove
fn = typedmemmove fn = typedmemmove
val = w.Args[1] val = w.Args[1]
...@@ -179,7 +179,8 @@ func writebarrier(f *Func) { ...@@ -179,7 +179,8 @@ func writebarrier(f *Func) {
} }
// then block: emit write barrier call // 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 // else block: normal store
if op == OpZero { if op == OpZero {
...@@ -223,7 +224,7 @@ func writebarrier(f *Func) { ...@@ -223,7 +224,7 @@ func writebarrier(f *Func) {
// if we have more stores in this block, do this block again // if we have more stores in this block, do this block again
for _, w := range b.Values { 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 goto again
} }
} }
...@@ -303,3 +304,12 @@ func IsStackAddr(v *Value) bool { ...@@ -303,3 +304,12 @@ func IsStackAddr(v *Value) bool {
} }
return false 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
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment