transforms.cfg_simplifier: remove.

Specifically, the following idiom broke our CFGSimplifier:

b1:
  branch_if %cond, %b2, %b3
b2:
  branch %b3
b3:
  %v = phi [ %b2 => 0, %b3 => 1 ]

This is very annoying to properly handle in general case, and also
this (specifically %b2) is exactly what broke LocalAccessValidator
in the first place. So, remove CFGSimplifier altogether.

Instead, teach LocalAccessValidator how to look through predecessors
in order to get a location.
This commit is contained in:
whitequark 2015-12-31 17:07:31 +08:00
parent 17802d3cff
commit 9ed6b54249
4 changed files with 16 additions and 42 deletions

View File

@ -55,7 +55,6 @@ class Module:
artiq_ir_generator = transforms.ARTIQIRGenerator(engine=self.engine, artiq_ir_generator = transforms.ARTIQIRGenerator(engine=self.engine,
module_name=src.name, module_name=src.name,
ref_period=ref_period) ref_period=ref_period)
cfg_simplifier = transforms.CFGSimplifier(engine=self.engine)
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)
devirtualization = analyses.Devirtualization() devirtualization = analyses.Devirtualization()
@ -71,7 +70,6 @@ class Module:
devirtualization.visit(src.typedtree) devirtualization.visit(src.typedtree)
self.artiq_ir = artiq_ir_generator.visit(src.typedtree) self.artiq_ir = artiq_ir_generator.visit(src.typedtree)
artiq_ir_generator.annotate_calls(devirtualization) artiq_ir_generator.annotate_calls(devirtualization)
cfg_simplifier.process(self.artiq_ir)
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)

View File

@ -4,6 +4,5 @@ from .int_monomorphizer import IntMonomorphizer
from .iodelay_estimator import IODelayEstimator 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 .cfg_simplifier import CFGSimplifier
from .llvm_ir_generator import LLVMIRGenerator from .llvm_ir_generator import LLVMIRGenerator
from .interleaver import Interleaver from .interleaver import Interleaver

View File

@ -1,35 +0,0 @@
"""
:class:`CFGSimplifier` is a simple control flow graph
simplification transform: it removes empty basic blocks.
"""
from .. import ir
class CFGSimplifier:
def __init__(self, engine):
self.engine = engine
def process(self, functions):
for func in functions:
self.process_function(func)
def process_function(self, func):
for block in list(func.basic_blocks):
if len(block.instructions) == 1 and \
isinstance(block.terminator(), ir.Branch):
successor, = block.successors()
for insn in set(block.uses):
if isinstance(insn, ir.BranchIf) and \
((insn.if_true() == block and insn.if_false() == successor) or
(insn.if_true() == successor and insn.if_false() == block)):
# Our IR doesn't tolerate branch_if %c, %b, %b
insn.replace_with(ir.Branch(successor))
elif isinstance(insn, ir.Phi):
incoming_value = insn.incoming_value_for_block(block)
insn.remove_incoming_block(block)
for pred in block.predecessors():
insn.add_incoming(incoming_value, pred)
block.replace_all_uses_with(successor)
block.erase()

View File

@ -143,11 +143,23 @@ class LocalAccessValidator:
def _uninitialized_access(self, insn, var_name, pred_at_fault): def _uninitialized_access(self, insn, var_name, pred_at_fault):
if pred_at_fault is not None: if pred_at_fault is not None:
visited = set()
possible_preds = [pred_at_fault]
uninitialized_loc = None uninitialized_loc = None
for pred_insn in reversed(pred_at_fault.instructions): while uninitialized_loc is None:
if pred_insn.loc is not None: possible_pred = possible_preds.pop(0)
uninitialized_loc = pred_insn.loc.begin() visited.add(possible_pred)
break
for pred_insn in reversed(possible_pred.instructions):
if pred_insn.loc is not None:
uninitialized_loc = pred_insn.loc.begin()
break
for block in possible_pred.predecessors():
if block not in visited:
possible_preds.append(block)
assert uninitialized_loc is not None assert uninitialized_loc is not None
note = diagnostic.Diagnostic("note", note = diagnostic.Diagnostic("note",