Skip to content

Commit

Permalink
fixes cast expressions introduces unnecessary copies (#24004)
Browse files Browse the repository at this point in the history
It speeds up
```nim
proc foo =
  let piece = cast[seq[char]](newSeqUninit[uint8](5220600386'i64))

foo()
```

Notes that `cast[ref](...)` is excluded because we need to keep the ref
alive if the parameter is something with pointer types (e.g.
`cast[ref](pointer)`or `cast[ref](makePointer(...))`)

---------

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
  • Loading branch information
ringabout and Araq authored Aug 23, 2024
1 parent 446501b commit 4ef06a5
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 44 deletions.
5 changes: 4 additions & 1 deletion compiler/injectdestructors.nim
Original file line number Diff line number Diff line change
Expand Up @@ -501,7 +501,7 @@ proc containsConstSeq(n: PNode): bool =
return true
result = false
case n.kind
of nkExprEqExpr, nkExprColonExpr, nkHiddenStdConv, nkHiddenSubConv:
of nkExprEqExpr, nkExprColonExpr, nkHiddenStdConv, nkHiddenSubConv, nkCast:
result = containsConstSeq(n[1])
of nkObjConstr, nkClosure:
for i in 1..<n.len:
Expand Down Expand Up @@ -829,6 +829,9 @@ proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode; tmpFlags = {sfSing
elif n.kind in {nkObjDownConv, nkObjUpConv}:
result = copyTree(n)
result[0] = p(n[0], c, s, sinkArg)
elif n.kind == nkCast and n.typ.skipTypes(abstractInst).kind in {tyString, tySequence}:
result = copyTree(n)
result[1] = p(n[1], c, s, sinkArg)
elif n.typ == nil:
# 'raise X' can be part of a 'case' expression. Deal with it here:
result = p(n, c, s, normal)
Expand Down
2 changes: 2 additions & 0 deletions tests/destructor/tatomicptrs.nim
Original file line number Diff line number Diff line change
Expand Up @@ -143,11 +143,13 @@ proc `=sink`*[T](m: var MySeq[T], m2: MySeq[T]) {.inline.} =
`=destroy`(m)
m.len = m2.len
m.data = m2.data
m.refcount = m2.refcount

proc len*[T](m: MySeq[T]): int {.inline.} = m.len

proc newMySeq*[T](size: int, initial_value: T): MySeq[T] =
result.len = size
result.refcount = 1
if size > 0:
result.data = cast[ptr UncheckedArray[T]](allocShared(sizeof(T) * size))

Expand Down
58 changes: 15 additions & 43 deletions tests/destructor/tv2_cast.nim
Original file line number Diff line number Diff line change
Expand Up @@ -10,69 +10,41 @@ destroying O1'''
var
data
:tmpD
:tmpD_1
:tmpD_2
data =
:tmpD = `=dup`(cast[string](
:tmpD_2 = encode(cast[seq[byte]](
:tmpD_1 = newString(100)
:tmpD_1))
:tmpD_2))
:tmpD
`=destroy`(:tmpD_2)
`=destroy_1`(:tmpD_1)
`=destroy_1`(data)
data = cast[string](encode(cast[seq[byte]](
:tmpD = newString(100)
:tmpD)))
`=destroy`(:tmpD)
`=destroy`(data)
-- end of expandArc ------------------------
--expandArc: main1
var
s
data
:tmpD
:tmpD_1
s = newString(100)
data =
:tmpD = `=dup`(cast[string](
:tmpD_1 = encode(toOpenArrayByte(s, 0, len(s) - 1))
:tmpD_1))
:tmpD
`=destroy`(:tmpD_1)
`=destroy_1`(data)
`=destroy_1`(s)
data = cast[string](encode(toOpenArrayByte(s, 0, len(s) - 1)))
`=destroy`(data)
`=destroy`(s)
-- end of expandArc ------------------------
--expandArc: main2
var
s
data
:tmpD
:tmpD_1
s = newSeq(100)
data =
:tmpD = `=dup`(cast[string](
:tmpD_1 = encode(s)
:tmpD_1))
:tmpD
`=destroy`(:tmpD_1)
`=destroy_1`(data)
`=destroy`(s)
data = cast[string](encode(s))
`=destroy`(data)
`=destroy_1`(s)
-- end of expandArc ------------------------
--expandArc: main3
var
data
:tmpD
:tmpD_1
:tmpD_2
data =
:tmpD = `=dup`(cast[string](
:tmpD_2 = encode do:
:tmpD_1 = newSeq(100)
:tmpD_1
:tmpD_2))
:tmpD
`=destroy`(:tmpD_2)
`=destroy`(:tmpD_1)
data = cast[string](encode do:
:tmpD = newSeq(100)
:tmpD)
`=destroy`(:tmpD)
`=destroy_1`(data)
-- end of expandArc ------------------------
'''
Expand Down

0 comments on commit 4ef06a5

Please sign in to comment.