Skip to content

Commit 5b5cd7f

Browse files
authored
fixes inefficient codegen for field return (#24874)
fixes #23395 fixes #23395
1 parent 8e57a9f commit 5b5cd7f

File tree

1 file changed

+26
-3
lines changed

1 file changed

+26
-3
lines changed

compiler/injectdestructors.nim

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ when false:
100100
proc 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

173173
proc 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+
11431162
proc 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

Comments
 (0)