forked from M-Labs/artiq
compiler: hoist loads of kernel invariants to function entry block.
Addresses intraprocedural cases of #1007.
This commit is contained in:
parent
12d1b9819c
commit
fbf2c9a2fb
|
@ -61,6 +61,7 @@ class Module:
|
|||
dead_code_eliminator = transforms.DeadCodeEliminator(engine=self.engine)
|
||||
local_access_validator = validators.LocalAccessValidator(engine=self.engine)
|
||||
local_demoter = transforms.LocalDemoter()
|
||||
constant_hoister = transforms.ConstantHoister()
|
||||
devirtualization = analyses.Devirtualization()
|
||||
interleaver = transforms.Interleaver(engine=self.engine)
|
||||
invariant_detection = analyses.InvariantDetection(engine=self.engine)
|
||||
|
@ -79,6 +80,7 @@ class Module:
|
|||
interleaver.process(self.artiq_ir)
|
||||
local_access_validator.process(self.artiq_ir)
|
||||
local_demoter.process(self.artiq_ir)
|
||||
constant_hoister.process(self.artiq_ir)
|
||||
if remarks:
|
||||
invariant_detection.process(self.artiq_ir)
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ from .iodelay_estimator import IODelayEstimator
|
|||
from .artiq_ir_generator import ARTIQIRGenerator
|
||||
from .dead_code_eliminator import DeadCodeEliminator
|
||||
from .local_demoter import LocalDemoter
|
||||
from .constant_hoister import ConstantHoister
|
||||
from .interleaver import Interleaver
|
||||
from .typedtree_printer import TypedtreePrinter
|
||||
from .llvm_ir_generator import LLVMIRGenerator
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
"""
|
||||
:class:`ConstantHoister` is a code motion transform:
|
||||
it moves any invariant loads to the earliest point where
|
||||
they may be executed.
|
||||
"""
|
||||
|
||||
from .. import types, ir
|
||||
|
||||
class ConstantHoister:
|
||||
def process(self, functions):
|
||||
for func in functions:
|
||||
self.process_function(func)
|
||||
|
||||
def process_function(self, func):
|
||||
entry = func.entry()
|
||||
worklist = set(func.instructions())
|
||||
moved = set()
|
||||
while len(worklist) > 0:
|
||||
insn = worklist.pop()
|
||||
|
||||
if (isinstance(insn, ir.GetAttr) and insn not in moved and
|
||||
types.is_instance(insn.object().type) and
|
||||
insn.attr in insn.object().type.constant_attributes):
|
||||
has_variant_operands = False
|
||||
index_in_entry = 0
|
||||
for operand in insn.operands:
|
||||
if isinstance(operand, ir.Argument):
|
||||
pass
|
||||
elif isinstance(operand, ir.Instruction) and operand.basic_block == entry:
|
||||
index_in_entry = entry.index(operand) + 1
|
||||
else:
|
||||
has_variant_operands = True
|
||||
break
|
||||
|
||||
if has_variant_operands:
|
||||
continue
|
||||
|
||||
insn.remove_from_parent()
|
||||
entry.instructions.insert(index_in_entry, insn)
|
||||
moved.add(insn)
|
||||
print(insn)
|
||||
|
||||
for use in insn.uses:
|
||||
worklist.add(use)
|
|
@ -0,0 +1,8 @@
|
|||
device_db = {
|
||||
"core": {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.core",
|
||||
"class": "Core",
|
||||
"arguments": {"host": None, "ref_period": 1e-9}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
# RUN: env ARTIQ_DUMP_IR=%t ARTIQ_IR_NO_LOC=1 %python -m artiq.compiler.testbench.embedding +compile %s
|
||||
# RUN: OutputCheck %s --file-to-check=%t.txt
|
||||
|
||||
from artiq.language.core import *
|
||||
from artiq.language.types import *
|
||||
|
||||
# CHECK-L: %LOC.self.FLD.foo = numpy.int32 getattr('foo') <instance testbench.c> %ARG.self
|
||||
# CHECK-L: for.head:
|
||||
|
||||
class c:
|
||||
kernel_invariants = {"foo"}
|
||||
|
||||
def __init__(self):
|
||||
self.foo = 1
|
||||
|
||||
@kernel
|
||||
def run(self):
|
||||
for _ in range(10):
|
||||
core_log(1.0 * self.foo)
|
||||
|
||||
i = c()
|
||||
|
||||
@kernel
|
||||
def entrypoint():
|
||||
i.run()
|
Loading…
Reference in New Issue