Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sink to MemMove optimization in injectdestructors #13002

Merged
merged 12 commits into from
Jan 2, 2020
Prev Previous commit
Next Next commit
MemMove optimization in inject destructors
  • Loading branch information
cooldome committed Dec 31, 2019
commit 008022b4a6aea089c31fd65220c0e914229f7d48
29 changes: 17 additions & 12 deletions compiler/injectdestructors.nim
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,11 @@ proc genSink(c: Con; dest, ri: PNode): PNode =
# we generate a fast assignment in this case:
result = newTree(nkFastAsgn, dest)

proc genSinkOrMemMove(c: Con; dest, ri: PNode, isFirstWrite: bool): PNode =
# optimize sink call into a bitwise mem
if isFirstWrite: newTree(nkFastAsgn, dest)
else: genSink(c, dest, ri)

proc genCopyNoCheck(c: Con; dest, ri: PNode): PNode =
let t = dest.typ.skipTypes({tyGenericInst, tyAlias, tySink})
result = genOp(c, t, attachedAsgn, dest, ri)
Expand Down Expand Up @@ -284,7 +289,7 @@ type
sinkArg

proc p(n: PNode; c: var Con; mode: ProcessMode): PNode
proc moveOrCopy(dest, ri: PNode; c: var Con): PNode
proc moveOrCopy(dest, ri: PNode; c: var Con, isFirstWrite = false): PNode

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

Expand Down Expand Up @@ -547,7 +552,7 @@ proc p(n: PNode; c: var Con; mode: ProcessMode): PNode =
if ri.kind == nkEmpty and c.inLoop > 0:
ri = genDefaultCall(v.typ, c, v.info)
if ri.kind != nkEmpty:
let r = moveOrCopy(v, ri, c)
let r = moveOrCopy(v, ri, c, isFirstWrite = (c.inLoop == 0))
result.add r
else: # keep the var but transform 'ri':
var v = copyNode(n)
Expand Down Expand Up @@ -609,21 +614,21 @@ proc p(n: PNode; c: var Con; mode: ProcessMode): PNode =
for i in 0..<n.len:
result[i] = p(n[i], c, mode)

proc moveOrCopy(dest, ri: PNode; c: var Con): PNode =
proc moveOrCopy(dest, ri: PNode; c: var Con, isFirstWrite = false): PNode =
case ri.kind
of nkCallKinds:
if isUnpackedTuple(dest):
result = newTree(nkFastAsgn, dest, p(ri, c, consumed))
else:
result = genSink(c, dest, ri)
result = genSinkOrMemMove(c, dest, ri, isFirstWrite)
result.add p(ri, c, consumed)
of nkBracketExpr:
if isUnpackedTuple(ri[0]):
# unpacking of tuple: take over elements
result = newTree(nkFastAsgn, dest, p(ri, c, consumed))
elif isAnalysableFieldAccess(ri, c.owner) and isLastRead(ri, c):
# Rule 3: `=sink`(x, z); wasMoved(z)
var snk = genSink(c, dest, ri)
var snk = genSinkOrMemMove(c, dest, ri, isFirstWrite)
snk.add ri
result = newTree(nkStmtList, snk, genWasMoved(ri, c))
else:
Expand All @@ -634,22 +639,22 @@ proc moveOrCopy(dest, ri: PNode; c: var Con): PNode =
if ri.len > 0 and isDangerousSeq(ri.typ):
result = genCopy(c, dest, ri)
else:
result = genSink(c, dest, ri)
result = genSinkOrMemMove(c, dest, ri, isFirstWrite)
result.add p(ri, c, consumed)
of nkObjConstr, nkTupleConstr, nkClosure, nkCharLit..nkNilLit:
result = genSink(c, dest, ri)
result = genSinkOrMemMove(c, dest, ri, isFirstWrite)
result.add p(ri, c, consumed)
of nkSym:
if isSinkParam(ri.sym):
# Rule 3: `=sink`(x, z); wasMoved(z)
sinkParamIsLastReadCheck(c, ri)
var snk = genSink(c, dest, ri)
var snk = genSinkOrMemMove(c, dest, ri, isFirstWrite)
snk.add ri
result = newTree(nkStmtList, snk, genWasMoved(ri, c))
elif ri.sym.kind != skParam and ri.sym.owner == c.owner and
isLastRead(ri, c) and canBeMoved(c, dest.typ):
# Rule 3: `=sink`(x, z); wasMoved(z)
var snk = genSink(c, dest, ri)
var snk = genSinkOrMemMove(c, dest, ri, isFirstWrite)
snk.add ri
result = newTree(nkStmtList, snk, genWasMoved(ri, c))
else:
Expand All @@ -663,7 +668,7 @@ proc moveOrCopy(dest, ri: PNode; c: var Con): PNode =
copyRi[1] = result[^1]
result[^1] = copyRi
else:
result = genSink(c, dest, ri)
result = genSinkOrMemMove(c, dest, ri, isFirstWrite)
result.add p(ri, c, sinkArg)
of nkObjDownConv, nkObjUpConv:
when false:
Expand All @@ -672,15 +677,15 @@ proc moveOrCopy(dest, ri: PNode; c: var Con): PNode =
copyRi[0] = result[^1]
result[^1] = copyRi
else:
result = genSink(c, dest, ri)
result = genSinkOrMemMove(c, dest, ri, isFirstWrite)
result.add p(ri, c, sinkArg)
of nkStmtListExpr, nkBlockExpr, nkIfExpr, nkCaseStmt:
handleNested(ri): moveOrCopy(dest, node, c)
else:
if isAnalysableFieldAccess(ri, c.owner) and isLastRead(ri, c) and
canBeMoved(c, dest.typ):
# Rule 3: `=sink`(x, z); wasMoved(z)
var snk = genSink(c, dest, ri)
var snk = genSinkOrMemMove(c, dest, ri, isFirstWrite)
snk.add ri
result = newTree(nkStmtList, snk, genWasMoved(ri, c))
else:
Expand Down
2 changes: 1 addition & 1 deletion tests/destructor/tmisc_destructors.nim
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ proc test(): auto =
var (a, b, _) = test()

doAssert assign_counter == 0
doAssert sink_counter == 6
doAssert sink_counter == 3

# bug #11510
proc main =
Expand Down