Skip to content

Commit a73849c

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 613030a commit a73849c

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
@@ -9,6 +9,10 @@ import (
99
"cmd/internal/src"
1010
)
1111

12+
// nonWBBudget is the number of non-WB stores we can duplicate
13+
// on either side of a check of runtime.writeBarrier.enabled.
14+
const nonWBBudget = 2
15+
1216
// needwb returns whether we need write barrier for store op v.
1317
// v must be Store/Move/Zero.
1418
func needwb(v *Value) bool {
@@ -116,6 +120,7 @@ func writebarrier(f *Func) {
116120
var last *Value
117121
var start, end int
118122
values := b.Values
123+
budget := nonWBBudget
119124
FindSeq:
120125
for i := len(values) - 1; i >= 0; i-- {
121126
w := values[i]
@@ -126,6 +131,15 @@ func writebarrier(f *Func) {
126131
last = w
127132
end = i + 1
128133
}
134+
case OpStore:
135+
if last == nil {
136+
continue
137+
}
138+
if budget > 0 {
139+
budget--
140+
} else {
141+
break FindSeq
142+
}
129143
case OpVarDef, OpVarLive, OpVarKill:
130144
continue
131145
default:
@@ -194,6 +208,8 @@ func writebarrier(f *Func) {
194208
case OpZeroWB:
195209
fn = typedmemclr
196210
typ = &ExternSymbol{Sym: w.Aux.(Type).Symbol()}
211+
case OpStore:
212+
val = w.Args[1]
197213
case OpVarDef, OpVarLive, OpVarKill:
198214
}
199215

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

209227
// else block: normal store
210228
switch w.Op {
211-
case OpStoreWB:
229+
case OpStoreWB, OpStore:
212230
memElse = bElse.NewValue3A(pos, OpStore, TypeMem, w.Aux, ptr, val, memElse)
213231
case OpMoveWB:
214232
memElse = bElse.NewValue3I(pos, OpMove, TypeMem, w.AuxInt, ptr, val, memElse)

0 commit comments

Comments
 (0)