* fix #16185 * fix test * fix comment * fix comment * better approach
This commit is contained in:
parent
5a43a20f53
commit
bb4b27a2ca
3 changed files with 126 additions and 61 deletions
|
|
@ -19,7 +19,7 @@ import
|
||||||
lineinfos, parampatterns, sighashes, liftdestructors, optimizer,
|
lineinfos, parampatterns, sighashes, liftdestructors, optimizer,
|
||||||
varpartitions
|
varpartitions
|
||||||
|
|
||||||
from trees import exprStructuralEquivalent, getRoot
|
from trees import exprStructuralEquivalent, getRoot, sameLocation
|
||||||
|
|
||||||
type
|
type
|
||||||
Scope = object # well we do scope-based memory management. \
|
Scope = object # well we do scope-based memory management. \
|
||||||
|
|
@ -969,6 +969,10 @@ proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode): PNode =
|
||||||
internalError(c.graph.config, n.info, "cannot inject destructors to node kind: " & $n.kind)
|
internalError(c.graph.config, n.info, "cannot inject destructors to node kind: " & $n.kind)
|
||||||
|
|
||||||
proc moveOrCopy(dest, ri: PNode; c: var Con; s: var Scope, isDecl = false): PNode =
|
proc moveOrCopy(dest, ri: PNode; c: var Con; s: var Scope, isDecl = false): PNode =
|
||||||
|
if sameLocation(dest, ri):
|
||||||
|
# rule (self-assignment-removal):
|
||||||
|
result = newNodeI(nkEmpty, dest.info)
|
||||||
|
else:
|
||||||
case ri.kind
|
case ri.kind
|
||||||
of nkCallKinds:
|
of nkCallKinds:
|
||||||
result = c.genSink(dest, p(ri, c, s, consumed), isDecl)
|
result = c.genSink(dest, p(ri, c, s, consumed), isDecl)
|
||||||
|
|
@ -996,10 +1000,7 @@ proc moveOrCopy(dest, ri: PNode; c: var Con; s: var Scope, isDecl = false): PNod
|
||||||
of nkObjConstr, nkTupleConstr, nkClosure, nkCharLit..nkNilLit:
|
of nkObjConstr, nkTupleConstr, nkClosure, nkCharLit..nkNilLit:
|
||||||
result = c.genSink(dest, p(ri, c, s, consumed), isDecl)
|
result = c.genSink(dest, p(ri, c, s, consumed), isDecl)
|
||||||
of nkSym:
|
of nkSym:
|
||||||
if dest.kind == nkSym and dest.sym == ri.sym:
|
if isSinkParam(ri.sym) and isLastRead(ri, c):
|
||||||
# rule (self-assignment-removal):
|
|
||||||
result = newNodeI(nkEmpty, dest.info)
|
|
||||||
elif isSinkParam(ri.sym) and isLastRead(ri, c):
|
|
||||||
# Rule 3: `=sink`(x, z); wasMoved(z)
|
# Rule 3: `=sink`(x, z); wasMoved(z)
|
||||||
let snk = c.genSink(dest, ri, isDecl)
|
let snk = c.genSink(dest, ri, isDecl)
|
||||||
result = newTree(nkStmtList, snk, c.genWasMoved(ri))
|
result = newTree(nkStmtList, snk, c.genWasMoved(ri))
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,21 @@ proc exprStructuralEquivalent*(a, b: PNode; strictSymEquality=false): bool =
|
||||||
strictSymEquality): return
|
strictSymEquality): return
|
||||||
result = true
|
result = true
|
||||||
|
|
||||||
|
proc sameLocation*(a, b: PNode): bool =
|
||||||
|
if a == b: true
|
||||||
|
elif a == nil or b == nil: false
|
||||||
|
elif a.kind == b.kind:
|
||||||
|
case a.kind:
|
||||||
|
of nkCheckedFieldExpr, nkDerefExpr, nkHiddenDeref,
|
||||||
|
nkAddr, nkHiddenAddr, nkObjDownConv, nkObjUpConv:
|
||||||
|
sameLocation(a[0], b[0])
|
||||||
|
of nkDotExpr, nkBracketExpr:
|
||||||
|
sameLocation(a[0], b[0]) and sameLocation(a[1], b[1])
|
||||||
|
of nkHiddenStdConv, nkHiddenSubConv: sameLocation(a[1], b[1])
|
||||||
|
of nkNone..nkNilLit: exprStructuralEquivalent(a, b, strictSymEquality = true)
|
||||||
|
else: false
|
||||||
|
else: false
|
||||||
|
|
||||||
proc sameTree*(a, b: PNode): bool =
|
proc sameTree*(a, b: PNode): bool =
|
||||||
if a == b:
|
if a == b:
|
||||||
result = true
|
result = true
|
||||||
|
|
|
||||||
|
|
@ -126,3 +126,52 @@ proc main =
|
||||||
echo avals.len, " ", rankdef.len
|
echo avals.len, " ", rankdef.len
|
||||||
|
|
||||||
main()
|
main()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
# Issue #16185, complex self-assingment elimination
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
type
|
||||||
|
CpuStorage*[T] = ref CpuStorageObj[T]
|
||||||
|
CpuStorageObj[T] = object
|
||||||
|
size*: int
|
||||||
|
raw_buffer*: ptr UncheckedArray[T]
|
||||||
|
Tensor[T] = object
|
||||||
|
buf*: CpuStorage[T]
|
||||||
|
TestObject = object
|
||||||
|
x: Tensor[float]
|
||||||
|
|
||||||
|
proc `=destroy`[T](s: var CpuStorageObj[T]) =
|
||||||
|
if s.raw_buffer != nil:
|
||||||
|
s.raw_buffer.deallocShared()
|
||||||
|
s.size = 0
|
||||||
|
s.raw_buffer = nil
|
||||||
|
|
||||||
|
proc `=`[T](a: var CpuStorageObj[T]; b: CpuStorageObj[T]) {.error.}
|
||||||
|
|
||||||
|
proc allocCpuStorage[T](s: var CpuStorage[T], size: int) =
|
||||||
|
new(s)
|
||||||
|
s.raw_buffer = cast[ptr UncheckedArray[T]](allocShared0(sizeof(T) * size))
|
||||||
|
s.size = size
|
||||||
|
|
||||||
|
proc newTensor[T](size: int): Tensor[T] =
|
||||||
|
allocCpuStorage(result.buf, size)
|
||||||
|
|
||||||
|
proc `[]`[T](t: Tensor[T], idx: int): T = t.buf.raw_buffer[idx]
|
||||||
|
proc `[]=`[T](t: Tensor[T], idx: int, val: T) = t.buf.raw_buffer[idx] = val
|
||||||
|
|
||||||
|
proc toTensor[T](s: seq[T]): Tensor[T] =
|
||||||
|
result = newTensor[T](s.len)
|
||||||
|
for i, x in s:
|
||||||
|
result[i] = x
|
||||||
|
|
||||||
|
proc main2() =
|
||||||
|
var t: TestObject
|
||||||
|
t.x = toTensor(@[1.0, 2, 3, 4])
|
||||||
|
t.x = t.x
|
||||||
|
doAssert(t.x.buf != nil) # self-assignment above should be eliminated
|
||||||
|
|
||||||
|
main2()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue