tvm
transform.h
Go to the documentation of this file.
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied. See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
56 #ifndef TVM_IR_TRANSFORM_H_
57 #define TVM_IR_TRANSFORM_H_
58 
59 #include <tvm/ffi/container/array.h>
60 #include <tvm/ffi/function.h>
61 #include <tvm/ffi/reflection/creator.h>
62 #include <tvm/ffi/reflection/registry.h>
63 #include <tvm/ffi/string.h>
64 #include <tvm/ir/instrument.h>
65 #include <tvm/ir/module.h>
66 #include <tvm/ir/with_context.h>
67 
68 #include <string>
69 #include <type_traits>
70 #include <utility>
71 
72 namespace tvm {
73 namespace transform {
74 
80 class PassContextNode : public ffi::Object {
81  public:
83  int opt_level{2};
84 
86  ffi::Array<ffi::String> required_pass;
88  ffi::Array<ffi::String> disabled_pass;
90  ffi::Map<ffi::String, Any> config;
91 
93  ffi::Array<instrument::PassInstrument> instruments;
94 
95  PassContextNode() = default;
96 
108  template <typename TObjectRef>
109  ffi::Optional<TObjectRef> GetConfig(
110  const std::string& key,
111  ffi::Optional<TObjectRef> default_value = ffi::Optional<TObjectRef>(std::nullopt)) const {
112  if (!config.defined()) return default_value;
113  auto it = config.find(key);
114  if (it != config.end()) {
115  return (*it).second.as_or_throw<ffi::Optional<TObjectRef>>();
116  } else {
117  return default_value;
118  }
119  }
120  // variant that uses TObjectRef to enable implicit conversion to default value.
121  template <typename TObjectRef>
122  ffi::Optional<TObjectRef> GetConfig(const std::string& key, TObjectRef default_value) const {
123  return GetConfig<TObjectRef>(key, ffi::Optional<TObjectRef>(default_value));
124  }
125 
126  static void RegisterReflection() {
127  namespace refl = tvm::ffi::reflection;
128  refl::ObjectDef<PassContextNode>()
129  .def_ro("opt_level", &PassContextNode::opt_level)
130  .def_ro("required_pass", &PassContextNode::required_pass)
131  .def_ro("disabled_pass", &PassContextNode::disabled_pass)
132  .def_ro("instruments", &PassContextNode::instruments)
133  .def_ro("config", &PassContextNode::config);
134  }
135  TVM_FFI_DECLARE_OBJECT_INFO_FINAL("transform.PassContext", PassContextNode, ffi::Object);
136 };
137 
151 class PassContext : public ffi::ObjectRef {
152  public:
157  explicit PassContext(ffi::UnsafeInit tag) : ffi::ObjectRef(tag) {}
161  explicit PassContext(ffi::ObjectPtr<PassContextNode> n) : ffi::ObjectRef(n) {}
166  const PassContextNode* operator->() const {
167  TVM_FFI_ICHECK(get() != nullptr);
168  return static_cast<const PassContextNode*>(get());
169  }
175  TVM_FFI_ICHECK(get() != nullptr);
176  return static_cast<PassContextNode*>(get_mutable());
177  }
178 
183  TVM_DLL static PassContext Create();
188  TVM_DLL static PassContext Current();
189 
194  TVM_DLL static ffi::Map<ffi::String, ffi::Map<ffi::String, ffi::String>> ListConfigs();
195 
202 
209 
220  TVM_DLL bool InstrumentBeforePass(const IRModule& mod, const PassInfo& info) const;
221 
230  TVM_DLL void InstrumentAfterPass(const IRModule& mod, const PassInfo& info) const;
231 
237  TVM_DLL bool PassEnabled(const PassInfo& info) const;
238 
245  template <typename ValueType>
246  static int32_t RegisterConfigOption(const char* key) {
247  // NOTE: we could further update the function later.
248  if constexpr (std::is_base_of_v<ffi::ObjectRef, ValueType>) {
249  int32_t tindex = ffi::TypeToRuntimeTypeIndex<ValueType>::v();
250  auto type_key = ffi::TypeIndexToTypeKey(tindex);
251  auto legalization = [=](ffi::Any value) -> ffi::Any {
252  if (auto opt_map = value.try_cast<ffi::Map<ffi::String, ffi::Any>>()) {
253  return ffi::reflection::ObjectCreator(type_key)(opt_map.value());
254  } else {
255  auto opt_val = value.try_cast<ValueType>();
256  if (!opt_val.has_value()) {
257  TVM_FFI_THROW(AttributeError)
258  << "Expect config " << key << " to have type " << type_key << ", but instead get "
259  << ffi::details::AnyUnsafe::GetMismatchTypeInfo<ValueType>(value);
260  }
261  return *opt_val;
262  }
263  };
264  RegisterConfigOption(key, type_key, legalization);
265  } else {
266  // non-object type, do not support implicit conversion from map
267  std::string type_str = ffi::TypeTraits<ValueType>::TypeStr();
268  auto legalization = [=](ffi::Any value) -> ffi::Any {
269  auto opt_val = value.try_cast<ValueType>();
270  if (!opt_val.has_value()) {
271  TVM_FFI_THROW(AttributeError)
272  << "Expect config " << key << " to have type " << type_str << ", but instead get "
273  << ffi::details::AnyUnsafe::GetMismatchTypeInfo<ValueType>(value);
274  } else {
275  return *opt_val;
276  }
277  };
278  RegisterConfigOption(key, type_str, legalization);
279  }
280  return 0;
281  }
282 
283  // accessor.
285  class Internal;
286 
287  private:
288  // The entry of a pass context scope.
289  TVM_DLL void EnterWithScope();
290  // The exit of a pass context scope.
291  TVM_DLL void ExitWithScope();
292  // Register configuration key value type.
293  TVM_DLL static void RegisterConfigOption(const char* key, ffi::String value_type_str,
294  std::function<ffi::Any(ffi::Any)> legalization);
295 
296  // Classes to get the Python `with` like syntax.
297  friend class Internal;
298  friend class With<PassContext>;
299 };
300 
307 template <typename TConfig>
308 inline TConfig PassConfigWithDefaults() {
309  static_assert(std::is_base_of_v<ffi::ObjectRef, TConfig>,
310  "Can only create ObjectRef-derived types");
311  using ContainerType = typename TConfig::ContainerType;
312  static auto finit_object = ffi::Function::GetGlobalRequired("ffi.MakeObjectFromPackedArgs");
313  ffi::AnyView packed_args[1];
314  packed_args[0] = ContainerType::RuntimeTypeIndex();
315  ffi::Any rv;
316  finit_object.CallPacked(ffi::PackedArgs(packed_args, 1), &rv);
317  return rv.cast<TConfig>();
318 }
319 
320 #define TVM_PASS_CTX_CONFIG_VAR_DEF [[maybe_unused]] static uint32_t __make_PassContext_tid
321 
328 #define TVM_REGISTER_PASS_CONFIG_OPTION(Key, ValueType) \
329  TVM_FFI_STR_CONCAT(TVM_PASS_CTX_CONFIG_VAR_DEF, __COUNTER__) = \
330  ::tvm::transform::PassContext::RegisterConfigOption<ValueType>(Key)
331 
336 class PassInfoNode : public ffi::Object {
337  public:
340 
342  ffi::String name;
343 
345  bool traceable;
346 
348  ffi::Array<ffi::String> required;
349 
350  PassInfoNode() = default;
351 
352  static void RegisterReflection() {
353  namespace refl = tvm::ffi::reflection;
354  refl::ObjectDef<PassInfoNode>()
355  .def_ro("opt_level", &PassInfoNode::opt_level)
356  .def_ro("name", &PassInfoNode::name)
357  .def_ro("required", &PassInfoNode::required)
358  .def_ro("traceable", &PassInfoNode::traceable);
359  }
360  TVM_FFI_DECLARE_OBJECT_INFO_FINAL("transform.PassInfo", PassInfoNode, ffi::Object);
361 };
362 
367 class PassInfo : public ffi::ObjectRef {
368  public:
376  TVM_DLL PassInfo(int opt_level, ffi::String name, ffi::Array<ffi::String> required,
377  bool traceable);
378 
380 };
381 
387 class PassNode : public ffi::Object {
388  public:
389  virtual ~PassNode() {}
392  virtual PassInfo Info() const = 0;
393 
402  return this->operator()(std::move(mod), PassContext::Current());
403  }
404 
413  virtual IRModule operator()(IRModule mod, const PassContext& pass_ctx) const = 0;
414  TVM_FFI_DECLARE_OBJECT_INFO("transform.Pass", PassNode, ffi::Object);
415 };
416 
417 class Pass : public ffi::ObjectRef {
418  public:
435 
444  IRModule operator()(IRModule mod, const PassContext& pass_ctx) const;
445 
447 
448  private:
449  IRModule static AssertImmutableModule(const IRModule& mod, const PassNode* node,
450  const PassContext& pass_ctx);
451 };
452 
461 class SequentialNode : public PassNode {
462  public:
463  /* \brief The pass meta data.*/
465 
467  tvm::ffi::Array<Pass> passes;
468 
469  static void RegisterReflection() {
470  namespace refl = tvm::ffi::reflection;
471  refl::ObjectDef<SequentialNode>()
472  .def_ro("pass_info", &SequentialNode::pass_info)
473  .def_ro("passes", &SequentialNode::passes);
474  }
475 
479  PassInfo Info() const override { return pass_info; }
480 
492 
504  IRModule operator()(IRModule mod, const PassContext& pass_ctx) const final;
506 };
507 
508 class Sequential : public Pass {
509  public:
516  TVM_DLL Sequential(ffi::Array<Pass> passes, PassInfo pass_info);
517 
526  TVM_DLL Sequential(ffi::Array<Pass> passes, ffi::String name = "sequential");
527 
528  Sequential() = default;
529  explicit Sequential(ffi::ObjectPtr<SequentialNode> n) : Pass(n) {}
530 
531  const SequentialNode* operator->() const;
533 };
534 
535 /*
536  * \brief Create a module pass.
537  *
538  * \param pass_func The packed function that contains the optimization.
539  * \param opt_level The optimization level of the module pass.
540  * \param name The name of the module pass.
541  * \param required The list of the passes that the module pass is dependent on.
542  *
543  * \return The created module pass.
544  */
545 TVM_DLL Pass CreateModulePass(std::function<IRModule(IRModule, PassContext)> pass_func,
546  int opt_level, ffi::String name, ffi::Array<ffi::String> required,
547  bool traceable = false);
548 
554 TVM_DLL Pass PrintIR(ffi::String header = "");
555 
577 TVM_DLL ffi::Error EnrichPassErrorWithContext(
578  const ffi::Error& err, const IRModule& mod, ffi::String pass_name,
579  ffi::Optional<GlobalVar> func = ffi::Optional<GlobalVar>(std::nullopt));
580 
581 } // namespace transform
582 } // namespace tvm
583 
584 #endif // TVM_IR_TRANSFORM_H_
Managed reference class to IRModuleNode.
Definition: module.h:255
RAII wrapper function to enter and exit a context object similar to python's with syntax.
Definition: with_context.h:59
PassContextNode contains the information that a pass can rely on, such as analysis results.
Definition: transform.h:80
ffi::Map< ffi::String, Any > config
Pass specific configurations.
Definition: transform.h:90
ffi::Array< ffi::String > disabled_pass
The list of disabled passes.
Definition: transform.h:88
ffi::Array< instrument::PassInstrument > instruments
A list of pass instrument implementations.
Definition: transform.h:93
ffi::Optional< TObjectRef > GetConfig(const std::string &key, ffi::Optional< TObjectRef > default_value=ffi::Optional< TObjectRef >(std::nullopt)) const
Get a config value from the pass context.
Definition: transform.h:109
ffi::Optional< TObjectRef > GetConfig(const std::string &key, TObjectRef default_value) const
Definition: transform.h:122
TVM_FFI_DECLARE_OBJECT_INFO_FINAL("transform.PassContext", PassContextNode, ffi::Object)
static void RegisterReflection()
Definition: transform.h:126
int opt_level
The default optimization level.
Definition: transform.h:83
ffi::Array< ffi::String > required_pass
The list of required passes.
Definition: transform.h:86
PassContext that is used to configure the pass behavior.
Definition: transform.h:151
const PassContextNode * operator->() const
const accessor.
Definition: transform.h:166
static PassContext Current()
Get the default pass context in the current scope.
bool PassEnabled(const PassInfo &info) const
Check whether a pass is enabled.
static ffi::Map< ffi::String, ffi::Map< ffi::String, ffi::String > > ListConfigs()
Get all supported configuration names and metadata, registered within the PassContext.
friend class Internal
Definition: transform.h:297
PassContext()
Definition: transform.h:153
static int32_t RegisterConfigOption(const char *key)
Register a valid configuration option and its ValueType for validation.
Definition: transform.h:246
static PassContext Create()
Construct a PassContext containing the default configurations.
PassContextNode * operator->()
mutable accessor.
Definition: transform.h:174
void InstrumentEnterPassContext()
Call instrument implementations' callbacks when entering PassContext. The callbacks are called in ord...
void InstrumentExitPassContext()
Call instrument implementations' callbacks when exiting PassContext. The callbacks are called in orde...
PassContext(ffi::ObjectPtr< PassContextNode > n)
constructor with ffi::ObjectPtr
Definition: transform.h:161
PassContext(ffi::UnsafeInit tag)
constructor with UnsafeInit
Definition: transform.h:157
bool InstrumentBeforePass(const IRModule &mod, const PassInfo &info) const
Call instrument implementations' callbacks before a pass run. The callbacks are called in order,...
void InstrumentAfterPass(const IRModule &mod, const PassInfo &info) const
Call instrument implementations callbacks after a pass run. The callbacks are called in order,...
Meta data that will be used to help optimization and analysis.
Definition: transform.h:336
ffi::String name
The name of an optimization/analysis pass.
Definition: transform.h:342
bool traceable
Boolean that tells whether this pass will be traced or not.
Definition: transform.h:345
static void RegisterReflection()
Definition: transform.h:352
int opt_level
The minimal optimization level that this pass will be enabled.
Definition: transform.h:339
ffi::Array< ffi::String > required
The passes that are required to perform the current pass.
Definition: transform.h:348
TVM_FFI_DECLARE_OBJECT_INFO_FINAL("transform.PassInfo", PassInfoNode, ffi::Object)
Managed reference class for PassInfoNode.
Definition: transform.h:367
TVM_FFI_DEFINE_OBJECT_REF_METHODS_NULLABLE(PassInfo, ffi::ObjectRef, PassInfoNode)
PassInfo(int opt_level, ffi::String name, ffi::Array< ffi::String > required, bool traceable)
Constructor.
PassNode is the base type of differnt types of optimization passes. It is designed as a pure class an...
Definition: transform.h:387
virtual IRModule operator()(IRModule mod, const PassContext &pass_ctx) const =0
Transform mod using a functor under a given pass context.
TVM_FFI_DECLARE_OBJECT_INFO("transform.Pass", PassNode, ffi::Object)
IRModule operator()(IRModule mod) const
Transform mod using the default PassContext in the current scope.
Definition: transform.h:401
virtual PassInfo Info() const =0
Get the pass information/meta data.
virtual ~PassNode()
Definition: transform.h:389
Definition: transform.h:417
TVM_FFI_DEFINE_OBJECT_REF_METHODS_NULLABLE(Pass, ffi::ObjectRef, PassNode)
IRModule operator()(IRModule mod, const PassContext &pass_ctx) const
Transform mod using a functor under a given pass context.
IRModule operator()(IRModule mod) const
Transform mod using the default PassContext in the current scope.
The SequentialNode contains a set of passes that transform Relax programs from one AST to another sem...
Definition: transform.h:461
static void RegisterReflection()
Definition: transform.h:469
PassInfo Info() const override
Get the pass information/meta data.
Definition: transform.h:479
void ResolveDependency(const IRModule &mod)
Resolve the pass dependency. It globs all required passes by a given pass and executes them.
IRModule operator()(IRModule mod, const PassContext &pass_ctx) const final
Perform optimizations on a series of passes. The aforementioned typical pass manager jobs could be do...
tvm::ffi::Array< Pass > passes
A list of passes that used to compose a sequential pass.
Definition: transform.h:467
TVM_FFI_DECLARE_OBJECT_INFO_FINAL("transform.Sequential", SequentialNode, PassNode)
PassInfo pass_info
Definition: transform.h:464
Definition: transform.h:508
Sequential(ffi::Array< Pass > passes, ffi::String name="sequential")
The constructor of Sequential.
const SequentialNode * operator->() const
Sequential(ffi::ObjectPtr< SequentialNode > n)
Definition: transform.h:529
Sequential(ffi::Array< Pass > passes, PassInfo pass_info)
The constructor of Sequential.
IRModule that holds the functions and type definitions.
IRModuleFrame IRModule()
The IRModule declaration statement.
Definition: module.h:248
tvm::PrimExpr mod(const tvm::PrimExpr &a, const tvm::PrimExpr &b)
Definition: broadcast.h:310
Pass PrintIR(ffi::String header="")
A special trace pass that prints the header and IR to LOG(INFO).
ffi::Error EnrichPassErrorWithContext(const ffi::Error &err, const IRModule &mod, ffi::String pass_name, ffi::Optional< GlobalVar > func=ffi::Optional< GlobalVar >(std::nullopt))
Enrich a pass-time error with a TVMScript-rendered, underlined source location derived from the error...
Pass CreateModulePass(std::function< IRModule(IRModule, PassContext)> pass_func, int opt_level, ffi::String name, ffi::Array< ffi::String > required, bool traceable=false)
TConfig PassConfigWithDefaults()
Create a pass-config object with all default values, using the reflection defaults.
Definition: transform.h:308
An object that builds and maintains block scope and StmtSref mapping for Dependence analysis.
Definition: analyzer.h:40
RAII wrapper function to enter and exit a context object similar to python's with syntax.