View source on GitHub |
Lowers a Program
that may have (recursive) FunctionCallOp instructions.
tfp.experimental.auto_batching.lowering.lower_function_calls(
program
)
Mutates the ControlFlowGraph
of the input program in place. After
lowering, the result CFG
Has no
FunctionCallOp
instructionsObeys a stack discipline
What is the stack discipline? Every function body becomes a CFG subset that:
Never transfers control in except to the first block (corresponding to being called), or to a block stored with
PushGotoOp
(corresponding to a subroutine returning)Never transfers control out except with
IndirectGotoOp
(corresponding to returning), or with aPushGotoOp
(corresponding to calling a subroutine)Every path through the graph has the following effect on the variable stacks:
The formal parameters receive exactly one net pop
The return variables receive exactly one net push
All other variable stacks are left as they are
No data is read except the top frames of the formal parameter stacks
Why mutate in place? Because tying the knot in the result seemed
too hard without an explicit indirection between Block
s and
references thereto in various Op
s. Specifically, when building a
new CFG to replicate the structure of an existing one, it is
necessary to allocate Block
s to serve as the targets of all
BranchOp
, GotoOp
(and FunctionCallOp
) before building those
Op
s, and then correctly reuse those Block
s when processing said
targets. With an explicit indirection, however, it would have been
possible to reuse the same Label
s, simply creating a new mapping
from them to Block
s.
Note that the semantics assumed by this transformation is that the
CFGs being transformed do not use variable stacks internally, but
they will only be used to implement the function sequence when
function calls are lowered. This semantics licenses placing
PopOp
s to enforce a stack discipline for FunctionCallOp
s.
Args | |
---|---|
program
|
A Program whose function calls to lower. Block s in
the program may be mutated.
|
Returns | |
---|---|
lowered
|
A Program that defines no Function s and does not use the
FunctionCallOp instruction. May share structure with the input
program .
|