pass.h 5.6 KB
Newer Older
Y
Yan Chunwei 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
// Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#pragma once
#include <memory>
17
#include <set>
Y
Yan Chunwei 已提交
18
#include <string>
19
#include <unordered_map>
20
#include <vector>
21

Y
Yan Chunwei 已提交
22 23
#include "lite/core/mir/node.h"
#include "lite/core/mir/ssa_graph.h"
24
#include "lite/utils/varient.h"
Y
Yan Chunwei 已提交
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51

namespace paddle {
namespace lite {
namespace mir {

class Pass {
 public:
  // Some appoint here, one pass should be only one of the following kinds.
  enum class Kind {
    // Will modify the program/graph topology.
    kProgramWise = 0,
    // Will modify the statement, with the graph topology fixed.
    kStmtWise,
    // Will not modify the IR, just collect information or visualization.
    kDebug,
  };

  explicit Pass(Kind kind) : kind_(kind) {}

  virtual void Apply(const std::unique_ptr<SSAGraph>& graph) = 0;

  void set_name(const std::string& name) { name_ = name; }
  const std::string& name() const { return name_; }

  void set_doc(const std::string& doc) { doc_ = doc; }
  const std::string& doc() const { return doc_; }

52 53
  // Some passes only apply to qualified targets, which need to be explicitly
  // declared.
54 55

  // Bind targets. At runtime, there must be one device in the bound targets.
56
  void BindTargets(const std::set<TargetType>& targets) {
57 58 59 60 61 62
    for (const auto& target : targets) {
      const std::set<TargetType>& universe = ExpandValidTargets(target);
      std::set_union(bound_targets_.begin(),
                     bound_targets_.end(),
                     universe.begin(),
                     universe.end(),
63
                     std::inserter(bound_targets_, bound_targets_.begin()));
64 65 66 67
    }
  }

  // Exclude targets. At runtime, there must be one device in the bound targets.
68
  // Disable the pass if one of the valid devices is in the excluded targets.
69 70 71
  void ExcludeTargets(const std::set<TargetType>& targets) {
    for (const auto& target : targets) {
      const std::set<TargetType>& universe = ExpandValidTargets(target);
72 73 74 75 76 77 78 79 80 81 82 83 84 85
      std::set<TargetType> updated_bound_targets;
      std::set_difference(
          bound_targets_.begin(),
          bound_targets_.end(),
          universe.begin(),
          universe.end(),
          std::inserter(updated_bound_targets, updated_bound_targets.begin()));
      bound_targets_ = updated_bound_targets;
      std::set_union(
          excluded_targets_.begin(),
          excluded_targets_.end(),
          universe.begin(),
          universe.end(),
          std::inserter(excluded_targets_, excluded_targets_.begin()));
86
    }
87
  }
88

89
  // Get all bound targets.
90 91 92 93 94
  const std::set<TargetType>& BoundTargets() const { return bound_targets_; }
  // Get all excluded targets.
  const std::set<TargetType>& ExcludedTargets() const {
    return excluded_targets_;
  }
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116

  // Some passes are only available on qualified kernels and need to be
  // explicitly declared.
  // Bind kernels. All kernels bound at runtime must be registered.
  void BindKernels(
      const std::unordered_map<std::string, std::set<lite_api::Place>>&
          kernels) {
    bound_kernels_ = kernels;
  }
  // Get all bound kernels.
  const std::unordered_map<std::string, std::set<lite_api::Place>>&
  GetBoundKernels() const {
    return bound_kernels_;
  }
  // Add one kernel to the bound kernels.
  void BindKernel(const std::string& kernel_name,
                  const lite_api::Place& place) {
    if (!bound_kernels_.count(kernel_name)) {
      bound_kernels_.insert({kernel_name, {place}});
    } else {
      bound_kernels_.at(kernel_name).insert(place);
    }
117 118
  }

Y
Yan Chunwei 已提交
119 120 121 122 123 124 125
  Kind kind() const { return kind_; }
  bool is_debug_pass() const { return kind_ == Kind::kDebug; }
  bool is_program_pass() const { return kind_ == Kind::kProgramWise; }
  bool is_stmt_pass() const { return kind_ == Kind::kStmtWise; }

  virtual ~Pass() = default;

126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
  bool HasAttr(const std::string& attr_name) const {
    return pass_attrs_.count(attr_name) > 0;
  }

  // Set a pointer to the attribute. Specific pass itself takes ownership of the
  // attribute.
  template <typename AttrType>
  void SetAttr(const std::string& attr_name, const AttrType* attr) {
    VLOG(4) << "Setting the attribute " << attr_name << " for the pass "
            << name_;
    pass_attrs_[attr_name].set<const AttrType>(*attr);
  }

  // Get a reference to the attribute previously set.
  template <typename AttrType>
  const AttrType& GetAttr(const std::string& attr_name) const {
    CHECK(pass_attrs_.count(attr_name))
        << attr_name << " attr not register for pass " << name_;
    return pass_attrs_.at(attr_name).get<const AttrType>();
  }

Y
Yan Chunwei 已提交
147 148 149 150
 private:
  const Kind kind_;
  std::string name_;
  std::string doc_;
151
  std::set<TargetType> bound_targets_;
152
  std::set<TargetType> excluded_targets_;
153
  std::unordered_map<std::string, std::set<lite_api::Place>> bound_kernels_;
154 155
  std::unordered_map<std::string, variant<Node, std::vector<Node*>>>
      pass_attrs_;
Y
Yan Chunwei 已提交
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
};

// Different kinds.
class ProgramPass : public Pass {
 public:
  ProgramPass() : Pass(Kind::kProgramWise) {}
};

class StmtPass : public Pass {
 public:
  StmtPass() : Pass(Kind::kStmtWise) {}
};

class DebugPass : public Pass {
 public:
  DebugPass() : Pass(Kind::kDebug) {}
};

}  // namespace mir
}  // namespace lite
}  // namespace paddle