Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
compiler.ir: print even blocks without predecessors.
Browse files Browse the repository at this point in the history
whitequark committed Nov 23, 2015
1 parent d92b343 commit 8e96117
Showing 3 changed files with 68 additions and 1 deletion.
1 change: 1 addition & 0 deletions artiq/compiler/algorithms/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .inline import inline
62 changes: 62 additions & 0 deletions artiq/compiler/algorithms/inline.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
"""
:func:`inline` inlines a call instruction in ARTIQ IR.
The call instruction must have a statically known callee,
it must be second to last in the basic block, and the basic
block must have exactly one successor.
"""

from .. import ir

def inline(call_insn):
assert isinstance(call_insn, ir.Call)
assert call_insn.static_target_function is not None
assert len(call_insn.basic_block.successors()) == 1
assert call_insn.basic_block.index(call_insn) == \
len(call_insn.basic_block.instructions) - 2

value_map = {}
source_function = call_insn.static_target_function
target_function = call_insn.basic_block.function
target_predecessor = call_insn.basic_block
target_successor = call_insn.basic_block.successors()[0]
target_return_phi = target_successor.prepend(ir.Phi(source_function.type.ret))

closure = target_predecessor.insert(ir.GetAttr(call_insn.target_function(), '__closure__'),
before=call_insn)
for actual_arg, formal_arg in zip([closure] + call_insn.arguments(),
source_function.arguments):
value_map[formal_arg] = actual_arg

for source_block in source_function.basic_blocks:
target_block = ir.BasicBlock([], "i." + source_block.name)
target_function.add(target_block)
value_map[source_block] = target_block

def mapper(value):
if isinstance(value, ir.Constant):
return value
else:
return value_map[value]

for source_insn in source_function.instructions():
target_block = value_map[source_insn.basic_block]
if isinstance(source_insn, ir.Return):
target_return_phi.add_incoming(mapper(source_insn.value()), target_block)
target_insn = ir.Branch(target_successor)
elif isinstance(source_insn, ir.Phi):
target_insn = ir.Phi()
else:
target_insn = source_insn.copy(mapper)
target_insn.name = "i." + source_insn.name
value_map[source_insn] = target_insn
target_block.append(target_insn)

for source_insn in source_function.instructions():
if isinstance(source_insn, ir.Phi):
target_insn = value_map[source_insn]
for block, value in source_insn.incoming():
target_insn.add_incoming(value_map[value], value_map[block])

target_predecessor.terminator().replace_with(ir.Branch(value_map[source_function.entry()]))
call_insn.replace_all_uses_with(target_return_phi)
call_insn.erase()
6 changes: 5 additions & 1 deletion artiq/compiler/ir.py
Original file line number Diff line number Diff line change
@@ -479,8 +479,12 @@ def visit(block):
type_printer.name(self.type.ret), self.name,
", ".join([arg.as_operand(type_printer) for arg in self.arguments]),
type_printer.name(self.type)))
for block in reversed(postorder):

postorder_blocks = list(reversed(postorder))
orphan_blocks = [block for block in self.basic_blocks if block not in postorder]
for block in postorder_blocks + orphan_blocks:
lines.append(block.as_entity(type_printer))

lines.append("}")
return "\n".join(lines)

0 comments on commit 8e96117

Please sign in to comment.