From 002d50f1f064cae1dbf49987172f7af5d9e7d35c Mon Sep 17 00:00:00 2001 From: cooldome Date: Thu, 2 Jan 2020 21:58:01 +0000 Subject: [PATCH] Sink to MemMove optimization in injectdestructors (#13002) --- compiler/injectdestructors.nim | 37 +++++++++++++++----------- compiler/liftdestructors.nim | 7 ----- compiler/lowerings.nim | 10 +++++-- tests/destructor/tmisc_destructors.nim | 2 +- 4 files changed, 30 insertions(+), 26 deletions(-) diff --git a/compiler/injectdestructors.nim b/compiler/injectdestructors.nim index d9a17cf7a2bfd..fad1eb03b9ff8 100644 --- a/compiler/injectdestructors.nim +++ b/compiler/injectdestructors.nim @@ -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 memcopy + 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) @@ -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: bool): PNode proc isClosureEnv(n: PNode): bool = n.kind == nkSym and n.sym.name.s[0] == ':' @@ -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) @@ -566,7 +571,7 @@ proc p(n: PNode; c: var Con; mode: ProcessMode): PNode = else: if n[0].kind in {nkDotExpr, nkCheckedFieldExpr}: cycleCheck(n, c) - result = moveOrCopy(n[0], n[1], c) + result = moveOrCopy(n[0], n[1], c, isFirstWrite = false) else: result = copyNode(n) result.add copyTree(n[0]) @@ -609,13 +614,13 @@ proc p(n: PNode; c: var Con; mode: ProcessMode): PNode = for i in 0.. 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: @@ -657,30 +662,30 @@ proc moveOrCopy(dest, ri: PNode; c: var Con): PNode = result.add p(ri, c, consumed) of nkHiddenSubConv, nkHiddenStdConv, nkConv: when false: - result = moveOrCopy(dest, ri[1], c) + result = moveOrCopy(dest, ri[1], c, isFirstWrite) if not sameType(ri.typ, ri[1].typ): let copyRi = copyTree(ri) 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: - result = moveOrCopy(dest, ri[0], c) + result = moveOrCopy(dest, ri[0], c, isFirstWrite) let copyRi = copyTree(ri) 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) + handleNested(ri): moveOrCopy(dest, node, c, isFirstWrite) 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: diff --git a/compiler/liftdestructors.nim b/compiler/liftdestructors.nim index 932b24bb097b2..daf91954b05be 100644 --- a/compiler/liftdestructors.nim +++ b/compiler/liftdestructors.nim @@ -253,13 +253,6 @@ proc considerUserDefinedOp(c: var TLiftCtx; t: PType; body, x, y: PNode): bool = body.add newDeepCopyCall(op, x, y) result = true -proc addVar(father, v, value: PNode) = - var vpart = newNodeI(nkIdentDefs, v.info, 3) - vpart[0] = v - vpart[1] = newNodeI(nkEmpty, v.info) - vpart[2] = value - father.add vpart - proc declareCounter(c: var TLiftCtx; body: PNode; first: BiggestInt): PNode = var temp = newSym(skTemp, getIdent(c.g.cache, lowerings.genPrefix), c.fn, c.info) temp.typ = getSysType(c.g, body.info, tyInt) diff --git a/compiler/lowerings.nim b/compiler/lowerings.nim index cf8445820580b..d069bba84171b 100644 --- a/compiler/lowerings.nim +++ b/compiler/lowerings.nim @@ -42,6 +42,13 @@ proc addVar*(father, v: PNode) = vpart[2] = vpart[1] father.add vpart +proc addVar*(father, v, value: PNode) = + var vpart = newNodeI(nkIdentDefs, v.info, 3) + vpart[0] = v + vpart[1] = newNodeI(nkEmpty, v.info) + vpart[2] = value + father.add vpart + proc newAsgnStmt*(le, ri: PNode): PNode = result = newNodeI(nkAsgn, le.info, 2) result[0] = le @@ -63,10 +70,9 @@ proc lowerTupleUnpacking*(g: ModuleGraph; n: PNode; owner: PSym): PNode = var v = newNodeI(nkVarSection, value.info) let tempAsNode = newSymNode(temp) - v.addVar(tempAsNode) + v.addVar(tempAsNode, value) result.add(v) - result.add newAsgnStmt(tempAsNode, value) for i in 0..