Coverage for /opt/cloud/slavespace/usr1/096471637100f3de0fcfc01072822a80/dttest/api/python/ge/ge/passes/base.py: 87%
47 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-07-27 10:03 +0800
« prev ^ index » next coverage.py v7.15.2, created at 2026-07-27 10:03 +0800
1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3# -----------------------------------------------------------------------------------------------------------
4# Copyright (c) 2026 Huawei Technologies Co., Ltd.
5# This program is free software, you can redistribute it and/or modify it under the terms and conditions of
6# CANN Open Software License Agreement Version 2.0 (the "License").
7# Please refer to the License for details. You may not use this file except in compliance with the License.
8# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
9# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
10# See LICENSE in the root of the software repository for the full text of the License.
11# -----------------------------------------------------------------------------------------------------------
13"""Base definitions for Python GE passes."""
15from __future__ import annotations
17from enum import Enum
18from typing import TYPE_CHECKING, Iterable, List, Optional, Union
20from ._native import MatchResult, PassContext, PatternMatcherConfig, PatternMatcherConfigBuilder, SubgraphInput, SubgraphOutput, SubgraphBoundary, SubgraphRewriter
22if TYPE_CHECKING:
23 from ge.graph.graph import Graph
24 from ge.graph.node import Node
26 from .pattern import Pattern
29PatternOrGraph = Union["Pattern", "Graph"]
30StatusLike = Optional[Union[bool, int]]
33class PassStage(str, Enum):
34 """Python-facing pass stage names."""
36 BEFORE_INFER_SHAPE = "BeforeInferShape"
37 AFTER_INFER_SHAPE = "AfterInferShape"
38 AFTER_BUILTIN_FUSION_PASS = "AfterBuiltinFusionPass"
39 AFTER_ORIGIN_GRAPH_OPTIMIZE = "AfterOriginGraphOptimize"
42class FusionBasePass:
43 """Python FusionBasePass contract."""
45 def run(self, graph: Graph, context: PassContext) -> StatusLike:
46 raise NotImplementedError("FusionBasePass.run must be implemented")
49class PatternFusionPass(FusionBasePass):
50 """Python PatternFusionPass contract.
52 The execution engine calls ``patterns()``, ``meet_requirements()``, and
53 ``replacement()`` — **not** ``run()``. Overriding ``run()`` in a
54 ``PatternFusionPass`` subclass has no effect; implement the three hook
55 methods above instead.
57 Subclasses can use either the legacy graph-building hooks:
58 - ``patterns(self) -> Iterable[Pattern | Graph]``
59 - ``replacement(self, match_result) -> Graph``
61 or expression-style pattern methods:
62 - ``@pattern def name(self, inputs) -> TensorHolder | list[TensorHolder] | tuple[TensorHolder, ...]``
63 - ``replacement(self, inputs) -> TensorHolder | list[TensorHolder] | tuple[TensorHolder, ...] | Graph``
64 - ``replacement(self, inputs, match_result)`` when match details are needed
66 In a ``@pattern`` method, a list/tuple means multiple outputs of one
67 pattern, not multiple patterns. Declare several ``@pattern`` methods for
68 a multiple-pattern pass. Expression-style patterns automatically capture
69 accessed inputs in input-index order, then returned outputs in return order.
70 """
72 def __init__(self, matcher_config: Optional[PatternMatcherConfig] = None) -> None:
73 self._matcher_config = matcher_config
75 def __init_subclass__(cls, **kwargs) -> None:
76 super().__init_subclass__(**kwargs)
77 if "run" in cls.__dict__:
78 raise TypeError(
79 f"{cls.__name__} overrides run(), which is never invoked "
80 f"by the PatternFusionPass execution path. "
81 f"Implement patterns()/replacement() instead."
82 )
83 from .pattern import (
84 _adapt_decorated_pattern_methods,
85 _adapt_expression_replacement,
86 _has_decorated_pattern_methods,
87 )
89 if _has_decorated_pattern_methods(cls):
90 if "patterns" in cls.__dict__:
91 raise TypeError(
92 f"{cls.__name__} cannot combine @pattern methods with patterns(). "
93 f"Use one style for declaring patterns."
94 )
95 cls.patterns = _adapt_decorated_pattern_methods(cls)
96 if "replacement" in cls.__dict__:
97 cls.replacement = _adapt_expression_replacement(cls.__dict__["replacement"])
99 @property
100 def matcher_config(self) -> Optional[PatternMatcherConfig]:
101 return self._matcher_config
103 def patterns(self) -> Iterable[PatternOrGraph]:
104 raise NotImplementedError("PatternFusionPass.patterns must be implemented")
106 def meet_requirements(self, match_result: MatchResult) -> bool:
107 return True
109 def replacement(self, match_result: MatchResult) -> "Graph":
110 raise NotImplementedError("PatternFusionPass.replacement must be implemented")
113class DecomposePass(FusionBasePass):
114 """Python DecomposePass contract.
116 The execution engine calls ``meet_requirements()`` and ``replacement()``
117 for matched nodes — **not** ``run()``. Overriding ``run()`` in a
118 ``DecomposePass`` subclass has no effect; implement the two hook methods
119 above instead.
120 """
122 op_types: Optional[List[str]] = None
124 def __init_subclass__(cls, **kwargs) -> None:
125 super().__init_subclass__(**kwargs)
126 if "run" in cls.__dict__:
127 raise TypeError(
128 f"{cls.__name__} overrides run(), which is never invoked "
129 f"by the DecomposePass execution path. "
130 f"Implement meet_requirements()/replacement() instead."
131 )
133 def meet_requirements(self, node: "Node") -> bool:
134 return True
136 def replacement(self, node: "Node") -> "Graph":
137 raise NotImplementedError("DecomposePass.replacement must be implemented")