Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: m-labs/artiq
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: a579b105b6a1
Choose a base ref
...
head repository: m-labs/artiq
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 7e9df82e372b
Choose a head ref
  • 3 commits
  • 3 files changed
  • 1 contributor

Commits on Aug 28, 2014

  1. Copy the full SHA
    a861226 View commit details
  2. Copy the full SHA
    841e7cc View commit details
  3. Copy the full SHA
    7e9df82 View commit details
Showing with 103 additions and 18 deletions.
  1. +3 −2 artiq/compiler/ir.py
  2. +99 −15 artiq/compiler/ir_values.py
  3. +1 −1 artiq/devices/runtime.py
5 changes: 3 additions & 2 deletions artiq/compiler/ir.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from llvm import core as lc
from llvm import passes as lp

from artiq.compiler import ir_infer_types, ir_ast_body
from artiq.compiler import ir_infer_types, ir_ast_body, ir_values

def compile_function(module, env, funcdef):
function_type = lc.Type.function(lc.Type.void(), [])
@@ -18,7 +18,8 @@ def compile_function(module, env, funcdef):

def get_runtime_binary(env, funcdef):
module = lc.Module.new("main")
env.set_module(module)
env.init_module(module)
ir_values.init_module(module)

compile_function(module, env, funcdef)

114 changes: 99 additions & 15 deletions artiq/compiler/ir_values.py
Original file line number Diff line number Diff line change
@@ -188,6 +188,22 @@ def o_bool(self, builder):

# Fraction type

def _gcd64(builder, a, b):
gcd_f = builder.module.get_function_named("__gcd64")
return builder.call(gcd_f, [a, b])

def _frac_normalize(builder, numerator, denominator):
gcd = _gcd64(numerator, denominator)
numerator = builder.sdiv(numerator, gcd)
denominator = builder.sdiv(denominator, gcd)
return numerator, denominator

def _frac_make_ssa(builder, numerator, denominator):
value = lc.Constant.undef(lc.Type.vector(lc.Type.int(64), 2))
value = builder.insert_element(value, numerator, lc.Constant.int(lc.Type.int(), 0))
value = builder.insert_element(value, denominator, lc.Constant.int(lc.Type.int(), 1))
return value

class VFraction(_Value):
def get_llvm_type(self):
return lc.Type.vector(lc.Type.int(64), 2)
@@ -202,17 +218,20 @@ def merge(self, other):
if not isinstance(other, VFraction):
raise TypeError

def _simplify(self, builder):
pass # TODO
def _nd(self, builder, invert=False):
ssa_value = self.get_ssa_value(builder)
numerator = builder.extract_element(ssa_value, lc.Constant.int(lc.Type.int(), 0))
denominator = builder.extract_element(ssa_value, lc.Constant.int(lc.Type.int(), 1))
if invert:
return denominator, numerator
else:
return numerator, denominator

def set_value_nd(self, builder, numerator, denominator):
numerator = numerator.o_int64(builder).get_ssa_value(builder)
denominator = denominator.o_int64(builder).get_ssa_value(builder)
value = lc.Constant.undef(lc.Type.vector(lc.Type.int(64), 2))
value = builder.insert_element(value, numerator, lc.Constant.int(lc.Type.int(), 0))
value = builder.insert_element(value, denominator, lc.Constant.int(lc.Type.int(), 1))
self.set_ssa_value(builder, value)
self._simplify(builder)
numerator, denominator = _frac_normalize(builder, numerator, denominator)
self.set_ssa_value(builder, _frac_make_ssa(builder, numerator, denominator))

def set_value(self, builder, n):
if not isinstance(n, VFraction):
@@ -232,8 +251,7 @@ def o_intx(self, target_bits, builder):
return VInt(target_bits)
else:
r = VInt(64)
numerator = builder.extract_element(self.get_ssa_value(builder), lc.Constant.int(lc.Type.int(), 0))
denominator = builder.extract_element(self.get_ssa_value(builder), lc.Constant.int(lc.Type.int(), 1))
numerator, denominator = self._nd(builder)
r.set_ssa_value(builder, builder.sdiv(numerator, denominator))
return r.o_intx(target_bits, builder)

@@ -242,14 +260,13 @@ def o_roundx(self, target_bits, builder):
return VInt(target_bits)
else:
r = VInt(64)
numerator = builder.extract_element(self.get_ssa_value(builder), lc.Constant.int(lc.Type.int(), 0))
denominator = builder.extract_element(self.get_ssa_value(builder), lc.Constant.int(lc.Type.int(), 1))
numerator, denominator = self._nd(builder)
h_denominator = builder.ashr(denominator, lc.Constant.int(lc.Type.int(), 1))
r_numerator = builder.add(numerator, h_denominator)
r.set_ssa_value(builder, builder.sdiv(r_numerator, denominator))
return r.o_intx(target_bits, builder)

def _o_eq_inv(self, other, builder, invert):
def _o_eq_inv(self, other, builder, ne):
if isinstance(other, VFraction):
r = VBool()
if builder is not None:
@@ -259,7 +276,7 @@ def _o_eq_inv(self, other, builder, invert):
eo = builder.extract_element(other.get_ssa_value(builder), lc.Constant.int(lc.Type.int(), i))
ee.append(builder.icmp(lc.ICMP_EQ, es, eo))
ssa_r = builder.and_(ee[0], ee[1])
if invert:
if ne:
ssa_r = builder.xor(ssa_r, lc.Constant.int(lc.Type.int(1), 1))
r.set_ssa_value(builder, ssa_r)
return r
@@ -272,6 +289,68 @@ def o_eq(self, other, builder):
def o_ne(self, other, builder):
return self._o_eq_inv(other, builder, True)

def _o_muldiv(self, other, builder, div, invert=False):
r = VFraction()
if isinstance(other, VInt):
if builder is None:
return r
else:
numerator, denominator = self._nd(builder, invert)
i = other.get_ssa_value(builder)
if div:
gcd = _gcd64(i, numerator)
i = builder.sdiv(i, gcd)
numerator = builder.sdiv(numerator, gcd)
denominator = builder.mul(denominator, i)
else:
gcd = _gcd64(i, denominator)
i = builder.sdiv(i, gcd)
denominator = builder.sdiv(denominator, gcd)
numerator = builder.mul(numerator, i)
self.set_ssa_value(builder, _frac_make_ssa(builder, numerator, denominator))
elif isinstance(other, VFraction):
if builder is None:
return r
else:
numerator, denominator = self._nd(builder, invert)
onumerator, odenominator = other._nd(builder)
if div:
numerator = builder.mul(numerator, odenominator)
denominator = builder.mul(denominator, onumerator)
else:
numerator = builder.mul(numerator, onumerator)
denominator = builder.mul(denominator, odenominator)
numerator, denominator = _frac_normalize(builder, numerator, denominator)
self.set_ssa_value(builder, _frac_make_ssa(builder, numerator, denominator))
else:
return NotImplemented

def o_mul(self, other, builder):
return self._o_muldiv(other, builder, False)

def o_truediv(self, other, builder):
return self._o_muldiv(other, builder, True)

def or_mul(self, other, builder):
return self._o_muldiv(other, builder, False)

def or_truediv(self, other, builder):
return self._o_muldiv(other, builder, False, True)

def o_floordiv(self, other, builder):
r = self.o_truediv(other, builder)
if r is NotImplemented:
return r
else:
return r.o_int(builder)

def or_floordiv(self, other, builder):
r = self.or_truediv(other, builder)
if r is NotImplemented:
return r
else:
return r.o_int(builder)

# Operators

def _make_unary_operator(op_name):
@@ -293,11 +372,11 @@ def op(l, r, builder):
result = opf(r, builder)
if result is NotImplemented:
try:
ropf = getattr(l, "or_"+op_name)
ropf = getattr(r, "or_"+op_name)
except AttributeError:
result = NotImplemented
else:
result = ropf(r, builder)
result = ropf(l, builder)
if result is NotImplemented:
raise TypeError("Unsupported operand types for {}: {} and {}".format(
op_name, type(l).__name__, type(r).__name__))
@@ -319,3 +398,8 @@ def _make_operators():
return SimpleNamespace(**d)

operators = _make_operators()

def init_module(module):
func_type = lc.Type.function(lc.Type.int(64),
[lc.Type.int(64), lc.Type.int(64)])
module.add_function(func_type, "__gcd64")
2 changes: 1 addition & 1 deletion artiq/devices/runtime.py
Original file line number Diff line number Diff line change
@@ -40,7 +40,7 @@ def _str_to_functype(s):
return var_arg_fixcount, lc.Type.function(type_ret, type_args, var_arg=var_arg_fixcount is not None)

class LinkInterface:
def set_module(self, module):
def init_module(self, module):
self.module = module
self.var_arg_fixcount = dict()
for func_name, func_type_str in _syscalls.items():