diff options
author | cooldome <cdome@bk.ru> | 2020-01-02 21:58:01 +0000 |
---|---|---|
committer | Andreas Rumpf <rumpf_a@web.de> | 2020-01-02 22:58:01 +0100 |
commit | 002d50f1f064cae1dbf49987172f7af5d9e7d35c (patch) | |
tree | ba5fca61c580f00e5eb2ac5a2c3eee4994671988 | |
parent | 0ff23e696c1e239214dfc2f1d2bb3e8fc6bf9493 (diff) | |
download | Nim-002d50f1f064cae1dbf49987172f7af5d9e7d35c.tar.gz |
Sink to MemMove optimization in injectdestructors (#13002)
-rw-r--r-- | compiler/injectdestructors.nim | 37 | ||||
-rw-r--r-- | compiler/liftdestructors.nim | 7 | ||||
-rw-r--r-- | compiler/lowerings.nim | 10 | ||||
-rw-r--r-- | tests/destructor/tmisc_destructors.nim | 2 |
4 files changed, 30 insertions, 26 deletions
diff --git a/compiler/injectdestructors.nim b/compiler/injectdestructors.nim index d9a17cf7a..fad1eb03b 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..<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: bool): 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]): @@ -623,7 +628,7 @@ proc moveOrCopy(dest, ri: PNode; c: var Con): PNode = 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: @@ -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: @@ -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 932b24bb0..daf91954b 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 cf8445820..d069bba84 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..<n.len-2: if n[i].kind == nkSym: v.addVar(n[i]) result.add newAsgnStmt(n[i], newTupleAccess(g, tempAsNode, i)) diff --git a/tests/destructor/tmisc_destructors.nim b/tests/destructor/tmisc_destructors.nim index 7fc8a61c2..7d6995e4e 100644 --- a/tests/destructor/tmisc_destructors.nim +++ b/tests/destructor/tmisc_destructors.nim @@ -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 = |