(
self,
emit_stacktrace: bool = False,
memory_planning: MemoryPlanningPass = None, # pyre-fixme[9]
)
| 179 | # TODO(chenlai): re-consider recapture instead of manually constructing the program because |
| 180 | # the meta data construction is done manually. |
| 181 | def program( |
| 182 | self, |
| 183 | emit_stacktrace: bool = False, |
| 184 | memory_planning: MemoryPlanningPass = None, # pyre-fixme[9] |
| 185 | ) -> Program: |
| 186 | # Fix autodpes introuces cyclic dependencies: |
| 187 | # program -> verifier -> lowered_backend_module -> program |
| 188 | # @manual |
| 189 | from executorch.exir.program._program import ( |
| 190 | _get_updated_graph_signature, |
| 191 | _transform, |
| 192 | ) |
| 193 | |
| 194 | """ |
| 195 | Returns the object that represents the ExecuTorch binary before serialization. |
| 196 | """ |
| 197 | # Creates a new module based on the original module. The original module will |
| 198 | # look something like following: |
| 199 | # |
| 200 | # opcode name target args kwargs |
| 201 | # ------------- ------------------- ---------------- ------------------------------------------ -------- |
| 202 | # placeholder arg0_1 arg0_1 () {} |
| 203 | # placeholder arg1_1 arg1_1 () {} |
| 204 | # call_function aten_repeat_default * (arg1_1, [4, 1]) {} |
| 205 | # call_function aten_mul_tensor * (aten_repeat_default, aten_repeat_default) {} |
| 206 | # call_function aten_add_tensor * (arg1_1, arg1_1) {} |
| 207 | # output output output ([aten_mul_tensor, aten_add_tensor],) {} |
| 208 | # |
| 209 | # if the whole module is lowered, the resulting lowered module look like |
| 210 | # |
| 211 | # opcode name target args kwargs |
| 212 | # ------------- ------------------------ --------------------------- ---------------------------------- -------- |
| 213 | # placeholder arg0_1 arg0_1 () {} |
| 214 | # placeholder arg1_1 arg1_1 () {} |
| 215 | # get_attr lowered_module_0 lowered_module_0 () {} |
| 216 | # call_function executorch_call_delegate executorch_call_delegate (lowered_module_0, arg0_1, arg1_1) {} |
| 217 | # call_function getitem <built-in function getitem> (executorch_call_delegate, 0) {} |
| 218 | # call_function getitem_1 <built-in function getitem> (executorch_call_delegate, 1) {} |
| 219 | # output output_1 output ([getitem, getitem_1],) {} |
| 220 | # |
| 221 | # We'll remove all call_function nodes, insert an call_delegate node, inserting getitems nodes to get the result for call_delegate node |
| 222 | # and return the list of getitems as the output |
| 223 | |
| 224 | lowered_exported_program = copy.deepcopy(self._original_exported_program) |
| 225 | |
| 226 | # Cache these properties to avoid rebuilding the dict on each access. |
| 227 | sig = lowered_exported_program.graph_signature |
| 228 | params_map = sig.inputs_to_parameters |
| 229 | buffers_map = sig.inputs_to_buffers |
| 230 | |
| 231 | # The real input nodes are the ones not buffer or parameter |
| 232 | all_input_nodes = [ |
| 233 | node |
| 234 | for node in lowered_exported_program.graph.nodes |
| 235 | if ( |
| 236 | node.op == "placeholder" |
| 237 | and node.name not in buffers_map |
| 238 | and node.name not in params_map |
no test coverage detected