ARC now capable of custom extra alignment. Ref, closure and seq support. (#15697)
This commit is contained in:
parent
732ddc02da
commit
0956a99537
11 changed files with 273 additions and 77 deletions
146
tests/arc/thard_alignment.nim
Normal file
146
tests/arc/thard_alignment.nim
Normal file
|
|
@ -0,0 +1,146 @@
|
|||
discard """
|
||||
disabled: "arm64"
|
||||
cmd: "nim c --gc:arc $file"
|
||||
output: "y"
|
||||
"""
|
||||
|
||||
{.passC: "-march=native".}
|
||||
|
||||
proc isAlignedCheck(p: pointer, alignment: int) =
|
||||
doAssert (cast[uint](p) and uint(alignment - 1)) == 0
|
||||
|
||||
proc isAlignedCheck[T](p: ref T, alignment: int) =
|
||||
isAlignedCheck(cast[pointer](p), alignment)
|
||||
|
||||
type
|
||||
m256d {.importc: "__m256d", header: "immintrin.h".} = object
|
||||
|
||||
proc set1(x: float): m256d {.importc: "_mm256_set1_pd", header: "immintrin.h".}
|
||||
func `+`(a,b: m256d): m256d {.importc: "_mm256_add_pd", header: "immintrin.h".}
|
||||
proc `$`(a: m256d): string =
|
||||
result = $(cast[ptr float](a.unsafeAddr)[])
|
||||
|
||||
|
||||
var res: seq[seq[m256d]]
|
||||
|
||||
for _ in 1..1000:
|
||||
var x = newSeq[m256d](1)
|
||||
x[0] = set1(1.0) # test if operation causes segfault
|
||||
isAlignedCheck(x[0].addr, alignof(m256d))
|
||||
res.add x
|
||||
|
||||
var res2: seq[m256d]
|
||||
for i in 1..10000:
|
||||
res2.setLen(res2.len + 1) # check if realloc works
|
||||
isAlignedCheck(res2[0].addr, alignof(m256d))
|
||||
|
||||
proc lambdaGen(a, b: float, z: ref m256d) : auto =
|
||||
var x1 = new(m256d)
|
||||
var x2 = new(m256d)
|
||||
isAlignedCheck(x1, alignof(m256d))
|
||||
isAlignedCheck(x2, alignof(m256d))
|
||||
x1[] = set1(2.0 + a)
|
||||
x2[] = set1(-23.0 - b)
|
||||
let capturingLambda = proc(x: ref m256d): ref m256d =
|
||||
var cc = new(m256d)
|
||||
var bb = new(m256d)
|
||||
isAlignedCheck(x1, alignof(m256d))
|
||||
isAlignedCheck(x2, alignof(m256d))
|
||||
isAlignedCheck(cc, alignof(m256d))
|
||||
isAlignedCheck(bb, alignof(m256d))
|
||||
isAlignedCheck(z, alignof(m256d))
|
||||
|
||||
cc[] = x1[] + x1[] + z[]
|
||||
bb[] = x2[] + set1(12.5) + z[]
|
||||
|
||||
result = new(m256d)
|
||||
isAlignedCheck(result, alignof(m256d))
|
||||
result[] = cc[] + bb[] + x[]
|
||||
|
||||
return capturingLambda
|
||||
|
||||
var xx = new(m256d)
|
||||
xx[] = set1(10)
|
||||
isAlignedCheck(xx, alignOf(m256d))
|
||||
|
||||
let f1 = lambdaGen(2.0 , 2.221, xx)
|
||||
let f2 = lambdaGen(-1.226 , 3.5, xx)
|
||||
isAlignedCheck(f1(xx), alignOf(m256d))
|
||||
isAlignedCheck(f2(xx), alignOf(m256d))
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
type
|
||||
MyAligned = object of RootObj
|
||||
a{.align: 128.}: float
|
||||
|
||||
|
||||
var f: MyAligned
|
||||
isAlignedCheck(f.addr, MyAligned.alignOf)
|
||||
|
||||
var fref = new(MyAligned)
|
||||
isAlignedCheck(fref, MyAligned.alignOf)
|
||||
|
||||
var fs: seq[MyAligned]
|
||||
var fr: seq[RootRef]
|
||||
|
||||
for i in 0..1000:
|
||||
fs.add MyAligned()
|
||||
isAlignedCheck(fs[^1].addr, MyAligned.alignOf)
|
||||
fs[^1].a = i.float
|
||||
|
||||
fr.add new(MyAligned)
|
||||
isAlignedCheck(fr[^1], MyAligned.alignOf)
|
||||
((ref MyAligned)fr[^1])[].a = i.float
|
||||
|
||||
for i in 0..1000:
|
||||
doAssert(fs[i].a == i.float)
|
||||
doAssert(((ref MyAligned)fr[i]).a == i.float)
|
||||
|
||||
|
||||
proc lambdaTest2(a: MyAligned, z: ref MyAligned): auto =
|
||||
var x1: MyAligned
|
||||
x1.a = a.a + z.a
|
||||
var x2: MyAligned
|
||||
x2.a = a.a - z.a
|
||||
let capturingLambda = proc(x: MyAligned): MyAligned =
|
||||
var cc: MyAligned
|
||||
var bb: MyAligned
|
||||
isAlignedCheck(x1.addr, MyAligned.alignOf)
|
||||
isAlignedCheck(x2.addr, MyAligned.alignOf)
|
||||
isAlignedCheck(cc.addr, MyAligned.alignOf)
|
||||
isAlignedCheck(bb.addr, MyAligned.alignOf)
|
||||
isAlignedCheck(z, MyAligned.alignOf)
|
||||
|
||||
cc.a = x1.a + x1.a + z.a
|
||||
bb.a = x2.a - z.a
|
||||
|
||||
isAlignedCheck(result.addr, MyAligned.alignOf)
|
||||
result.a = cc.a + bb.a + x2.a
|
||||
|
||||
return capturingLambda
|
||||
|
||||
|
||||
let q1 = lambdaTest2(MyAligned(a: 1.0), (ref MyAligned)(a: 2.0))
|
||||
let q2 = lambdaTest2(MyAligned( a: -1.0), (ref MyAligned)(a: -2.0))
|
||||
|
||||
isAlignedCheck(rawEnv(q1), MyAligned.alignOf)
|
||||
isAlignedCheck(rawEnv(q2), MyAligned.alignOf)
|
||||
discard q1(MyAligned(a: 1.0))
|
||||
discard q2(MyAligned(a: -1.0))
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
block:
|
||||
var s: seq[seq[MyAligned]]
|
||||
for len in 0..128:
|
||||
s.add newSeq[MyAligned](len)
|
||||
for i in 0..<len:
|
||||
s[^1][i] = MyAligned(a: 1.0)
|
||||
|
||||
if len > 0:
|
||||
isAlignedCheck(s[^1][0].addr, MyAligned.alignOf)
|
||||
|
||||
echo "y"
|
||||
Loading…
Add table
Add a link
Reference in a new issue