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 .constness import Constness
|
||||||
from .domination import DominatorTree
|
from .domination import DominatorTree
|
||||||
from .devirtualization import Devirtualization
|
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)
|
return cls(source.Buffer(f.read(), filename, 1), engine=engine)
|
||||||
|
|
||||||
class Module:
|
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.attribute_writeback = attribute_writeback
|
||||||
self.engine = src.engine
|
self.engine = src.engine
|
||||||
self.embedding_map = src.embedding_map
|
self.embedding_map = src.embedding_map
|
||||||
|
@ -61,6 +61,7 @@ class Module:
|
||||||
local_access_validator = validators.LocalAccessValidator(engine=self.engine)
|
local_access_validator = validators.LocalAccessValidator(engine=self.engine)
|
||||||
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)
|
||||||
|
|
||||||
int_monomorphizer.visit(src.typedtree)
|
int_monomorphizer.visit(src.typedtree)
|
||||||
inferencer.visit(src.typedtree)
|
inferencer.visit(src.typedtree)
|
||||||
|
@ -74,6 +75,8 @@ class Module:
|
||||||
dead_code_eliminator.process(self.artiq_ir)
|
dead_code_eliminator.process(self.artiq_ir)
|
||||||
interleaver.process(self.artiq_ir)
|
interleaver.process(self.artiq_ir)
|
||||||
local_access_validator.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):
|
def build_llvm_ir(self, target):
|
||||||
"""Compile the module to LLVM IR for the specified target."""
|
"""Compile the module to LLVM IR for the specified target."""
|
||||||
|
|
|
@ -1151,8 +1151,12 @@ class LLVMIRGenerator:
|
||||||
byvals = [i + 1 for i in byvals]
|
byvals = [i + 1 for i in byvals]
|
||||||
for i in byvals:
|
for i in byvals:
|
||||||
llfun.args[i].add_attribute('byval')
|
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')
|
llfun.attributes.add('nounwind')
|
||||||
|
if 'nowrite' in flags:
|
||||||
|
llfun.attributes.add('inaccessiblememonly')
|
||||||
|
|
||||||
return llfun, list(llargs)
|
return llfun, list(llargs)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue