Sink to MemMove optimization in injectdestructors (#13002)
This commit is contained in:
parent
0ff23e696c
commit
002d50f1f0
4 changed files with 30 additions and 26 deletions
|
|
@ -212,6 +212,11 @@ proc genSink(c: Con; dest, ri: PNode): PNode =
|
||||||
# we generate a fast assignment in this case:
|
# we generate a fast assignment in this case:
|
||||||
result = newTree(nkFastAsgn, dest)
|
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 =
|
proc genCopyNoCheck(c: Con; dest, ri: PNode): PNode =
|
||||||
let t = dest.typ.skipTypes({tyGenericInst, tyAlias, tySink})
|
let t = dest.typ.skipTypes({tyGenericInst, tyAlias, tySink})
|
||||||
result = genOp(c, t, attachedAsgn, dest, ri)
|
result = genOp(c, t, attachedAsgn, dest, ri)
|
||||||
|
|
@ -284,7 +289,7 @@ type
|
||||||
sinkArg
|
sinkArg
|
||||||
|
|
||||||
proc p(n: PNode; c: var Con; mode: ProcessMode): PNode
|
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] == ':'
|
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:
|
if ri.kind == nkEmpty and c.inLoop > 0:
|
||||||
ri = genDefaultCall(v.typ, c, v.info)
|
ri = genDefaultCall(v.typ, c, v.info)
|
||||||
if ri.kind != nkEmpty:
|
if ri.kind != nkEmpty:
|
||||||
let r = moveOrCopy(v, ri, c)
|
let r = moveOrCopy(v, ri, c, isFirstWrite = (c.inLoop == 0))
|
||||||
result.add r
|
result.add r
|
||||||
else: # keep the var but transform 'ri':
|
else: # keep the var but transform 'ri':
|
||||||
var v = copyNode(n)
|
var v = copyNode(n)
|
||||||
|
|
@ -566,7 +571,7 @@ proc p(n: PNode; c: var Con; mode: ProcessMode): PNode =
|
||||||
else:
|
else:
|
||||||
if n[0].kind in {nkDotExpr, nkCheckedFieldExpr}:
|
if n[0].kind in {nkDotExpr, nkCheckedFieldExpr}:
|
||||||
cycleCheck(n, c)
|
cycleCheck(n, c)
|
||||||
result = moveOrCopy(n[0], n[1], c)
|
result = moveOrCopy(n[0], n[1], c, isFirstWrite = false)
|
||||||
else:
|
else:
|
||||||
result = copyNode(n)
|
result = copyNode(n)
|
||||||
result.add copyTree(n[0])
|
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:
|
for i in 0..<n.len:
|
||||||
result[i] = p(n[i], c, mode)
|
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
|
case ri.kind
|
||||||
of nkCallKinds:
|
of nkCallKinds:
|
||||||
if isUnpackedTuple(dest):
|
if isUnpackedTuple(dest):
|
||||||
result = newTree(nkFastAsgn, dest, p(ri, c, consumed))
|
result = newTree(nkFastAsgn, dest, p(ri, c, consumed))
|
||||||
else:
|
else:
|
||||||
result = genSink(c, dest, ri)
|
result = genSinkOrMemMove(c, dest, ri, isFirstWrite)
|
||||||
result.add p(ri, c, consumed)
|
result.add p(ri, c, consumed)
|
||||||
of nkBracketExpr:
|
of nkBracketExpr:
|
||||||
if isUnpackedTuple(ri[0]):
|
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))
|
result = newTree(nkFastAsgn, dest, p(ri, c, consumed))
|
||||||
elif isAnalysableFieldAccess(ri, c.owner) and isLastRead(ri, c):
|
elif isAnalysableFieldAccess(ri, c.owner) and isLastRead(ri, c):
|
||||||
# Rule 3: `=sink`(x, z); wasMoved(z)
|
# Rule 3: `=sink`(x, z); wasMoved(z)
|
||||||
var snk = genSink(c, dest, ri)
|
var snk = genSinkOrMemMove(c, dest, ri, isFirstWrite)
|
||||||
snk.add ri
|
snk.add ri
|
||||||
result = newTree(nkStmtList, snk, genWasMoved(ri, c))
|
result = newTree(nkStmtList, snk, genWasMoved(ri, c))
|
||||||
else:
|
else:
|
||||||
|
|
@ -634,22 +639,22 @@ proc moveOrCopy(dest, ri: PNode; c: var Con): PNode =
|
||||||
if ri.len > 0 and isDangerousSeq(ri.typ):
|
if ri.len > 0 and isDangerousSeq(ri.typ):
|
||||||
result = genCopy(c, dest, ri)
|
result = genCopy(c, dest, ri)
|
||||||
else:
|
else:
|
||||||
result = genSink(c, dest, ri)
|
result = genSinkOrMemMove(c, dest, ri, isFirstWrite)
|
||||||
result.add p(ri, c, consumed)
|
result.add p(ri, c, consumed)
|
||||||
of nkObjConstr, nkTupleConstr, nkClosure, nkCharLit..nkNilLit:
|
of nkObjConstr, nkTupleConstr, nkClosure, nkCharLit..nkNilLit:
|
||||||
result = genSink(c, dest, ri)
|
result = genSinkOrMemMove(c, dest, ri, isFirstWrite)
|
||||||
result.add p(ri, c, consumed)
|
result.add p(ri, c, consumed)
|
||||||
of nkSym:
|
of nkSym:
|
||||||
if isSinkParam(ri.sym):
|
if isSinkParam(ri.sym):
|
||||||
# Rule 3: `=sink`(x, z); wasMoved(z)
|
# Rule 3: `=sink`(x, z); wasMoved(z)
|
||||||
sinkParamIsLastReadCheck(c, ri)
|
sinkParamIsLastReadCheck(c, ri)
|
||||||
var snk = genSink(c, dest, ri)
|
var snk = genSinkOrMemMove(c, dest, ri, isFirstWrite)
|
||||||
snk.add ri
|
snk.add ri
|
||||||
result = newTree(nkStmtList, snk, genWasMoved(ri, c))
|
result = newTree(nkStmtList, snk, genWasMoved(ri, c))
|
||||||
elif ri.sym.kind != skParam and ri.sym.owner == c.owner and
|
elif ri.sym.kind != skParam and ri.sym.owner == c.owner and
|
||||||
isLastRead(ri, c) and canBeMoved(c, dest.typ):
|
isLastRead(ri, c) and canBeMoved(c, dest.typ):
|
||||||
# Rule 3: `=sink`(x, z); wasMoved(z)
|
# Rule 3: `=sink`(x, z); wasMoved(z)
|
||||||
var snk = genSink(c, dest, ri)
|
var snk = genSinkOrMemMove(c, dest, ri, isFirstWrite)
|
||||||
snk.add ri
|
snk.add ri
|
||||||
result = newTree(nkStmtList, snk, genWasMoved(ri, c))
|
result = newTree(nkStmtList, snk, genWasMoved(ri, c))
|
||||||
else:
|
else:
|
||||||
|
|
@ -657,30 +662,30 @@ proc moveOrCopy(dest, ri: PNode; c: var Con): PNode =
|
||||||
result.add p(ri, c, consumed)
|
result.add p(ri, c, consumed)
|
||||||
of nkHiddenSubConv, nkHiddenStdConv, nkConv:
|
of nkHiddenSubConv, nkHiddenStdConv, nkConv:
|
||||||
when false:
|
when false:
|
||||||
result = moveOrCopy(dest, ri[1], c)
|
result = moveOrCopy(dest, ri[1], c, isFirstWrite)
|
||||||
if not sameType(ri.typ, ri[1].typ):
|
if not sameType(ri.typ, ri[1].typ):
|
||||||
let copyRi = copyTree(ri)
|
let copyRi = copyTree(ri)
|
||||||
copyRi[1] = result[^1]
|
copyRi[1] = result[^1]
|
||||||
result[^1] = copyRi
|
result[^1] = copyRi
|
||||||
else:
|
else:
|
||||||
result = genSink(c, dest, ri)
|
result = genSinkOrMemMove(c, dest, ri, isFirstWrite)
|
||||||
result.add p(ri, c, sinkArg)
|
result.add p(ri, c, sinkArg)
|
||||||
of nkObjDownConv, nkObjUpConv:
|
of nkObjDownConv, nkObjUpConv:
|
||||||
when false:
|
when false:
|
||||||
result = moveOrCopy(dest, ri[0], c)
|
result = moveOrCopy(dest, ri[0], c, isFirstWrite)
|
||||||
let copyRi = copyTree(ri)
|
let copyRi = copyTree(ri)
|
||||||
copyRi[0] = result[^1]
|
copyRi[0] = result[^1]
|
||||||
result[^1] = copyRi
|
result[^1] = copyRi
|
||||||
else:
|
else:
|
||||||
result = genSink(c, dest, ri)
|
result = genSinkOrMemMove(c, dest, ri, isFirstWrite)
|
||||||
result.add p(ri, c, sinkArg)
|
result.add p(ri, c, sinkArg)
|
||||||
of nkStmtListExpr, nkBlockExpr, nkIfExpr, nkCaseStmt:
|
of nkStmtListExpr, nkBlockExpr, nkIfExpr, nkCaseStmt:
|
||||||
handleNested(ri): moveOrCopy(dest, node, c)
|
handleNested(ri): moveOrCopy(dest, node, c, isFirstWrite)
|
||||||
else:
|
else:
|
||||||
if isAnalysableFieldAccess(ri, c.owner) and isLastRead(ri, c) and
|
if isAnalysableFieldAccess(ri, c.owner) and isLastRead(ri, c) and
|
||||||
canBeMoved(c, dest.typ):
|
canBeMoved(c, dest.typ):
|
||||||
# Rule 3: `=sink`(x, z); wasMoved(z)
|
# Rule 3: `=sink`(x, z); wasMoved(z)
|
||||||
var snk = genSink(c, dest, ri)
|
var snk = genSinkOrMemMove(c, dest, ri, isFirstWrite)
|
||||||
snk.add ri
|
snk.add ri
|
||||||
result = newTree(nkStmtList, snk, genWasMoved(ri, c))
|
result = newTree(nkStmtList, snk, genWasMoved(ri, c))
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -253,13 +253,6 @@ proc considerUserDefinedOp(c: var TLiftCtx; t: PType; body, x, y: PNode): bool =
|
||||||
body.add newDeepCopyCall(op, x, y)
|
body.add newDeepCopyCall(op, x, y)
|
||||||
result = true
|
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 =
|
proc declareCounter(c: var TLiftCtx; body: PNode; first: BiggestInt): PNode =
|
||||||
var temp = newSym(skTemp, getIdent(c.g.cache, lowerings.genPrefix), c.fn, c.info)
|
var temp = newSym(skTemp, getIdent(c.g.cache, lowerings.genPrefix), c.fn, c.info)
|
||||||
temp.typ = getSysType(c.g, body.info, tyInt)
|
temp.typ = getSysType(c.g, body.info, tyInt)
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,13 @@ proc addVar*(father, v: PNode) =
|
||||||
vpart[2] = vpart[1]
|
vpart[2] = vpart[1]
|
||||||
father.add vpart
|
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 =
|
proc newAsgnStmt*(le, ri: PNode): PNode =
|
||||||
result = newNodeI(nkAsgn, le.info, 2)
|
result = newNodeI(nkAsgn, le.info, 2)
|
||||||
result[0] = le
|
result[0] = le
|
||||||
|
|
@ -63,10 +70,9 @@ proc lowerTupleUnpacking*(g: ModuleGraph; n: PNode; owner: PSym): PNode =
|
||||||
|
|
||||||
var v = newNodeI(nkVarSection, value.info)
|
var v = newNodeI(nkVarSection, value.info)
|
||||||
let tempAsNode = newSymNode(temp)
|
let tempAsNode = newSymNode(temp)
|
||||||
v.addVar(tempAsNode)
|
v.addVar(tempAsNode, value)
|
||||||
result.add(v)
|
result.add(v)
|
||||||
|
|
||||||
result.add newAsgnStmt(tempAsNode, value)
|
|
||||||
for i in 0..<n.len-2:
|
for i in 0..<n.len-2:
|
||||||
if n[i].kind == nkSym: v.addVar(n[i])
|
if n[i].kind == nkSym: v.addVar(n[i])
|
||||||
result.add newAsgnStmt(n[i], newTupleAccess(g, tempAsNode, i))
|
result.add newAsgnStmt(n[i], newTupleAccess(g, tempAsNode, i))
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ proc test(): auto =
|
||||||
var (a, b, _) = test()
|
var (a, b, _) = test()
|
||||||
|
|
||||||
doAssert assign_counter == 0
|
doAssert assign_counter == 0
|
||||||
doAssert sink_counter == 6
|
doAssert sink_counter == 3
|
||||||
|
|
||||||
# bug #11510
|
# bug #11510
|
||||||
proc main =
|
proc main =
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue