'Given a pipeline and a dictionary of basic blocks, exhaustively
attempt to apply all registered rewrites to all basic blocks.'

def apply(self, kind, pipeline, func_ir):

    assert (kind in self._kinds)
    blocks = func_ir.blocks
    old_blocks = blocks.copy()
    for rewrite_cls in self.rewrites[kind]:
        rewrite = rewrite_cls(pipeline)
        work_list = list(blocks.items())
        while work_list:
            (key, block) = work_list.pop()
            matches = rewrite.match(func_ir, block, pipeline.typemap, pipeline.calltypes)
            if matches:
                if (config.DEBUG or config.DUMP_IR):
                    print(('_' * 70))
                    print(('REWRITING    (%s):' % rewrite_cls.__name__))
                    block.dump()
                    print(('_' * 60))
                new_block = rewrite.apply()
                blocks[key] = new_block
                work_list.append((key, new_block))
                if (config.DEBUG or config.DUMP_IR):
                    new_block.dump()
                    print(('_' * 70))
    for (key, block) in blocks.items():
        if (block != old_blocks[key]):
            block.verify()
