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: 6f5332f8921a
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: 3ed852e077f8
Choose a head ref
  • 3 commits
  • 15 files changed
  • 1 contributor

Commits on Mar 28, 2016

  1. Commit missing parts of 6f5332f.

    whitequark committed Mar 28, 2016

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    f31249a View commit details
  2. compiler: allow specifying per-function "fast-math" flags.

    Fixes #351.
    whitequark committed Mar 28, 2016
    6

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    1038f13 View commit details
  3. Commit missing parts of 1d8b0d4.

    whitequark committed Mar 28, 2016
    Copy the full SHA
    3ed852e View commit details
4 changes: 3 additions & 1 deletion artiq/compiler/asttyped.py
Original file line number Diff line number Diff line change
@@ -30,7 +30,9 @@ class ClassDefT(ast.ClassDef):
class FunctionDefT(ast.FunctionDef, scoped):
_types = ("signature_type",)
class QuotedFunctionDefT(FunctionDefT):
pass
"""
:ivar flags: (set of str) Code generation flags (see :class:`ir.Function`).
"""
class ModuleT(ast.Module, scoped):
pass

6 changes: 4 additions & 2 deletions artiq/compiler/embedding.py
Original file line number Diff line number Diff line change
@@ -546,7 +546,7 @@ def _synthesizer(self, expanded_from=None):
value_map=self.value_map,
quote_function=self._quote_function)

def _quote_embedded_function(self, function):
def _quote_embedded_function(self, function, flags):
if not hasattr(function, "artiq_embedded"):
raise ValueError("{} is not an embedded function".format(repr(function)))

@@ -596,6 +596,7 @@ def _quote_embedded_function(self, function):
globals=self.globals, host_environment=host_environment,
quote=self._quote)
function_node = asttyped_rewriter.visit_quoted_function(function_node, embedded_function)
function_node.flags = flags

# Add it into our typedtree so that it gets inferenced and codegen'd.
self._inject(function_node)
@@ -774,7 +775,8 @@ def _quote_function(self, function, loc):
notes=[note])
self.engine.process(diag)

self._quote_embedded_function(function)
self._quote_embedded_function(function,
flags=function.artiq_embedded.flags)
elif function.artiq_embedded.syscall is not None:
# Insert a storage-less global whose type instructs the compiler
# to perform a system call instead of a regular call.
3 changes: 3 additions & 0 deletions artiq/compiler/ir.py
Original file line number Diff line number Diff line change
@@ -425,6 +425,8 @@ class Function:
the module it is contained in
:ivar is_cold:
(bool) if True, the function should be considered rarely called
:ivar flags: (set of str) Code generation flags.
Flag ``fast-math`` is the equivalent of gcc's ``-ffast-math``.
"""

def __init__(self, typ, name, arguments, loc=None):
@@ -434,6 +436,7 @@ def __init__(self, typ, name, arguments, loc=None):
self.set_arguments(arguments)
self.is_internal = False
self.is_cold = False
self.flags = {}

def _remove_name(self, name):
self.names.remove(name)
6 changes: 4 additions & 2 deletions artiq/compiler/transforms/artiq_ir_generator.py
Original file line number Diff line number Diff line change
@@ -224,7 +224,8 @@ def visit_ClassDefT(self, node):
finally:
self.current_class = old_class

def visit_function(self, node, is_lambda=False, is_internal=False, is_quoted=False):
def visit_function(self, node, is_lambda=False, is_internal=False, is_quoted=False,
flags={}):
if is_lambda:
name = "lambda@{}:{}".format(node.loc.line(), node.loc.column())
typ = node.type.find()
@@ -270,6 +271,7 @@ def codegen_default(default_node):
func = ir.Function(typ, ".".join(self.name), [env_arg] + args + optargs,
loc=node.lambda_loc if is_lambda else node.keyword_loc)
func.is_internal = is_internal
func.flags = flags
self.functions.append(func)
old_func, self.current_function = self.current_function, func

@@ -336,7 +338,7 @@ def visit_FunctionDefT(self, node):
self.append(ir.SetAttr(self.current_class, node.name, func))

def visit_QuotedFunctionDefT(self, node):
self.visit_function(node, is_internal=True, is_quoted=True)
self.visit_function(node, is_internal=True, is_quoted=True, flags=node.flags)

def visit_Return(self, node):
if node.value is None:
8 changes: 7 additions & 1 deletion artiq/compiler/transforms/inferencer.py
Original file line number Diff line number Diff line change
@@ -846,6 +846,10 @@ def makenotes(printer, typea, typeb, loca, locb):
# An user-defined class.
self._unify(node.type, typ.find().instance,
node.loc, None)
elif types.is_builtin(typ, "kernel"):
# Ignored.
self._unify(node.type, builtins.TNone(),
node.loc, None)
else:
assert False

@@ -1188,7 +1192,9 @@ def visit_arguments(self, node):

def visit_FunctionDefT(self, node):
for index, decorator in enumerate(node.decorator_list):
if types.is_builtin(decorator.type, "kernel"):
if types.is_builtin(decorator.type, "kernel") or \
isinstance(decorator, asttyped.CallT) and \
types.is_builtin(decorator.func.type, "kernel"):
continue

diag = diagnostic.Diagnostic("error",
52 changes: 38 additions & 14 deletions artiq/compiler/transforms/llvm_ir_generator.py
Original file line number Diff line number Diff line change
@@ -175,6 +175,7 @@ def __init__(self, engine, module_name, target, function_map, object_map, type_m
self.llmodule = ll.Module(context=self.llcontext, name=module_name)
self.llmodule.triple = target.triple
self.llmodule.data_layout = target.data_layout
self.function_flags = None
self.llfunction = None
self.llmap = {}
self.llobject_map = {}
@@ -562,6 +563,7 @@ def rpc_tag_error(typ):

def process_function(self, func):
try:
self.function_flags = func.flags
self.llfunction = self.map(func)

if func.is_internal:
@@ -617,6 +619,7 @@ def process_function(self, func):
for value, block in phi.incoming():
llphi.add_incoming(self.map(value), llblock_map[block])
finally:
self.function_flags = None
self.llfunction = None
self.llmap = {}
self.phis = []
@@ -863,40 +866,55 @@ def process_Coerce(self, insn):
else:
assert False

def add_fast_math_flags(self, llvalue):
if 'fast-math' in self.function_flags:
llvalue.opname = llvalue.opname + ' fast'

def process_Arith(self, insn):
if isinstance(insn.op, ast.Add):
if builtins.is_float(insn.type):
return self.llbuilder.fadd(self.map(insn.lhs()), self.map(insn.rhs()),
name=insn.name)
llvalue = self.llbuilder.fadd(self.map(insn.lhs()), self.map(insn.rhs()),
name=insn.name)
self.add_fast_math_flags(llvalue)
return llvalue
else:
return self.llbuilder.add(self.map(insn.lhs()), self.map(insn.rhs()),
name=insn.name)
elif isinstance(insn.op, ast.Sub):
if builtins.is_float(insn.type):
return self.llbuilder.fsub(self.map(insn.lhs()), self.map(insn.rhs()),
name=insn.name)
llvalue = self.llbuilder.fsub(self.map(insn.lhs()), self.map(insn.rhs()),
name=insn.name)
self.add_fast_math_flags(llvalue)
return llvalue
else:
return self.llbuilder.sub(self.map(insn.lhs()), self.map(insn.rhs()),
name=insn.name)
elif isinstance(insn.op, ast.Mult):
if builtins.is_float(insn.type):
return self.llbuilder.fmul(self.map(insn.lhs()), self.map(insn.rhs()),
name=insn.name)
llvalue = self.llbuilder.fmul(self.map(insn.lhs()), self.map(insn.rhs()),
name=insn.name)
self.add_fast_math_flags(llvalue)
return llvalue
else:
return self.llbuilder.mul(self.map(insn.lhs()), self.map(insn.rhs()),
name=insn.name)
elif isinstance(insn.op, ast.Div):
if builtins.is_float(insn.lhs().type):
return self.llbuilder.fdiv(self.map(insn.lhs()), self.map(insn.rhs()),
name=insn.name)
llvalue = self.llbuilder.fdiv(self.map(insn.lhs()), self.map(insn.rhs()),
name=insn.name)
self.add_fast_math_flags(llvalue)
return llvalue
else:
lllhs = self.llbuilder.sitofp(self.map(insn.lhs()), self.llty_of_type(insn.type))
llrhs = self.llbuilder.sitofp(self.map(insn.rhs()), self.llty_of_type(insn.type))
return self.llbuilder.fdiv(lllhs, llrhs,
name=insn.name)
llvalue = self.llbuilder.fdiv(lllhs, llrhs,
name=insn.name)
self.add_fast_math_flags(llvalue)
return llvalue
elif isinstance(insn.op, ast.FloorDiv):
if builtins.is_float(insn.type):
llvalue = self.llbuilder.fdiv(self.map(insn.lhs()), self.map(insn.rhs()))
self.add_fast_math_flags(llvalue)
return self.llbuilder.call(self.llbuiltin("llvm.floor.f64"), [llvalue],
name=insn.name)
else:
@@ -906,6 +924,7 @@ def process_Arith(self, insn):
# Python only has the modulo operator, LLVM only has the remainder
if builtins.is_float(insn.type):
llvalue = self.llbuilder.frem(self.map(insn.lhs()), self.map(insn.rhs()))
self.add_fast_math_flags(llvalue)
return self.llbuilder.call(self.llbuiltin("llvm.copysign.f64"),
[llvalue, self.map(insn.rhs())],
name=insn.name)
@@ -1298,19 +1317,20 @@ def process_Call(self, insn):
return llresult

def process_Invoke(self, insn):
functiontyp = insn.target_function().type
llnormalblock = self.map(insn.normal_target())
llunwindblock = self.map(insn.exception_target())
if types.is_rpc_function(insn.target_function().type):
if types.is_rpc_function(functiontyp):
return self._build_rpc(insn.target_function().loc,
insn.target_function().type,
functiontyp,
insn.arguments(),
llnormalblock, llunwindblock)
elif types.is_c_function(insn.target_function().type):
elif types.is_c_function(functiontyp):
llfun, llargs = self._prepare_ffi_call(insn)
else:
llfun, llargs = self._prepare_closure_call(insn)

if self.has_sret(insn.target_function().type):
if self.has_sret(functiontyp):
llstackptr = self.llbuilder.call(self.llbuiltin("llvm.stacksave"), [])

llresultslot = self.llbuilder.alloca(llfun.type.pointee.args[0].pointee)
@@ -1323,6 +1343,10 @@ def process_Invoke(self, insn):
llcall = self.llbuilder.invoke(llfun, llargs, llnormalblock, llunwindblock,
name=insn.name)

# See the comment in process_Call.
if types.is_c_function(functiontyp) and 'nowrite' in functiontyp.flags:
llcall.metadata['tbaa'] = self.tbaa_nowrite_call

if insn.is_cold:
llcall.cconv = 'coldcc'

1 change: 1 addition & 0 deletions artiq/compiler/types.py
Original file line number Diff line number Diff line change
@@ -351,6 +351,7 @@ class TCFunction(TFunction):
attributes = OrderedDict()

def __init__(self, args, ret, name, flags={}):
assert isinstance(flags, set)
for flag in flags:
assert flag in {'nounwind', 'nowrite'}
super().__init__(args, OrderedDict(), ret)
4 changes: 2 additions & 2 deletions artiq/coredevice/cache.py
Original file line number Diff line number Diff line change
@@ -2,11 +2,11 @@
from artiq.language.types import *


@syscall("cache_get", flags={"nounwind", "nowrite"})
@syscall(flags={"nounwind", "nowrite"})
def cache_get(key: TStr) -> TList(TInt32):
raise NotImplementedError("syscall not simulated")

@syscall("cache_put", flags={"nowrite"})
@syscall(flags={"nowrite"})
def cache_put(key: TStr, value: TList(TInt32)) -> TNone:
raise NotImplementedError("syscall not simulated")

2 changes: 1 addition & 1 deletion artiq/coredevice/core.py
Original file line number Diff line number Diff line change
@@ -37,7 +37,7 @@ def __str__(self):
return "\n" + _render_diagnostic(self.diagnostic, colored=colors_supported)


@syscall("rtio_get_counter", flags={"nounwind", "nowrite"})
@syscall(flags={"nounwind", "nowrite"})
def rtio_get_counter() -> TInt64:
raise NotImplementedError("syscall not simulated")

16 changes: 8 additions & 8 deletions artiq/coredevice/dds.py
Original file line number Diff line number Diff line change
@@ -10,20 +10,20 @@
PHASE_MODE_TRACKING = 2


@syscall("dds_init", flags={"nowrite"})
@syscall(flags={"nowrite"})
def dds_init(time_mu: TInt64, bus_channel: TInt32, channel: TInt32) -> TNone:
raise NotImplementedError("syscall not simulated")

@syscall("dds_set", flags={"nowrite"})
@syscall(flags={"nowrite"})
def dds_set(time_mu: TInt64, bus_channel: TInt32, channel: TInt32, ftw: TInt32,
pow: TInt32, phase_mode: TInt32, amplitude: TInt32) -> TNone:
raise NotImplementedError("syscall not simulated")

@syscall("dds_batch_enter", flags={"nowrite"})
@syscall(flags={"nowrite"})
def dds_batch_enter(time_mu: TInt64) -> TNone:
raise NotImplementedError("syscall not simulated")

@syscall("dds_batch_exit", flags={"nowrite"})
@syscall(flags={"nowrite"})
def dds_batch_exit() -> TNone:
raise NotImplementedError("syscall not simulated")

@@ -99,27 +99,27 @@ def __init__(self, dmgr, bus_channel, channel, core_dds_device="core_dds"):
self.channel = channel
self.phase_mode = PHASE_MODE_CONTINUOUS

@portable
@portable(flags=["fast-math"])
def frequency_to_ftw(self, frequency):
"""Returns the frequency tuning word corresponding to the given
frequency.
"""
return round(int(2, width=64)**32*frequency/self.core_dds.sysclk)

@portable
@portable(flags=["fast-math"])
def ftw_to_frequency(self, ftw):
"""Returns the frequency corresponding to the given frequency tuning
word.
"""
return ftw*self.core_dds.sysclk/int(2, width=64)**32

@portable
@portable(flags=["fast-math"])
def turns_to_pow(self, turns):
"""Returns the phase offset word corresponding to the given phase
in turns."""
return round(turns*2**self.pow_width)

@portable
@portable(flags=["fast-math"])
def pow_to_turns(self, pow):
"""Returns the phase in turns corresponding to the given phase offset
word."""
10 changes: 5 additions & 5 deletions artiq/coredevice/i2c.py
Original file line number Diff line number Diff line change
@@ -3,27 +3,27 @@
from artiq.coredevice.exceptions import I2CError


@syscall("i2c_init", flags={"nowrite"})
@syscall(flags={"nowrite"})
def i2c_init(busno: TInt32) -> TNone:
raise NotImplementedError("syscall not simulated")


@syscall("i2c_start", flags={"nounwind", "nowrite"})
@syscall(flags={"nounwind", "nowrite"})
def i2c_start(busno: TInt32) -> TNone:
raise NotImplementedError("syscall not simulated")


@syscall("i2c_stop", flags={"nounwind", "nowrite"})
@syscall(flags={"nounwind", "nowrite"})
def i2c_stop(busno: TInt32) -> TNone:
raise NotImplementedError("syscall not simulated")


@syscall("i2c_write", flags={"nounwind", "nowrite"})
@syscall(flags={"nounwind", "nowrite"})
def i2c_write(busno: TInt32, b: TInt32) -> TBool:
raise NotImplementedError("syscall not simulated")


@syscall("i2c_read", flags={"nounwind", "nowrite"})
@syscall(flags={"nounwind", "nowrite"})
def i2c_read(busno: TInt32, ack: TBool) -> TInt32:
raise NotImplementedError("syscall not simulated")

6 changes: 3 additions & 3 deletions artiq/coredevice/rtio.py
Original file line number Diff line number Diff line change
@@ -2,17 +2,17 @@
from artiq.language.types import TInt64, TInt32, TNone


@syscall("rtio_output", flags={"nowrite"})
@syscall(flags={"nowrite"})
def rtio_output(time_mu: TInt64, channel: TInt32, addr: TInt32, data: TInt32
) -> TNone:
raise NotImplementedError("syscall not simulated")


@syscall("rtio_input_timestamp", flags={"nowrite"})
@syscall(flags={"nowrite"})
def rtio_input_timestamp(timeout_mu: TInt64, channel: TInt32) -> TInt64:
raise NotImplementedError("syscall not simulated")


@syscall("rtio_input_data", flags={"nowrite"})
@syscall(flags={"nowrite"})
def rtio_input_data(channel: TInt32) -> TInt32:
raise NotImplementedError("syscall not simulated")
Loading