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)
|
dead_code_eliminator = transforms.DeadCodeEliminator(engine=self.engine)
|
||||||
local_access_validator = validators.LocalAccessValidator(engine=self.engine)
|
local_access_validator = validators.LocalAccessValidator(engine=self.engine)
|
||||||
local_demoter = transforms.LocalDemoter()
|
local_demoter = transforms.LocalDemoter()
|
||||||
|
constant_hoister = transforms.ConstantHoister()
|
||||||
devirtualization = analyses.Devirtualization()
|
devirtualization = analyses.Devirtualization()
|
||||||
interleaver = transforms.Interleaver(engine=self.engine)
|
interleaver = transforms.Interleaver(engine=self.engine)
|
||||||
invariant_detection = analyses.InvariantDetection(engine=self.engine)
|
invariant_detection = analyses.InvariantDetection(engine=self.engine)
|
||||||
|
@ -79,6 +80,7 @@ class Module:
|
||||||
interleaver.process(self.artiq_ir)
|
interleaver.process(self.artiq_ir)
|
||||||
local_access_validator.process(self.artiq_ir)
|
local_access_validator.process(self.artiq_ir)
|
||||||
local_demoter.process(self.artiq_ir)
|
local_demoter.process(self.artiq_ir)
|
||||||
|
constant_hoister.process(self.artiq_ir)
|
||||||
if remarks:
|
if remarks:
|
||||||
invariant_detection.process(self.artiq_ir)
|
invariant_detection.process(self.artiq_ir)
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ from .iodelay_estimator import IODelayEstimator
|
||||||
from .artiq_ir_generator import ARTIQIRGenerator
|
from .artiq_ir_generator import ARTIQIRGenerator
|
||||||
from .dead_code_eliminator import DeadCodeEliminator
|
from .dead_code_eliminator import DeadCodeEliminator
|
||||||
from .local_demoter import LocalDemoter
|
from .local_demoter import LocalDemoter
|
||||||
|
from .constant_hoister import ConstantHoister
|
||||||
from .interleaver import Interleaver
|
from .interleaver import Interleaver
|
||||||
from .typedtree_printer import TypedtreePrinter
|
from .typedtree_printer import TypedtreePrinter
|
||||||
from .llvm_ir_generator import LLVMIRGenerator
|
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