Skip to content

Commit fdf21be

Browse files
committed
cmd/compile: duplicate some scalar stores in wb blocks
DO NOT SUBMIT [mailing for initial feedback, needs benchmark numbers] Duplicate some scalar stores on both halves of a writeBarrier.enabled block, to reduce branching. There are other memory ops besides OpVarXXX and OpStore that we could consider here: OpMove, OpZero, Op*Call, atomic stores, OpSelect1, OpPhi. However, OpVarXXX and OpStore are by far the most common, and they correspond to a fixed number of instructions. The others are all rare and are either tricky (OpSelect1, OpPhi, atomic stores) or correspond to potentially lots of code. Fixes golang#19838 Change-Id: I0d5a68c2dfb3b6a6916b92151b3e64df533d4581
1 parent 700690f commit fdf21be

File tree

1 file changed

+19
-1
lines changed

1 file changed

+19
-1
lines changed

src/cmd/compile/internal/ssa/writebarrier.go

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ import (
1010
"cmd/internal/src"
1111
)
1212

13+
// nonWBBudget is the number of non-WB stores we can duplicate
14+
// on either side of a check of runtime.writeBarrier.enabled.
15+
const nonWBBudget = 2
16+
1317
// needwb returns whether we need write barrier for store op v.
1418
// v must be Store/Move/Zero.
1519
func needwb(v *Value) bool {
@@ -117,6 +121,7 @@ func writebarrier(f *Func) {
117121
var last *Value
118122
var start, end int
119123
values := b.Values
124+
budget := nonWBBudget
120125
FindSeq:
121126
for i := len(values) - 1; i >= 0; i-- {
122127
w := values[i]
@@ -127,6 +132,15 @@ func writebarrier(f *Func) {
127132
last = w
128133
end = i + 1
129134
}
135+
case OpStore:
136+
if last == nil {
137+
continue
138+
}
139+
if budget > 0 {
140+
budget--
141+
} else {
142+
break FindSeq
143+
}
130144
case OpVarDef, OpVarLive, OpVarKill:
131145
continue
132146
default:
@@ -195,6 +209,8 @@ func writebarrier(f *Func) {
195209
case OpZeroWB:
196210
fn = typedmemclr
197211
typ = &ExternSymbol{Sym: w.Aux.(*types.Type).Symbol()}
212+
case OpStore:
213+
val = w.Args[1]
198214
case OpVarDef, OpVarLive, OpVarKill:
199215
}
200216

@@ -203,13 +219,15 @@ func writebarrier(f *Func) {
203219
case OpStoreWB, OpMoveWB, OpZeroWB:
204220
volatile := w.Op == OpMoveWB && isVolatile(val)
205221
memThen = wbcall(pos, bThen, fn, typ, ptr, val, memThen, sp, sb, volatile)
222+
case OpStore:
223+
memThen = bThen.NewValue3A(pos, OpStore, types.TypeMem, w.Aux, ptr, val, memThen)
206224
case OpVarDef, OpVarLive, OpVarKill:
207225
memThen = bThen.NewValue1A(pos, w.Op, types.TypeMem, w.Aux, memThen)
208226
}
209227

210228
// else block: normal store
211229
switch w.Op {
212-
case OpStoreWB:
230+
case OpStoreWB, OpStore:
213231
memElse = bElse.NewValue3A(pos, OpStore, types.TypeMem, w.Aux, ptr, val, memElse)
214232
case OpMoveWB:
215233
memElse = bElse.NewValue3I(pos, OpMove, types.TypeMem, w.AuxInt, ptr, val, memElse)

0 commit comments

Comments
 (0)