Skip to content

Commit 002d50f

Browse files
cooldomeAraq
authored andcommitted
Sink to MemMove optimization in injectdestructors (#13002)
1 parent 0ff23e6 commit 002d50f

File tree

4 files changed

+30
-26
lines changed

4 files changed

+30
-26
lines changed

compiler/injectdestructors.nim

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,11 @@ proc genSink(c: Con; dest, ri: PNode): PNode =
212212
# we generate a fast assignment in this case:
213213
result = newTree(nkFastAsgn, dest)
214214

215+
proc genSinkOrMemMove(c: Con; dest, ri: PNode, isFirstWrite: bool): PNode =
216+
# optimize sink call into a bitwise memcopy
217+
if isFirstWrite: newTree(nkFastAsgn, dest)
218+
else: genSink(c, dest, ri)
219+
215220
proc genCopyNoCheck(c: Con; dest, ri: PNode): PNode =
216221
let t = dest.typ.skipTypes({tyGenericInst, tyAlias, tySink})
217222
result = genOp(c, t, attachedAsgn, dest, ri)
@@ -284,7 +289,7 @@ type
284289
sinkArg
285290

286291
proc p(n: PNode; c: var Con; mode: ProcessMode): PNode
287-
proc moveOrCopy(dest, ri: PNode; c: var Con): PNode
292+
proc moveOrCopy(dest, ri: PNode; c: var Con, isFirstWrite: bool): PNode
288293

289294
proc isClosureEnv(n: PNode): bool = n.kind == nkSym and n.sym.name.s[0] == ':'
290295

@@ -547,7 +552,7 @@ proc p(n: PNode; c: var Con; mode: ProcessMode): PNode =
547552
if ri.kind == nkEmpty and c.inLoop > 0:
548553
ri = genDefaultCall(v.typ, c, v.info)
549554
if ri.kind != nkEmpty:
550-
let r = moveOrCopy(v, ri, c)
555+
let r = moveOrCopy(v, ri, c, isFirstWrite = (c.inLoop == 0))
551556
result.add r
552557
else: # keep the var but transform 'ri':
553558
var v = copyNode(n)
@@ -566,7 +571,7 @@ proc p(n: PNode; c: var Con; mode: ProcessMode): PNode =
566571
else:
567572
if n[0].kind in {nkDotExpr, nkCheckedFieldExpr}:
568573
cycleCheck(n, c)
569-
result = moveOrCopy(n[0], n[1], c)
574+
result = moveOrCopy(n[0], n[1], c, isFirstWrite = false)
570575
else:
571576
result = copyNode(n)
572577
result.add copyTree(n[0])
@@ -609,21 +614,21 @@ proc p(n: PNode; c: var Con; mode: ProcessMode): PNode =
609614
for i in 0..<n.len:
610615
result[i] = p(n[i], c, mode)
611616

612-
proc moveOrCopy(dest, ri: PNode; c: var Con): PNode =
617+
proc moveOrCopy(dest, ri: PNode; c: var Con, isFirstWrite: bool): PNode =
613618
case ri.kind
614619
of nkCallKinds:
615620
if isUnpackedTuple(dest):
616621
result = newTree(nkFastAsgn, dest, p(ri, c, consumed))
617622
else:
618-
result = genSink(c, dest, ri)
623+
result = genSinkOrMemMove(c, dest, ri, isFirstWrite)
619624
result.add p(ri, c, consumed)
620625
of nkBracketExpr:
621626
if isUnpackedTuple(ri[0]):
622627
# unpacking of tuple: take over elements
623628
result = newTree(nkFastAsgn, dest, p(ri, c, consumed))
624629
elif isAnalysableFieldAccess(ri, c.owner) and isLastRead(ri, c):
625630
# Rule 3: `=sink`(x, z); wasMoved(z)
626-
var snk = genSink(c, dest, ri)
631+
var snk = genSinkOrMemMove(c, dest, ri, isFirstWrite)
627632
snk.add ri
628633
result = newTree(nkStmtList, snk, genWasMoved(ri, c))
629634
else:
@@ -634,53 +639,53 @@ proc moveOrCopy(dest, ri: PNode; c: var Con): PNode =
634639
if ri.len > 0 and isDangerousSeq(ri.typ):
635640
result = genCopy(c, dest, ri)
636641
else:
637-
result = genSink(c, dest, ri)
642+
result = genSinkOrMemMove(c, dest, ri, isFirstWrite)
638643
result.add p(ri, c, consumed)
639644
of nkObjConstr, nkTupleConstr, nkClosure, nkCharLit..nkNilLit:
640-
result = genSink(c, dest, ri)
645+
result = genSinkOrMemMove(c, dest, ri, isFirstWrite)
641646
result.add p(ri, c, consumed)
642647
of nkSym:
643648
if isSinkParam(ri.sym):
644649
# Rule 3: `=sink`(x, z); wasMoved(z)
645650
sinkParamIsLastReadCheck(c, ri)
646-
var snk = genSink(c, dest, ri)
651+
var snk = genSinkOrMemMove(c, dest, ri, isFirstWrite)
647652
snk.add ri
648653
result = newTree(nkStmtList, snk, genWasMoved(ri, c))
649654
elif ri.sym.kind != skParam and ri.sym.owner == c.owner and
650655
isLastRead(ri, c) and canBeMoved(c, dest.typ):
651656
# Rule 3: `=sink`(x, z); wasMoved(z)
652-
var snk = genSink(c, dest, ri)
657+
var snk = genSinkOrMemMove(c, dest, ri, isFirstWrite)
653658
snk.add ri
654659
result = newTree(nkStmtList, snk, genWasMoved(ri, c))
655660
else:
656661
result = genCopy(c, dest, ri)
657662
result.add p(ri, c, consumed)
658663
of nkHiddenSubConv, nkHiddenStdConv, nkConv:
659664
when false:
660-
result = moveOrCopy(dest, ri[1], c)
665+
result = moveOrCopy(dest, ri[1], c, isFirstWrite)
661666
if not sameType(ri.typ, ri[1].typ):
662667
let copyRi = copyTree(ri)
663668
copyRi[1] = result[^1]
664669
result[^1] = copyRi
665670
else:
666-
result = genSink(c, dest, ri)
671+
result = genSinkOrMemMove(c, dest, ri, isFirstWrite)
667672
result.add p(ri, c, sinkArg)
668673
of nkObjDownConv, nkObjUpConv:
669674
when false:
670-
result = moveOrCopy(dest, ri[0], c)
675+
result = moveOrCopy(dest, ri[0], c, isFirstWrite)
671676
let copyRi = copyTree(ri)
672677
copyRi[0] = result[^1]
673678
result[^1] = copyRi
674679
else:
675-
result = genSink(c, dest, ri)
680+
result = genSinkOrMemMove(c, dest, ri, isFirstWrite)
676681
result.add p(ri, c, sinkArg)
677682
of nkStmtListExpr, nkBlockExpr, nkIfExpr, nkCaseStmt:
678-
handleNested(ri): moveOrCopy(dest, node, c)
683+
handleNested(ri): moveOrCopy(dest, node, c, isFirstWrite)
679684
else:
680685
if isAnalysableFieldAccess(ri, c.owner) and isLastRead(ri, c) and
681686
canBeMoved(c, dest.typ):
682687
# Rule 3: `=sink`(x, z); wasMoved(z)
683-
var snk = genSink(c, dest, ri)
688+
var snk = genSinkOrMemMove(c, dest, ri, isFirstWrite)
684689
snk.add ri
685690
result = newTree(nkStmtList, snk, genWasMoved(ri, c))
686691
else:

compiler/liftdestructors.nim

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -253,13 +253,6 @@ proc considerUserDefinedOp(c: var TLiftCtx; t: PType; body, x, y: PNode): bool =
253253
body.add newDeepCopyCall(op, x, y)
254254
result = true
255255

256-
proc addVar(father, v, value: PNode) =
257-
var vpart = newNodeI(nkIdentDefs, v.info, 3)
258-
vpart[0] = v
259-
vpart[1] = newNodeI(nkEmpty, v.info)
260-
vpart[2] = value
261-
father.add vpart
262-
263256
proc declareCounter(c: var TLiftCtx; body: PNode; first: BiggestInt): PNode =
264257
var temp = newSym(skTemp, getIdent(c.g.cache, lowerings.genPrefix), c.fn, c.info)
265258
temp.typ = getSysType(c.g, body.info, tyInt)

compiler/lowerings.nim

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,13 @@ proc addVar*(father, v: PNode) =
4242
vpart[2] = vpart[1]
4343
father.add vpart
4444

45+
proc addVar*(father, v, value: PNode) =
46+
var vpart = newNodeI(nkIdentDefs, v.info, 3)
47+
vpart[0] = v
48+
vpart[1] = newNodeI(nkEmpty, v.info)
49+
vpart[2] = value
50+
father.add vpart
51+
4552
proc newAsgnStmt*(le, ri: PNode): PNode =
4653
result = newNodeI(nkAsgn, le.info, 2)
4754
result[0] = le
@@ -63,10 +70,9 @@ proc lowerTupleUnpacking*(g: ModuleGraph; n: PNode; owner: PSym): PNode =
6370

6471
var v = newNodeI(nkVarSection, value.info)
6572
let tempAsNode = newSymNode(temp)
66-
v.addVar(tempAsNode)
73+
v.addVar(tempAsNode, value)
6774
result.add(v)
6875

69-
result.add newAsgnStmt(tempAsNode, value)
7076
for i in 0..<n.len-2:
7177
if n[i].kind == nkSym: v.addVar(n[i])
7278
result.add newAsgnStmt(n[i], newTupleAccess(g, tempAsNode, i))

tests/destructor/tmisc_destructors.nim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ proc test(): auto =
2828
var (a, b, _) = test()
2929

3030
doAssert assign_counter == 0
31-
doAssert sink_counter == 6
31+
doAssert sink_counter == 3
3232

3333
# bug #11510
3434
proc main =

0 commit comments

Comments
 (0)