moved crates in lib/ to src/, renamed crates, modified some files' text (#660)
moved crates in lib/ to src/, renamed crates, modified some files' text (#660)
This commit is contained in:
392
cranelift/codegen/meta-python/semantics/test_elaborate.py
Normal file
392
cranelift/codegen/meta-python/semantics/test_elaborate.py
Normal file
@@ -0,0 +1,392 @@
|
||||
from __future__ import absolute_import
|
||||
from base.instructions import vselect, vsplit, vconcat, iconst, iadd, bint
|
||||
from base.instructions import b1, icmp, ireduce, iadd_cout
|
||||
from base.immediates import intcc, imm64
|
||||
from base.types import i64, i8, b32, i32, i16, f32
|
||||
from cdsl.typevar import TypeVar
|
||||
from cdsl.ast import Var
|
||||
from cdsl.xform import Rtl
|
||||
from unittest import TestCase
|
||||
from .elaborate import elaborate
|
||||
from .primitives import prim_to_bv, bvsplit, prim_from_bv, bvconcat, bvadd, \
|
||||
bvult, bv_from_imm64, bvite
|
||||
import base.semantics # noqa
|
||||
|
||||
|
||||
def concrete_rtls_eq(r1, r2):
|
||||
# type: (Rtl, Rtl) -> bool
|
||||
"""
|
||||
Check whether 2 concrete Rtls are equivalent. That is:
|
||||
1) They are structurally the same (i.e. there is a substitution between
|
||||
them)
|
||||
2) Corresponding Vars between them have the same singleton type.
|
||||
"""
|
||||
assert r1.is_concrete()
|
||||
assert r2.is_concrete()
|
||||
|
||||
s = r1.substitution(r2, {})
|
||||
|
||||
if s is None:
|
||||
return False
|
||||
|
||||
for (v, v1) in s.items():
|
||||
if v.get_typevar().singleton_type() !=\
|
||||
v1.get_typevar().singleton_type():
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
class TestCleanupConcreteRtl(TestCase):
|
||||
"""
|
||||
Test cleanup_concrete_rtl(). cleanup_concrete_rtl() should take Rtls for
|
||||
which we can infer a single concrete typing, and update the TypeVars
|
||||
in-place to singleton TVs.
|
||||
"""
|
||||
def test_cleanup_concrete_rtl(self):
|
||||
# type: () -> None
|
||||
typ = i64.by(4)
|
||||
x = Var('x')
|
||||
lo = Var('lo')
|
||||
hi = Var('hi')
|
||||
|
||||
r = Rtl(
|
||||
(lo, hi) << vsplit(x),
|
||||
)
|
||||
r1 = r.copy({})
|
||||
s = r.substitution(r1, {})
|
||||
|
||||
s[x].set_typevar(TypeVar.singleton(typ))
|
||||
r1.cleanup_concrete_rtl()
|
||||
assert s is not None
|
||||
assert s[x].get_typevar().singleton_type() == typ
|
||||
assert s[lo].get_typevar().singleton_type() == i64.by(2)
|
||||
assert s[hi].get_typevar().singleton_type() == i64.by(2)
|
||||
|
||||
def test_cleanup_concrete_rtl_fail(self):
|
||||
# type: () -> None
|
||||
x = Var('x')
|
||||
lo = Var('lo')
|
||||
hi = Var('hi')
|
||||
r = Rtl(
|
||||
(lo, hi) << vsplit(x),
|
||||
)
|
||||
|
||||
with self.assertRaises(AssertionError):
|
||||
r.cleanup_concrete_rtl()
|
||||
|
||||
def test_cleanup_concrete_rtl_ireduce(self):
|
||||
# type: () -> None
|
||||
x = Var('x')
|
||||
y = Var('y')
|
||||
r = Rtl(
|
||||
y << ireduce(x),
|
||||
)
|
||||
r1 = r.copy({})
|
||||
s = r.substitution(r1, {})
|
||||
s[x].set_typevar(TypeVar.singleton(i8.by(2)))
|
||||
r1.cleanup_concrete_rtl()
|
||||
|
||||
assert s is not None
|
||||
assert s[x].get_typevar().singleton_type() == i8.by(2)
|
||||
assert s[y].get_typevar().singleton_type() == i8.by(2)
|
||||
|
||||
def test_cleanup_concrete_rtl_ireduce_bad(self):
|
||||
# type: () -> None
|
||||
x = Var('x')
|
||||
y = Var('y')
|
||||
x.set_typevar(TypeVar.singleton(i16.by(1)))
|
||||
r = Rtl(
|
||||
y << ireduce(x),
|
||||
)
|
||||
|
||||
with self.assertRaises(AssertionError):
|
||||
r.cleanup_concrete_rtl()
|
||||
|
||||
def test_vselect_icmpimm(self):
|
||||
# type: () -> None
|
||||
x = Var('x')
|
||||
y = Var('y')
|
||||
z = Var('z')
|
||||
w = Var('w')
|
||||
v = Var('v')
|
||||
zeroes = Var('zeroes')
|
||||
imm0 = Var("imm0")
|
||||
|
||||
r = Rtl(
|
||||
zeroes << iconst(imm0),
|
||||
y << icmp(intcc.eq, x, zeroes),
|
||||
v << vselect(y, z, w),
|
||||
)
|
||||
r1 = r.copy({})
|
||||
|
||||
s = r.substitution(r1, {})
|
||||
s[zeroes].set_typevar(TypeVar.singleton(i32.by(4)))
|
||||
s[z].set_typevar(TypeVar.singleton(f32.by(4)))
|
||||
|
||||
r1.cleanup_concrete_rtl()
|
||||
|
||||
assert s is not None
|
||||
assert s[zeroes].get_typevar().singleton_type() == i32.by(4)
|
||||
assert s[x].get_typevar().singleton_type() == i32.by(4)
|
||||
assert s[y].get_typevar().singleton_type() == b32.by(4)
|
||||
assert s[z].get_typevar().singleton_type() == f32.by(4)
|
||||
assert s[w].get_typevar().singleton_type() == f32.by(4)
|
||||
assert s[v].get_typevar().singleton_type() == f32.by(4)
|
||||
|
||||
def test_bint(self):
|
||||
# type: () -> None
|
||||
x = Var('x')
|
||||
y = Var('y')
|
||||
z = Var('z')
|
||||
w = Var('w')
|
||||
v = Var('v')
|
||||
u = Var('u')
|
||||
|
||||
r = Rtl(
|
||||
z << iadd(x, y),
|
||||
w << bint(v),
|
||||
u << iadd(z, w)
|
||||
)
|
||||
r1 = r.copy({})
|
||||
s = r.substitution(r1, {})
|
||||
|
||||
s[x].set_typevar(TypeVar.singleton(i32.by(8)))
|
||||
s[z].set_typevar(TypeVar.singleton(i32.by(8)))
|
||||
# TODO: Relax this to simd=True
|
||||
s[v].set_typevar(TypeVar('v', '', bools=(1, 1), simd=(8, 8)))
|
||||
r1.cleanup_concrete_rtl()
|
||||
|
||||
assert s is not None
|
||||
assert s[x].get_typevar().singleton_type() == i32.by(8)
|
||||
assert s[y].get_typevar().singleton_type() == i32.by(8)
|
||||
assert s[z].get_typevar().singleton_type() == i32.by(8)
|
||||
assert s[w].get_typevar().singleton_type() == i32.by(8)
|
||||
assert s[u].get_typevar().singleton_type() == i32.by(8)
|
||||
assert s[v].get_typevar().singleton_type() == b1.by(8)
|
||||
|
||||
|
||||
class TestElaborate(TestCase):
|
||||
"""
|
||||
Test semantics elaboration.
|
||||
"""
|
||||
def setUp(self):
|
||||
# type: () -> None
|
||||
self.v0 = Var("v0")
|
||||
self.v1 = Var("v1")
|
||||
self.v2 = Var("v2")
|
||||
self.v3 = Var("v3")
|
||||
self.v4 = Var("v4")
|
||||
self.v5 = Var("v5")
|
||||
self.v6 = Var("v6")
|
||||
self.v7 = Var("v7")
|
||||
self.v8 = Var("v8")
|
||||
self.v9 = Var("v9")
|
||||
self.imm0 = Var("imm0")
|
||||
self.IxN_nonscalar = TypeVar("IxN_nonscalar", "", ints=True,
|
||||
scalars=False, simd=True)
|
||||
self.TxN = TypeVar("TxN", "", ints=True, bools=True, floats=True,
|
||||
scalars=False, simd=True)
|
||||
self.b1 = TypeVar.singleton(b1)
|
||||
|
||||
def test_elaborate_vsplit(self):
|
||||
# type: () -> None
|
||||
i32.by(4) # Make sure i32x4 exists.
|
||||
i32.by(2) # Make sure i32x2 exists.
|
||||
r = Rtl(
|
||||
(self.v0, self.v1) << vsplit.i32x4(self.v2),
|
||||
)
|
||||
r.cleanup_concrete_rtl()
|
||||
sem = elaborate(r)
|
||||
bvx = Var('bvx')
|
||||
bvlo = Var('bvlo')
|
||||
bvhi = Var('bvhi')
|
||||
x = Var('x')
|
||||
lo = Var('lo')
|
||||
hi = Var('hi')
|
||||
|
||||
exp = Rtl(
|
||||
bvx << prim_to_bv.i32x4(x),
|
||||
(bvlo, bvhi) << bvsplit.bv128(bvx),
|
||||
lo << prim_from_bv.i32x2(bvlo),
|
||||
hi << prim_from_bv.i32x2(bvhi)
|
||||
)
|
||||
exp.cleanup_concrete_rtl()
|
||||
|
||||
assert concrete_rtls_eq(sem, exp)
|
||||
|
||||
def test_elaborate_vconcat(self):
|
||||
# type: () -> None
|
||||
i32.by(4) # Make sure i32x4 exists.
|
||||
i32.by(2) # Make sure i32x2 exists.
|
||||
r = Rtl(
|
||||
self.v0 << vconcat.i32x2(self.v1, self.v2),
|
||||
)
|
||||
r.cleanup_concrete_rtl()
|
||||
sem = elaborate(r)
|
||||
bvx = Var('bvx')
|
||||
bvlo = Var('bvlo')
|
||||
bvhi = Var('bvhi')
|
||||
x = Var('x')
|
||||
lo = Var('lo')
|
||||
hi = Var('hi')
|
||||
|
||||
exp = Rtl(
|
||||
bvlo << prim_to_bv.i32x2(lo),
|
||||
bvhi << prim_to_bv.i32x2(hi),
|
||||
bvx << bvconcat.bv64(bvlo, bvhi),
|
||||
x << prim_from_bv.i32x4(bvx)
|
||||
)
|
||||
exp.cleanup_concrete_rtl()
|
||||
|
||||
assert concrete_rtls_eq(sem, exp)
|
||||
|
||||
def test_elaborate_iadd_simple(self):
|
||||
# type: () -> None
|
||||
i32.by(2) # Make sure i32x2 exists.
|
||||
x = Var('x')
|
||||
y = Var('y')
|
||||
a = Var('a')
|
||||
bvx = Var('bvx')
|
||||
bvy = Var('bvy')
|
||||
bva = Var('bva')
|
||||
r = Rtl(
|
||||
a << iadd.i32(x, y),
|
||||
)
|
||||
r.cleanup_concrete_rtl()
|
||||
sem = elaborate(r)
|
||||
exp = Rtl(
|
||||
bvx << prim_to_bv.i32(x),
|
||||
bvy << prim_to_bv.i32(y),
|
||||
bva << bvadd.bv32(bvx, bvy),
|
||||
a << prim_from_bv.i32(bva)
|
||||
)
|
||||
exp.cleanup_concrete_rtl()
|
||||
|
||||
assert concrete_rtls_eq(sem, exp)
|
||||
|
||||
def test_elaborate_iadd_elaborate_1(self):
|
||||
# type: () -> None
|
||||
i32.by(2) # Make sure i32x2 exists.
|
||||
r = Rtl(
|
||||
self.v0 << iadd.i32x2(self.v1, self.v2),
|
||||
)
|
||||
r.cleanup_concrete_rtl()
|
||||
sem = elaborate(r)
|
||||
x = Var('x')
|
||||
y = Var('y')
|
||||
a = Var('a')
|
||||
bvx_1 = Var('bvx_1')
|
||||
bvx_2 = Var('bvx_2')
|
||||
bvx_5 = Var('bvx_5')
|
||||
bvlo_1 = Var('bvlo_1')
|
||||
bvlo_2 = Var('bvlo_2')
|
||||
bvhi_1 = Var('bvhi_1')
|
||||
bvhi_2 = Var('bvhi_2')
|
||||
|
||||
bva_3 = Var('bva_3')
|
||||
bva_4 = Var('bva_4')
|
||||
|
||||
exp = Rtl(
|
||||
bvx_1 << prim_to_bv.i32x2(x),
|
||||
(bvlo_1, bvhi_1) << bvsplit.bv64(bvx_1),
|
||||
bvx_2 << prim_to_bv.i32x2(y),
|
||||
(bvlo_2, bvhi_2) << bvsplit.bv64(bvx_2),
|
||||
bva_3 << bvadd.bv32(bvlo_1, bvlo_2),
|
||||
bva_4 << bvadd.bv32(bvhi_1, bvhi_2),
|
||||
bvx_5 << bvconcat.bv32(bva_3, bva_4),
|
||||
a << prim_from_bv.i32x2(bvx_5)
|
||||
)
|
||||
exp.cleanup_concrete_rtl()
|
||||
|
||||
assert concrete_rtls_eq(sem, exp)
|
||||
|
||||
def test_elaborate_iadd_elaborate_2(self):
|
||||
# type: () -> None
|
||||
i8.by(4) # Make sure i32x2 exists.
|
||||
r = Rtl(
|
||||
self.v0 << iadd.i8x4(self.v1, self.v2),
|
||||
)
|
||||
r.cleanup_concrete_rtl()
|
||||
|
||||
sem = elaborate(r)
|
||||
x = Var('x')
|
||||
y = Var('y')
|
||||
a = Var('a')
|
||||
bvx_1 = Var('bvx_1')
|
||||
bvx_2 = Var('bvx_2')
|
||||
bvx_5 = Var('bvx_5')
|
||||
bvx_10 = Var('bvx_10')
|
||||
bvx_15 = Var('bvx_15')
|
||||
|
||||
bvlo_1 = Var('bvlo_1')
|
||||
bvlo_2 = Var('bvlo_2')
|
||||
bvlo_6 = Var('bvlo_6')
|
||||
bvlo_7 = Var('bvlo_7')
|
||||
bvlo_11 = Var('bvlo_11')
|
||||
bvlo_12 = Var('bvlo_12')
|
||||
|
||||
bvhi_1 = Var('bvhi_1')
|
||||
bvhi_2 = Var('bvhi_2')
|
||||
bvhi_6 = Var('bvhi_6')
|
||||
bvhi_7 = Var('bvhi_7')
|
||||
bvhi_11 = Var('bvhi_11')
|
||||
bvhi_12 = Var('bvhi_12')
|
||||
|
||||
bva_8 = Var('bva_8')
|
||||
bva_9 = Var('bva_9')
|
||||
bva_13 = Var('bva_13')
|
||||
bva_14 = Var('bva_14')
|
||||
|
||||
exp = Rtl(
|
||||
bvx_1 << prim_to_bv.i8x4(x),
|
||||
(bvlo_1, bvhi_1) << bvsplit.bv32(bvx_1),
|
||||
bvx_2 << prim_to_bv.i8x4(y),
|
||||
(bvlo_2, bvhi_2) << bvsplit.bv32(bvx_2),
|
||||
(bvlo_6, bvhi_6) << bvsplit.bv16(bvlo_1),
|
||||
(bvlo_7, bvhi_7) << bvsplit.bv16(bvlo_2),
|
||||
bva_8 << bvadd.bv8(bvlo_6, bvlo_7),
|
||||
bva_9 << bvadd.bv8(bvhi_6, bvhi_7),
|
||||
bvx_10 << bvconcat.bv8(bva_8, bva_9),
|
||||
(bvlo_11, bvhi_11) << bvsplit.bv16(bvhi_1),
|
||||
(bvlo_12, bvhi_12) << bvsplit.bv16(bvhi_2),
|
||||
bva_13 << bvadd.bv8(bvlo_11, bvlo_12),
|
||||
bva_14 << bvadd.bv8(bvhi_11, bvhi_12),
|
||||
bvx_15 << bvconcat.bv8(bva_13, bva_14),
|
||||
bvx_5 << bvconcat.bv16(bvx_10, bvx_15),
|
||||
a << prim_from_bv.i8x4(bvx_5)
|
||||
)
|
||||
exp.cleanup_concrete_rtl()
|
||||
assert concrete_rtls_eq(sem, exp)
|
||||
|
||||
def test_elaborate_iadd_cout_simple(self):
|
||||
# type: () -> None
|
||||
x = Var('x')
|
||||
y = Var('y')
|
||||
a = Var('a')
|
||||
c_out = Var('c_out')
|
||||
bvc_out = Var('bvc_out')
|
||||
bc_out = Var('bc_out')
|
||||
bvx = Var('bvx')
|
||||
bvy = Var('bvy')
|
||||
bva = Var('bva')
|
||||
bvone = Var('bvone')
|
||||
bvzero = Var('bvzero')
|
||||
r = Rtl(
|
||||
(a, c_out) << iadd_cout.i32(x, y),
|
||||
)
|
||||
r.cleanup_concrete_rtl()
|
||||
sem = elaborate(r)
|
||||
exp = Rtl(
|
||||
bvx << prim_to_bv.i32(x),
|
||||
bvy << prim_to_bv.i32(y),
|
||||
bva << bvadd.bv32(bvx, bvy),
|
||||
bc_out << bvult.bv32(bva, bvx),
|
||||
bvone << bv_from_imm64(imm64(1)),
|
||||
bvzero << bv_from_imm64(imm64(0)),
|
||||
bvc_out << bvite(bc_out, bvone, bvzero),
|
||||
a << prim_from_bv.i32(bva),
|
||||
c_out << prim_from_bv.b1(bvc_out)
|
||||
)
|
||||
exp.cleanup_concrete_rtl()
|
||||
assert concrete_rtls_eq(sem, exp)
|
||||
Reference in New Issue
Block a user