@@ -100,6 +100,7 @@ when false:
100100proc isLastReadImpl (n: PNode ; c: var Con ; scope: var Scope ): bool =
101101 let root = parampatterns.exprRoot (n, allowCalls= false )
102102 if root == nil : return false
103+ elif sfSingleUsedTemp in root.flags: return true
103104
104105 var s = addr (scope)
105106 while s != nil :
@@ -167,8 +168,7 @@ proc isLastRead(n: PNode; c: var Con; s: var Scope): bool =
167168 if not hasDestructor (c, n.typ) and (n.typ.kind != tyObject or isTrival (getAttachedOp (c.graph, n.typ, attachedAsgn))): return true
168169
169170 let m = skipConvDfa (n)
170- result = (m.kind == nkSym and sfSingleUsedTemp in m.sym.flags) or
171- isLastReadImpl (n, c, s)
171+ result = isLastReadImpl (n, c, s)
172172
173173proc isFirstWrite (n: PNode ; c: var Con ): bool =
174174 let m = skipConvDfa (n)
@@ -1140,6 +1140,25 @@ proc genFieldAccessSideEffects(c: var Con; s: var Scope; dest, ri: PNode; flags:
11401140 var snk = c.genSink (s, dest, newAccess, flags)
11411141 result = newTree (nkStmtList, v, snk, c.genWasMoved (newAccess))
11421142
1143+ proc ownsData (c: var Con ; s: var Scope ; orig: PNode ; flags: set [MoveOrCopyFlag ]): PNode =
1144+ var n = orig
1145+ while true :
1146+ case n.kind
1147+ of nkDotExpr, nkCheckedFieldExpr, nkBracketExpr:
1148+ n = n[0 ]
1149+ else :
1150+ break
1151+ if n.kind in nkCallKinds and n.typ != nil and hasDestructor (c, n.typ):
1152+ result = newNodeIT (nkStmtListExpr, orig.info, orig.typ)
1153+ let tmp = c.getTemp (s, n.typ, n.info)
1154+ tmp.sym.flags.incl sfSingleUsedTemp
1155+ result .add newTree (nkFastAsgn, tmp, copyTree (n))
1156+ s.final.add c.genDestroy (tmp)
1157+ n[] = tmp[]
1158+ result .add copyTree (orig)
1159+ else :
1160+ result = nil
1161+
11431162proc moveOrCopy (dest, ri: PNode ; c: var Con ; s: var Scope , flags: set [MoveOrCopyFlag ] = {}): PNode =
11441163 var ri = ri
11451164 var isEnsureMove = 0
@@ -1226,7 +1245,11 @@ proc moveOrCopy(dest, ri: PNode; c: var Con; s: var Scope, flags: set[MoveOrCopy
12261245 of nkRaiseStmt:
12271246 result = pRaiseStmt (ri, c, s)
12281247 else :
1229- if isAnalysableFieldAccess (ri, c.owner) and isLastRead (ri, c, s) and
1248+ let isOwnsData = ownsData (c, s, ri2, flags)
1249+
1250+ if isOwnsData != nil :
1251+ result = moveOrCopy (dest, isOwnsData, c, s, flags)
1252+ elif isAnalysableFieldAccess (ri, c.owner) and isLastRead (ri, c, s) and
12301253 canBeMoved (c, dest.typ):
12311254 # Rule 3: `=sink`(x, z); wasMoved(z)
12321255 let snk = c.genSink (s, dest, ri, flags)
0 commit comments