3838from executorch .exir .debug_handle_utils import (
3939 DEBUG_HANDLE_KEY ,
4040 FROM_NODE_KEY ,
41- get_greatest_ancestor_node_identifier ,
4241 UNSET_DEBUG_HANDLE ,
4342)
4443
@@ -976,32 +975,13 @@ def get_parent_node_identifier(node: Node) -> Optional[str]:
976975 return f"{ node_source .name } .{ str (node_source .graph_id )} "
977976
978977
979- def propagate_back_debug_handle (
980- exported_program : ExportedProgram ,
981- exported_program_graph_id : int ,
978+ def _extract_ancestor_debug_handles (
982979 edge_dialect_program : ExportedProgram ,
983- ) -> bool :
984- """
985- Propagate debug handle from edge dialect program back to the exported program while maintain the correctness
986- of operator tracing.
987-
988- e.g.
989- export program: op1 -> op2 -> op3
990- edge dialect program: op1_0 -> op3_0 -> op3_1
991- where op1_0 is from op1, op3_0 and op3_1 are from op3, op2 is removed by to_edge pipeline (e.g. RemoveNoopPass).
992-
993- Then debug handle of op1 should be same as op1_0, and debug handle of op3 should be same as op3_0 and op3_1.
994- The debug handle of op2 will be UNSET_DEBUG_HANDLE for further skipping.
995-
996- Return: True if every debug handle in the edge dialect program has a corresponding node in the exported program, otherwise, return False.
997- """
998-
999- # 1. set up a mapping from identifier of every possible ancestor node id to debug handle
1000- # using edge dialect program nodes' debug handles and from_node info
980+ ) -> Dict [str , int ]:
981+ """Extract mapping from ancestor node identifiers to debug handles."""
1001982 ancestors_node_id_to_debug_handle : Dict [str , int ] = {}
1002983
1003984 def _extract_node_id_to_debug_handle (node : Node ) -> None :
1004- nonlocal ancestors_node_id_to_debug_handle
1005985 if node .op in ("placeholder" , "output" ):
1006986 return
1007987 for ancestor_node_id in get_ancestor_node_identifiers (node ):
@@ -1018,40 +998,55 @@ def _extract_node_id_to_debug_handle(node: Node) -> None:
1018998 bfs_trace_with_node_process (
1019999 edge_dialect_program .graph_module , _extract_node_id_to_debug_handle
10201000 )
1001+ return ancestors_node_id_to_debug_handle
10211002
1022- # 2. verify if every debug handle in the edge dialect program has a corresponding node in the exported program
1023- matched_debug_handes : Set [int ] = set ()
1003+
1004+ def _find_matched_debug_handles (
1005+ exported_program : ExportedProgram ,
1006+ exported_program_graph_id : int ,
1007+ ancestors_node_id_to_debug_handle : Dict [str , int ],
1008+ ) -> Set [int ]:
1009+ """Find debug handles that have corresponding nodes in the exported program."""
1010+ matched_debug_handles : Set [int ] = set ()
10241011
10251012 def _find_n_match_node (node : Node ) -> None :
1026- nonlocal matched_debug_handes
10271013 if node .op in ("output" , "placeholder" ):
10281014 return
10291015 node_id = f"{ node .name } .{ exported_program_graph_id } "
10301016 parent_node_id = get_parent_node_identifier (node )
10311017 if node_id in ancestors_node_id_to_debug_handle :
1032- matched_debug_handes .add (ancestors_node_id_to_debug_handle [node_id ])
1018+ matched_debug_handles .add (ancestors_node_id_to_debug_handle [node_id ])
10331019 elif parent_node_id and parent_node_id in ancestors_node_id_to_debug_handle :
1034- matched_debug_handes .add (ancestors_node_id_to_debug_handle [parent_node_id ])
1020+ matched_debug_handles .add (ancestors_node_id_to_debug_handle [parent_node_id ])
10351021
10361022 bfs_trace_with_node_process (exported_program .graph_module , _find_n_match_node )
1023+ return matched_debug_handles
10371024
1025+
1026+ def _verify_graph_match (
1027+ edge_dialect_program : ExportedProgram , matched_debug_handles : Set [int ]
1028+ ) -> bool :
1029+ """Verify if every debug handle in edge dialect program has a corresponding node."""
10381030 graph_matched = True
10391031
10401032 def _check_graph_match (node : Node ) -> None :
10411033 nonlocal graph_matched
10421034 if node .op in ("output" , "placeholder" ):
10431035 return
1044-
1045- if node .meta [DEBUG_HANDLE_KEY ] not in matched_debug_handes :
1036+ if node .meta [DEBUG_HANDLE_KEY ] not in matched_debug_handles :
10461037 graph_matched = False
10471038
10481039 bfs_trace_with_node_process (edge_dialect_program .graph_module , _check_graph_match )
1040+ return graph_matched
10491041
1050- # if any node in the edge dialect program has no corresponding node in the exported program, match failed
1051- if not graph_matched :
1052- return False
10531042
1054- # 3. propagate debug handle from edge dialect program back to the exported program while maintain the correctness of operator tracing
1043+ def _apply_debug_handles (
1044+ exported_program : ExportedProgram ,
1045+ exported_program_graph_id : int ,
1046+ ancestors_node_id_to_debug_handle : Dict [str , int ],
1047+ ) -> None :
1048+ """Apply debug handles to the exported program nodes."""
1049+
10551050 def _equip_debug_handle (node : Node ) -> None :
10561051 if node .op in ("output" , "placeholder" ):
10571052 return
@@ -1067,4 +1062,43 @@ def _equip_debug_handle(node: Node) -> None:
10671062 node .meta [DEBUG_HANDLE_KEY ] = UNSET_DEBUG_HANDLE
10681063
10691064 bfs_trace_with_node_process (exported_program .graph_module , _equip_debug_handle )
1065+
1066+
1067+ def propagate_back_debug_handle (
1068+ exported_program : ExportedProgram ,
1069+ exported_program_graph_id : int ,
1070+ edge_dialect_program : ExportedProgram ,
1071+ ) -> bool :
1072+ """
1073+ Propagate debug handle from edge dialect program back to the exported program while maintain the correctness
1074+ of operator tracing.
1075+
1076+ e.g.
1077+ export program: op1 -> op2 -> op3
1078+ edge dialect program: op1_0 -> op3_0 -> op3_1
1079+ where op1_0 is from op1, op3_0 and op3_1 are from op3, op2 is removed by to_edge pipeline (e.g. RemoveNoopPass).
1080+
1081+ Then debug handle of op1 should be same as op1_0, and debug handle of op3 should be same as op3_0 and op3_1.
1082+ The debug handle of op2 will be UNSET_DEBUG_HANDLE for further skipping.
1083+
1084+ Return: True if every debug handle in the edge dialect program has a corresponding node in the exported program, otherwise, return False.
1085+ """
1086+ # 1. Extract mapping from ancestor node identifiers to debug handles
1087+ ancestors_node_id_to_debug_handle = _extract_ancestor_debug_handles (
1088+ edge_dialect_program
1089+ )
1090+
1091+ # 2. Find debug handles that have corresponding nodes in the exported program
1092+ matched_debug_handles = _find_matched_debug_handles (
1093+ exported_program , exported_program_graph_id , ancestors_node_id_to_debug_handle
1094+ )
1095+
1096+ # 3. Verify if every debug handle in edge dialect program has a corresponding node
1097+ if not _verify_graph_match (edge_dialect_program , matched_debug_handles ):
1098+ return False
1099+
1100+ # 4. Apply debug handles to the exported program
1101+ _apply_debug_handles (
1102+ exported_program , exported_program_graph_id , ancestors_node_id_to_debug_handle
1103+ )
10701104 return True
0 commit comments