We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[RELAY][PASS] Check Positiveness in FoldScaleAxis
This issue is bought up by @merrymercy . So far FoldScaleAxis is able to pass through functions like relu. However, this is only true if the scaling factor is all positive number -- we didn't encounter this problem so far because most networks only have scaling coming from BN and the result is positive constant. 

We should update the pass by running the following thing:
- Do constant folding before running FoldScaleAxis
- Check positiveness of the scale(since scale is constant it is not hard to do so)
- Only allow passing relu through if the scale is positive.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `python/tvm/relay/build_module.py`
Content:
```
1 """
2 Construct the necessary state for the TVM graph runtime
3 from a Relay expression.
4 """
5 from ..build_module import build as _tvm_build_module
6 from .. import nd as _nd, target as _target, autotvm
7 from ..contrib import graph_runtime as _graph_rt
8 from . import ir_pass
9 from . import expr
10 from .backend import interpreter as _interpreter
11 from .backend import graph_runtime_codegen as _graph_gen
12 
13 # List of optimization pass and level when switch on
14 OPT_PASS_LEVEL = {
15     "SimplifyInference": 0,
16     "OpFusion": 1,
17     "FoldConstant": 2,
18     "CombineParallelConv2D": 3,
19     "FoldScaleAxis": 3,
20     "AlterOpLayout": 3,
21 }
22 
23 class BuildConfig(object):
24     """Configuration scope to set a build config option.
25 
26     Parameters
27     ----------
28     kwargs
29         Keyword arguments of configurations to set.
30     """
31     current = None
32     defaults = {
33         "opt_level": 2,
34         "add_pass": None,
35     }
36     def __init__(self, **kwargs):
37         self._old_scope = None
38         for k, _ in kwargs.items():
39             if k not in BuildConfig.defaults:
40                 raise ValueError(
41                     "invalid argument %s, candidates are %s" % (k, BuildConfig.defaults.keys()))
42         self._attr = kwargs
43 
44     def __getattr__(self, name):
45         if name not in self._attr:
46             return BuildConfig.defaults[name]
47         return self._attr[name]
48 
49     def __enter__(self):
50         # pylint: disable=protected-access
51         self._old_scope = BuildConfig.current
52         attr = BuildConfig.current._attr.copy()
53         attr.update(self._attr)
54         self._attr = attr
55         BuildConfig.current = self
56         return self
57 
58     def __exit__(self, ptype, value, trace):
59         assert self._old_scope
60         BuildConfig.current = self._old_scope
61 
62     def pass_enabled(self, pass_name):
63         """Get whether pass is enabled.
64 
65         Parameters
66         ----------
67         pass_name : str
68             The optimization pass name
69 
70         Returns
71         -------
72         enabled : bool
73             Whether pass is enabled.
74         """
75         if self.add_pass and pass_name in self.add_pass:
76             return True
77         return self.opt_level >= OPT_PASS_LEVEL[pass_name]
78 
79 
80 BuildConfig.current = BuildConfig()
81 
82 
83 def build_config(**kwargs):
84     """Configure the build behavior by setting config variables.
85 
86     Parameters
87     ----------
88     opt_level: int, default=2
89         Optimization level. See OPT_PASS_LEVEL for level of each pass.
90 
91     add_pass: set of str
92         Optimization pass to be added regardless of optimization level.
93 
94     Returns
95     -------
96     config: BuildConfig
97         The build configuration
98     """
99     return BuildConfig(**kwargs)
100 
101 
102 def _bind_params_by_name(func, params):
103     """Bind parameters of function by its name."""
104     name_dict = {}
105     for arg in func.params:
106         name = arg.name_hint
107         if name in name_dict:
108             name_dict[name] = None
109         else:
110             name_dict[name] = arg
111     bind_dict = {}
112     for k, v in params.items():
113         if k not in name_dict:
114             continue
115         arg = name_dict[k]
116         if arg is None:
117             raise ValueError("Multiple args in the function have name %s" % k)
118         bind_dict[arg] = expr.const(v)
119     return expr.bind(func, bind_dict)
120 
121 
122 def optimize(func, params=None):
123     """Perform target invariant optimizations.
124 
125     Parameters
126     ----------
127     func : tvm.relay.Function
128         The input to optimization.
129 
130     params : Optional[Dict[str, tvm.nd.NDArray]]
131         Input parameters to the graph that do not change
132         during inference time. used for constant folding.
133 
134     Returns
135     -------
136     opt_func : tvm.relay.Function
137         The optimized version of the function.
138     """
139     cfg = BuildConfig.current
140 
141     # bind expressions
142     if params:
143         func = _bind_params_by_name(func, params)
144 
145     if cfg.pass_enabled("SimplifyInference"):
146         func = ir_pass.infer_type(func)
147         func = ir_pass.simplify_inference(func)
148 
149     if cfg.pass_enabled("CombineParallelConv2D"):
150         func = ir_pass.infer_type(func)
151         func = ir_pass.combine_parallel_conv2d(func)
152 
153     if cfg.pass_enabled("FoldScaleAxis"):
154         func = ir_pass.infer_type(func)
155         func = ir_pass.backward_fold_scale_axis(func)
156         func = ir_pass.infer_type(func)
157         func = ir_pass.forward_fold_scale_axis(func)
158 
159     if cfg.pass_enabled("FoldConstant"):
160         func = ir_pass.fold_constant(func)
161 
162     if cfg.pass_enabled("AlterOpLayout"):
163         func = ir_pass.infer_type(func)
164         func = ir_pass.canonicalize_ops(func)
165         func = ir_pass.infer_type(func)
166         func = ir_pass.alter_op_layout(func)
167 
168     return func
169 
170 
171 def build(func,
172           target=None,
173           target_host=None,
174           params=None):
175     """Build a function to run on TVM graph runtime.
176 
177     Parameters
178     ----------
179     func: relay.Function
180         The function to build.
181 
182     target : str or :any:`tvm.target.Target`, optional
183         The build target
184 
185     target_host : str or :any:`tvm.target.Target` optional
186         Host compilation target, if target is device.
187         When TVM compiles device specific program such as CUDA,
188         we also need host(CPU) side code to interact with the driver
189         setup the dimensions and parameters correctly.
190         target_host is used to specify the host side codegen target.
191         By default, llvm is used if it is enabled,
192         otherwise a stackvm intepreter is used.
193 
194     params : dict of str to NDArray
195         Input parameters to the graph that do not change
196         during inference time. Used for constant folding.
197 
198     Returns
199     -------
200     graph_json : str
201         The json string that can be accepted by graph runtime.
202 
203     mod : tvm.Module
204         The module containing necessary libraries.
205 
206     params : dict
207         The parameters of the final graph.
208     """
209     target = target if target else _target.current_target()
210     if target is None:
211         raise ValueError("Target is not set in env or passed as argument.")
212     target = _target.create(target)
213 
214     # If current dispatch context is fallback context (the default root context),
215     # then load pre-tuned parameters from TopHub
216     if isinstance(autotvm.DispatchContext.current, autotvm.FallbackContext):
217         tophub_context = autotvm.tophub.context(target)
218     else:
219         tophub_context = autotvm.util.EmptyContext()
220 
221     cfg = BuildConfig.current
222 
223     with tophub_context:
224         func = optimize(func, params)
225         # Fuse ops before running code gen
226         func = ir_pass.infer_type(func)
227         func = ir_pass.fuse_ops(func, cfg.opt_level)
228         # Graph code generation
229         func = ir_pass.infer_type(func)
230         graph_gen = _graph_gen.GraphRuntimeCodegen(mod=None, target=target)
231         graph_json, lowered_funcs, params = graph_gen.codegen(func)
232         mod = _tvm_build_module(lowered_funcs, target=target, target_host=target_host)
233     return graph_json, mod, params
234 
235 
236 class GraphExecutor(_interpreter.Executor):
237     """Wrapper around Executor interface.
238 
239     This executor is used for debug and testing purpoes.
240 
241     Parameters
242     ----------
243     mod : :py:class:`~tvm.relay.module.Module`
244         The module to support the execution.
245 
246     ctx : :py:class:`TVMContext`
247         The runtime context to run the code on.
248 
249     target : :py:class:`Target`
250         The target option to build the function.
251     """
252     def __init__(self, mod, ctx, target):
253         self.mod = mod
254         self.ctx = ctx
255         self.target = target
256 
257     def _make_executor(self, func):
258         graph_json, mod, params = build(func, target=self.target)
259         gmodule = _graph_rt.create(graph_json, mod, self.ctx)
260         if params:
261             gmodule.set_input(*params)
262         def _graph_wrapper(*args):
263             # Create map of inputs.
264             for i, arg in enumerate(args):
265                 gmodule.set_input(i, arg)
266             # Run the module, and fetch the output.
267             gmodule.run()
268             # make a copy so multiple invocation won't hurt perf.
269             return gmodule.get_output(0).copyto(_nd.cpu(0))
270 
271         return _graph_wrapper
272 
273 
274 def create_executor(kind="debug",
275                     mod=None,
276                     ctx=None,
277                     target="llvm"):
278     """Factory function to create an executor.
279 
280     Parameters
281     ----------
282     kind : str
283         The type of executor
284 
285     mod : :py:class:`~tvm.relay.module.Module`
286         The Relay module containing collection of functions
287 
288     ctx : :py:class:`tvm.TVMContext`
289         The context to execute the code.
290 
291     target : :py:class:`tvm.Target`
292         The corresponding context
293     """
294     if ctx is not None:
295         assert ctx.device_type == _nd.context(str(target), 0).device_type
296     else:
297         ctx = _nd.context(str(target), 0)
298 
299     if isinstance(target, str):
300         target = _target.create(target)
301     if kind == "debug":
302         return _interpreter.Interpreter(mod, ctx, target)
303     elif kind == "graph":
304         return GraphExecutor(mod, ctx, target)
305     else:
306         raise RuntimeError("unknown mode {0}".format(mode))
307
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/python/tvm/relay/build_module.py b/python/tvm/relay/build_module.py
--- a/python/tvm/relay/build_module.py
+++ b/python/tvm/relay/build_module.py
@@ -150,13 +150,14 @@
         func = ir_pass.infer_type(func)
         func = ir_pass.combine_parallel_conv2d(func)
 
+    if cfg.pass_enabled("FoldConstant"):
+        func = ir_pass.fold_constant(func)
+
     if cfg.pass_enabled("FoldScaleAxis"):
         func = ir_pass.infer_type(func)
         func = ir_pass.backward_fold_scale_axis(func)
         func = ir_pass.infer_type(func)
         func = ir_pass.forward_fold_scale_axis(func)
-
-    if cfg.pass_enabled("FoldConstant"):
         func = ir_pass.fold_constant(func)
 
     if cfg.pass_enabled("AlterOpLayout"):

{"golden_diff": "diff --git a/python/tvm/relay/build_module.py b/python/tvm/relay/build_module.py\n--- a/python/tvm/relay/build_module.py\n+++ b/python/tvm/relay/build_module.py\n@@ -150,13 +150,14 @@\n         func = ir_pass.infer_type(func)\n         func = ir_pass.combine_parallel_conv2d(func)\n \n+    if cfg.pass_enabled(\"FoldConstant\"):\n+        func = ir_pass.fold_constant(func)\n+\n     if cfg.pass_enabled(\"FoldScaleAxis\"):\n         func = ir_pass.infer_type(func)\n         func = ir_pass.backward_fold_scale_axis(func)\n         func = ir_pass.infer_type(func)\n         func = ir_pass.forward_fold_scale_axis(func)\n-\n-    if cfg.pass_enabled(\"FoldConstant\"):\n         func = ir_pass.fold_constant(func)\n \n     if cfg.pass_enabled(\"AlterOpLayout\"):\n", "issue": "[RELAY][PASS] Check Positiveness in FoldScaleAxis\nThis issue is bought up by @merrymercy . So far FoldScaleAxis is able to pass through functions like relu. However, this is only true if the scaling factor is all positive number -- we didn't encounter this problem so far because most networks only have scaling coming from BN and the result is positive constant. \r\n\r\nWe should update the pass by running the following thing:\r\n- Do constant folding before running FoldScaleAxis\r\n- Check positiveness of the scale(since scale is constant it is not hard to do so)\r\n- Only allow passing relu through if the scale is positive.\r\n\n", "before_files": [{"content": "\"\"\"\nConstruct the necessary state for the TVM graph runtime\nfrom a Relay expression.\n\"\"\"\nfrom ..build_module import build as _tvm_build_module\nfrom .. import nd as _nd, target as _target, autotvm\nfrom ..contrib import graph_runtime as _graph_rt\nfrom . import ir_pass\nfrom . import expr\nfrom .backend import interpreter as _interpreter\nfrom .backend import graph_runtime_codegen as _graph_gen\n\n# List of optimization pass and level when switch on\nOPT_PASS_LEVEL = {\n    \"SimplifyInference\": 0,\n    \"OpFusion\": 1,\n    \"FoldConstant\": 2,\n    \"CombineParallelConv2D\": 3,\n    \"FoldScaleAxis\": 3,\n    \"AlterOpLayout\": 3,\n}\n\nclass BuildConfig(object):\n    \"\"\"Configuration scope to set a build config option.\n\n    Parameters\n    ----------\n    kwargs\n        Keyword arguments of configurations to set.\n    \"\"\"\n    current = None\n    defaults = {\n        \"opt_level\": 2,\n        \"add_pass\": None,\n    }\n    def __init__(self, **kwargs):\n        self._old_scope = None\n        for k, _ in kwargs.items():\n            if k not in BuildConfig.defaults:\n                raise ValueError(\n                    \"invalid argument %s, candidates are %s\" % (k, BuildConfig.defaults.keys()))\n        self._attr = kwargs\n\n    def __getattr__(self, name):\n        if name not in self._attr:\n            return BuildConfig.defaults[name]\n        return self._attr[name]\n\n    def __enter__(self):\n        # pylint: disable=protected-access\n        self._old_scope = BuildConfig.current\n        attr = BuildConfig.current._attr.copy()\n        attr.update(self._attr)\n        self._attr = attr\n        BuildConfig.current = self\n        return self\n\n    def __exit__(self, ptype, value, trace):\n        assert self._old_scope\n        BuildConfig.current = self._old_scope\n\n    def pass_enabled(self, pass_name):\n        \"\"\"Get whether pass is enabled.\n\n        Parameters\n        ----------\n        pass_name : str\n            The optimization pass name\n\n        Returns\n        -------\n        enabled : bool\n            Whether pass is enabled.\n        \"\"\"\n        if self.add_pass and pass_name in self.add_pass:\n            return True\n        return self.opt_level >= OPT_PASS_LEVEL[pass_name]\n\n\nBuildConfig.current = BuildConfig()\n\n\ndef build_config(**kwargs):\n    \"\"\"Configure the build behavior by setting config variables.\n\n    Parameters\n    ----------\n    opt_level: int, default=2\n        Optimization level. See OPT_PASS_LEVEL for level of each pass.\n\n    add_pass: set of str\n        Optimization pass to be added regardless of optimization level.\n\n    Returns\n    -------\n    config: BuildConfig\n        The build configuration\n    \"\"\"\n    return BuildConfig(**kwargs)\n\n\ndef _bind_params_by_name(func, params):\n    \"\"\"Bind parameters of function by its name.\"\"\"\n    name_dict = {}\n    for arg in func.params:\n        name = arg.name_hint\n        if name in name_dict:\n            name_dict[name] = None\n        else:\n            name_dict[name] = arg\n    bind_dict = {}\n    for k, v in params.items():\n        if k not in name_dict:\n            continue\n        arg = name_dict[k]\n        if arg is None:\n            raise ValueError(\"Multiple args in the function have name %s\" % k)\n        bind_dict[arg] = expr.const(v)\n    return expr.bind(func, bind_dict)\n\n\ndef optimize(func, params=None):\n    \"\"\"Perform target invariant optimizations.\n\n    Parameters\n    ----------\n    func : tvm.relay.Function\n        The input to optimization.\n\n    params : Optional[Dict[str, tvm.nd.NDArray]]\n        Input parameters to the graph that do not change\n        during inference time. used for constant folding.\n\n    Returns\n    -------\n    opt_func : tvm.relay.Function\n        The optimized version of the function.\n    \"\"\"\n    cfg = BuildConfig.current\n\n    # bind expressions\n    if params:\n        func = _bind_params_by_name(func, params)\n\n    if cfg.pass_enabled(\"SimplifyInference\"):\n        func = ir_pass.infer_type(func)\n        func = ir_pass.simplify_inference(func)\n\n    if cfg.pass_enabled(\"CombineParallelConv2D\"):\n        func = ir_pass.infer_type(func)\n        func = ir_pass.combine_parallel_conv2d(func)\n\n    if cfg.pass_enabled(\"FoldScaleAxis\"):\n        func = ir_pass.infer_type(func)\n        func = ir_pass.backward_fold_scale_axis(func)\n        func = ir_pass.infer_type(func)\n        func = ir_pass.forward_fold_scale_axis(func)\n\n    if cfg.pass_enabled(\"FoldConstant\"):\n        func = ir_pass.fold_constant(func)\n\n    if cfg.pass_enabled(\"AlterOpLayout\"):\n        func = ir_pass.infer_type(func)\n        func = ir_pass.canonicalize_ops(func)\n        func = ir_pass.infer_type(func)\n        func = ir_pass.alter_op_layout(func)\n\n    return func\n\n\ndef build(func,\n          target=None,\n          target_host=None,\n          params=None):\n    \"\"\"Build a function to run on TVM graph runtime.\n\n    Parameters\n    ----------\n    func: relay.Function\n        The function to build.\n\n    target : str or :any:`tvm.target.Target`, optional\n        The build target\n\n    target_host : str or :any:`tvm.target.Target` optional\n        Host compilation target, if target is device.\n        When TVM compiles device specific program such as CUDA,\n        we also need host(CPU) side code to interact with the driver\n        setup the dimensions and parameters correctly.\n        target_host is used to specify the host side codegen target.\n        By default, llvm is used if it is enabled,\n        otherwise a stackvm intepreter is used.\n\n    params : dict of str to NDArray\n        Input parameters to the graph that do not change\n        during inference time. Used for constant folding.\n\n    Returns\n    -------\n    graph_json : str\n        The json string that can be accepted by graph runtime.\n\n    mod : tvm.Module\n        The module containing necessary libraries.\n\n    params : dict\n        The parameters of the final graph.\n    \"\"\"\n    target = target if target else _target.current_target()\n    if target is None:\n        raise ValueError(\"Target is not set in env or passed as argument.\")\n    target = _target.create(target)\n\n    # If current dispatch context is fallback context (the default root context),\n    # then load pre-tuned parameters from TopHub\n    if isinstance(autotvm.DispatchContext.current, autotvm.FallbackContext):\n        tophub_context = autotvm.tophub.context(target)\n    else:\n        tophub_context = autotvm.util.EmptyContext()\n\n    cfg = BuildConfig.current\n\n    with tophub_context:\n        func = optimize(func, params)\n        # Fuse ops before running code gen\n        func = ir_pass.infer_type(func)\n        func = ir_pass.fuse_ops(func, cfg.opt_level)\n        # Graph code generation\n        func = ir_pass.infer_type(func)\n        graph_gen = _graph_gen.GraphRuntimeCodegen(mod=None, target=target)\n        graph_json, lowered_funcs, params = graph_gen.codegen(func)\n        mod = _tvm_build_module(lowered_funcs, target=target, target_host=target_host)\n    return graph_json, mod, params\n\n\nclass GraphExecutor(_interpreter.Executor):\n    \"\"\"Wrapper around Executor interface.\n\n    This executor is used for debug and testing purpoes.\n\n    Parameters\n    ----------\n    mod : :py:class:`~tvm.relay.module.Module`\n        The module to support the execution.\n\n    ctx : :py:class:`TVMContext`\n        The runtime context to run the code on.\n\n    target : :py:class:`Target`\n        The target option to build the function.\n    \"\"\"\n    def __init__(self, mod, ctx, target):\n        self.mod = mod\n        self.ctx = ctx\n        self.target = target\n\n    def _make_executor(self, func):\n        graph_json, mod, params = build(func, target=self.target)\n        gmodule = _graph_rt.create(graph_json, mod, self.ctx)\n        if params:\n            gmodule.set_input(*params)\n        def _graph_wrapper(*args):\n            # Create map of inputs.\n            for i, arg in enumerate(args):\n                gmodule.set_input(i, arg)\n            # Run the module, and fetch the output.\n            gmodule.run()\n            # make a copy so multiple invocation won't hurt perf.\n            return gmodule.get_output(0).copyto(_nd.cpu(0))\n\n        return _graph_wrapper\n\n\ndef create_executor(kind=\"debug\",\n                    mod=None,\n                    ctx=None,\n                    target=\"llvm\"):\n    \"\"\"Factory function to create an executor.\n\n    Parameters\n    ----------\n    kind : str\n        The type of executor\n\n    mod : :py:class:`~tvm.relay.module.Module`\n        The Relay module containing collection of functions\n\n    ctx : :py:class:`tvm.TVMContext`\n        The context to execute the code.\n\n    target : :py:class:`tvm.Target`\n        The corresponding context\n    \"\"\"\n    if ctx is not None:\n        assert ctx.device_type == _nd.context(str(target), 0).device_type\n    else:\n        ctx = _nd.context(str(target), 0)\n\n    if isinstance(target, str):\n        target = _target.create(target)\n    if kind == \"debug\":\n        return _interpreter.Interpreter(mod, ctx, target)\n    elif kind == \"graph\":\n        return GraphExecutor(mod, ctx, target)\n    else:\n        raise RuntimeError(\"unknown mode {0}\".format(mode))\n", "path": "python/tvm/relay/build_module.py"}], "after_files": [{"content": "\"\"\"\nConstruct the necessary state for the TVM graph runtime\nfrom a Relay expression.\n\"\"\"\nfrom ..build_module import build as _tvm_build_module\nfrom .. import nd as _nd, target as _target, autotvm\nfrom ..contrib import graph_runtime as _graph_rt\nfrom . import ir_pass\nfrom . import expr\nfrom .backend import interpreter as _interpreter\nfrom .backend import graph_runtime_codegen as _graph_gen\n\n# List of optimization pass and level when switch on\nOPT_PASS_LEVEL = {\n    \"SimplifyInference\": 0,\n    \"OpFusion\": 1,\n    \"FoldConstant\": 2,\n    \"CombineParallelConv2D\": 3,\n    \"FoldScaleAxis\": 3,\n    \"AlterOpLayout\": 3,\n}\n\nclass BuildConfig(object):\n    \"\"\"Configuration scope to set a build config option.\n\n    Parameters\n    ----------\n    kwargs\n        Keyword arguments of configurations to set.\n    \"\"\"\n    current = None\n    defaults = {\n        \"opt_level\": 2,\n        \"add_pass\": None,\n    }\n    def __init__(self, **kwargs):\n        self._old_scope = None\n        for k, _ in kwargs.items():\n            if k not in BuildConfig.defaults:\n                raise ValueError(\n                    \"invalid argument %s, candidates are %s\" % (k, BuildConfig.defaults.keys()))\n        self._attr = kwargs\n\n    def __getattr__(self, name):\n        if name not in self._attr:\n            return BuildConfig.defaults[name]\n        return self._attr[name]\n\n    def __enter__(self):\n        # pylint: disable=protected-access\n        self._old_scope = BuildConfig.current\n        attr = BuildConfig.current._attr.copy()\n        attr.update(self._attr)\n        self._attr = attr\n        BuildConfig.current = self\n        return self\n\n    def __exit__(self, ptype, value, trace):\n        assert self._old_scope\n        BuildConfig.current = self._old_scope\n\n    def pass_enabled(self, pass_name):\n        \"\"\"Get whether pass is enabled.\n\n        Parameters\n        ----------\n        pass_name : str\n            The optimization pass name\n\n        Returns\n        -------\n        enabled : bool\n            Whether pass is enabled.\n        \"\"\"\n        if self.add_pass and pass_name in self.add_pass:\n            return True\n        return self.opt_level >= OPT_PASS_LEVEL[pass_name]\n\n\nBuildConfig.current = BuildConfig()\n\n\ndef build_config(**kwargs):\n    \"\"\"Configure the build behavior by setting config variables.\n\n    Parameters\n    ----------\n    opt_level: int, default=2\n        Optimization level. See OPT_PASS_LEVEL for level of each pass.\n\n    add_pass: set of str\n        Optimization pass to be added regardless of optimization level.\n\n    Returns\n    -------\n    config: BuildConfig\n        The build configuration\n    \"\"\"\n    return BuildConfig(**kwargs)\n\n\ndef _bind_params_by_name(func, params):\n    \"\"\"Bind parameters of function by its name.\"\"\"\n    name_dict = {}\n    for arg in func.params:\n        name = arg.name_hint\n        if name in name_dict:\n            name_dict[name] = None\n        else:\n            name_dict[name] = arg\n    bind_dict = {}\n    for k, v in params.items():\n        if k not in name_dict:\n            continue\n        arg = name_dict[k]\n        if arg is None:\n            raise ValueError(\"Multiple args in the function have name %s\" % k)\n        bind_dict[arg] = expr.const(v)\n    return expr.bind(func, bind_dict)\n\n\ndef optimize(func, params=None):\n    \"\"\"Perform target invariant optimizations.\n\n    Parameters\n    ----------\n    func : tvm.relay.Function\n        The input to optimization.\n\n    params : Optional[Dict[str, tvm.nd.NDArray]]\n        Input parameters to the graph that do not change\n        during inference time. used for constant folding.\n\n    Returns\n    -------\n    opt_func : tvm.relay.Function\n        The optimized version of the function.\n    \"\"\"\n    cfg = BuildConfig.current\n\n    # bind expressions\n    if params:\n        func = _bind_params_by_name(func, params)\n\n    if cfg.pass_enabled(\"SimplifyInference\"):\n        func = ir_pass.infer_type(func)\n        func = ir_pass.simplify_inference(func)\n\n    if cfg.pass_enabled(\"CombineParallelConv2D\"):\n        func = ir_pass.infer_type(func)\n        func = ir_pass.combine_parallel_conv2d(func)\n\n    if cfg.pass_enabled(\"FoldConstant\"):\n        func = ir_pass.fold_constant(func)\n\n    if cfg.pass_enabled(\"FoldScaleAxis\"):\n        func = ir_pass.infer_type(func)\n        func = ir_pass.backward_fold_scale_axis(func)\n        func = ir_pass.infer_type(func)\n        func = ir_pass.forward_fold_scale_axis(func)\n        func = ir_pass.fold_constant(func)\n\n    if cfg.pass_enabled(\"AlterOpLayout\"):\n        func = ir_pass.infer_type(func)\n        func = ir_pass.canonicalize_ops(func)\n        func = ir_pass.infer_type(func)\n        func = ir_pass.alter_op_layout(func)\n\n    return func\n\n\ndef build(func,\n          target=None,\n          target_host=None,\n          params=None):\n    \"\"\"Build a function to run on TVM graph runtime.\n\n    Parameters\n    ----------\n    func: relay.Function\n        The function to build.\n\n    target : str or :any:`tvm.target.Target`, optional\n        The build target\n\n    target_host : str or :any:`tvm.target.Target` optional\n        Host compilation target, if target is device.\n        When TVM compiles device specific program such as CUDA,\n        we also need host(CPU) side code to interact with the driver\n        setup the dimensions and parameters correctly.\n        target_host is used to specify the host side codegen target.\n        By default, llvm is used if it is enabled,\n        otherwise a stackvm intepreter is used.\n\n    params : dict of str to NDArray\n        Input parameters to the graph that do not change\n        during inference time. Used for constant folding.\n\n    Returns\n    -------\n    graph_json : str\n        The json string that can be accepted by graph runtime.\n\n    mod : tvm.Module\n        The module containing necessary libraries.\n\n    params : dict\n        The parameters of the final graph.\n    \"\"\"\n    target = target if target else _target.current_target()\n    if target is None:\n        raise ValueError(\"Target is not set in env or passed as argument.\")\n    target = _target.create(target)\n\n    # If current dispatch context is fallback context (the default root context),\n    # then load pre-tuned parameters from TopHub\n    if isinstance(autotvm.DispatchContext.current, autotvm.FallbackContext):\n        tophub_context = autotvm.tophub.context(target)\n    else:\n        tophub_context = autotvm.util.EmptyContext()\n\n    cfg = BuildConfig.current\n\n    with tophub_context:\n        func = optimize(func, params)\n        # Fuse ops before running code gen\n        func = ir_pass.infer_type(func)\n        func = ir_pass.fuse_ops(func, cfg.opt_level)\n        # Graph code generation\n        func = ir_pass.infer_type(func)\n        graph_gen = _graph_gen.GraphRuntimeCodegen(mod=None, target=target)\n        graph_json, lowered_funcs, params = graph_gen.codegen(func)\n        mod = _tvm_build_module(lowered_funcs, target=target, target_host=target_host)\n    return graph_json, mod, params\n\n\nclass GraphExecutor(_interpreter.Executor):\n    \"\"\"Wrapper around Executor interface.\n\n    This executor is used for debug and testing purpoes.\n\n    Parameters\n    ----------\n    mod : :py:class:`~tvm.relay.module.Module`\n        The module to support the execution.\n\n    ctx : :py:class:`TVMContext`\n        The runtime context to run the code on.\n\n    target : :py:class:`Target`\n        The target option to build the function.\n    \"\"\"\n    def __init__(self, mod, ctx, target):\n        self.mod = mod\n        self.ctx = ctx\n        self.target = target\n\n    def _make_executor(self, func):\n        graph_json, mod, params = build(func, target=self.target)\n        gmodule = _graph_rt.create(graph_json, mod, self.ctx)\n        if params:\n            gmodule.set_input(*params)\n        def _graph_wrapper(*args):\n            # Create map of inputs.\n            for i, arg in enumerate(args):\n                gmodule.set_input(i, arg)\n            # Run the module, and fetch the output.\n            gmodule.run()\n            # make a copy so multiple invocation won't hurt perf.\n            return gmodule.get_output(0).copyto(_nd.cpu(0))\n\n        return _graph_wrapper\n\n\ndef create_executor(kind=\"debug\",\n                    mod=None,\n                    ctx=None,\n                    target=\"llvm\"):\n    \"\"\"Factory function to create an executor.\n\n    Parameters\n    ----------\n    kind : str\n        The type of executor\n\n    mod : :py:class:`~tvm.relay.module.Module`\n        The Relay module containing collection of functions\n\n    ctx : :py:class:`tvm.TVMContext`\n        The context to execute the code.\n\n    target : :py:class:`tvm.Target`\n        The corresponding context\n    \"\"\"\n    if ctx is not None:\n        assert ctx.device_type == _nd.context(str(target), 0).device_type\n    else:\n        ctx = _nd.context(str(target), 0)\n\n    if isinstance(target, str):\n        target = _target.create(target)\n    if kind == \"debug\":\n        return _interpreter.Interpreter(mod, ctx, target)\n    elif kind == \"graph\":\n        return GraphExecutor(mod, ctx, target)\n    else:\n        raise RuntimeError(\"unknown mode {0}\".format(mode))\n", "path": "python/tvm/relay/build_module.py"}]}