analyses.invariant_detection: implement (#622).

old/phaser2
whitequark 2016-11-20 12:48:26 +00:00
parent 30598720f4
commit f5cca6b09e
4 changed files with 59 additions and 2 deletions

View File

@ -1,3 +1,4 @@
from .constness import Constness
from .domination import DominatorTree
from .devirtualization import Devirtualization
from .invariant_detection import InvariantDetection

View File

@ -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)

View File

@ -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."""

View File

@ -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)