forked from M-Labs/artiq
analyses.invariant_detection: implement (#622).
This commit is contained in:
parent
30598720f4
commit
f5cca6b09e
|
@ -1,3 +1,4 @@
|
|||
from .constness import Constness
|
||||
from .domination import DominatorTree
|
||||
from .devirtualization import Devirtualization
|
||||
from .invariant_detection import InvariantDetection
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
"""
|
||||
:class:`InvariantDetection` determines which attributes can be safely
|
||||
marked kernel invariant.
|
||||
"""
|
||||
|
||||
from pythonparser import diagnostic
|
||||
from .. import ir, types
|
||||
|
||||
class InvariantDetection:
|
||||
def __init__(self, engine):
|
||||
self.engine = engine
|
||||
|
||||
def process(self, functions):
|
||||
self.attr_locs = dict()
|
||||
self.attr_written = set()
|
||||
|
||||
for func in functions:
|
||||
self.process_function(func)
|
||||
|
||||
for key in self.attr_locs:
|
||||
if key not in self.attr_written:
|
||||
typ, attr = key
|
||||
if attr in typ.constant_attributes:
|
||||
continue
|
||||
|
||||
diag = diagnostic.Diagnostic("note",
|
||||
"attribute '{attr}' of type '{type}' is never written to; " +
|
||||
"it could be marked as kernel invariant to potentially increase performance",
|
||||
{"attr": attr,
|
||||
"type": typ.name},
|
||||
self.attr_locs[key])
|
||||
self.engine.process(diag)
|
||||
|
||||
def process_function(self, func):
|
||||
for block in func.basic_blocks:
|
||||
for insn in block.instructions:
|
||||
if not isinstance(insn, (ir.GetAttr, ir.SetAttr)):
|
||||
continue
|
||||
if not types.is_instance(insn.object().type):
|
||||
continue
|
||||
|
||||
key = (insn.object().type, insn.attr)
|
||||
if isinstance(insn, ir.GetAttr):
|
||||
if types.is_method(insn.type):
|
||||
continue
|
||||
if key not in self.attr_locs and insn.loc is not None:
|
||||
self.attr_locs[key] = insn.loc
|
||||
elif isinstance(insn, ir.SetAttr):
|
||||
self.attr_written.add(key)
|
|
@ -40,7 +40,7 @@ class Source:
|
|||
return cls(source.Buffer(f.read(), filename, 1), engine=engine)
|
||||
|
||||
class Module:
|
||||
def __init__(self, src, ref_period=1e-6, attribute_writeback=True):
|
||||
def __init__(self, src, ref_period=1e-6, attribute_writeback=True, remarks=True):
|
||||
self.attribute_writeback = attribute_writeback
|
||||
self.engine = src.engine
|
||||
self.embedding_map = src.embedding_map
|
||||
|
@ -61,6 +61,7 @@ class Module:
|
|||
local_access_validator = validators.LocalAccessValidator(engine=self.engine)
|
||||
devirtualization = analyses.Devirtualization()
|
||||
interleaver = transforms.Interleaver(engine=self.engine)
|
||||
invariant_detection = analyses.InvariantDetection(engine=self.engine)
|
||||
|
||||
int_monomorphizer.visit(src.typedtree)
|
||||
inferencer.visit(src.typedtree)
|
||||
|
@ -74,6 +75,8 @@ class Module:
|
|||
dead_code_eliminator.process(self.artiq_ir)
|
||||
interleaver.process(self.artiq_ir)
|
||||
local_access_validator.process(self.artiq_ir)
|
||||
if remarks:
|
||||
invariant_detection.process(self.artiq_ir)
|
||||
|
||||
def build_llvm_ir(self, target):
|
||||
"""Compile the module to LLVM IR for the specified target."""
|
||||
|
|
|
@ -1151,8 +1151,12 @@ class LLVMIRGenerator:
|
|||
byvals = [i + 1 for i in byvals]
|
||||
for i in byvals:
|
||||
llfun.args[i].add_attribute('byval')
|
||||
if 'nounwind' in insn.target_function().type.flags:
|
||||
|
||||
flags = insn.target_function().type.flags
|
||||
if 'nounwind' in flags:
|
||||
llfun.attributes.add('nounwind')
|
||||
if 'nowrite' in flags:
|
||||
llfun.attributes.add('inaccessiblememonly')
|
||||
|
||||
return llfun, list(llargs)
|
||||
|
||||
|
|
Loading…
Reference in New Issue