fixes cast expressions introduces unnecessary copies (#24004)

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>
This commit is contained in:
ringabout
2024-08-24 02:07:00 +08:00
committed by GitHub
parent 446501b53b
commit 4ef06a5cc5
3 changed files with 21 additions and 44 deletions

View File

@@ -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:
@@ -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)

View File

@@ -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))

View File

@@ -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 ------------------------
'''