pass.h 4.8 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

Y
Yan Chunwei 已提交
21 22 23 24 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
#include "lite/core/mir/node.h"
#include "lite/core/mir/ssa_graph.h"

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_; }

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

  // Bind targets. At runtime, there must be one device in the bound targets.
54
  void BindTargets(const std::set<TargetType>& targets) {
55 56 57 58 59 60
    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(),
61
                     std::inserter(bound_targets_, bound_targets_.begin()));
62 63 64 65
    }
  }

  // Exclude targets. At runtime, there must be one device in the bound targets.
66
  // Disable the pass if one of the valid devices is in the excluded targets.
67 68 69
  void ExcludeTargets(const std::set<TargetType>& targets) {
    for (const auto& target : targets) {
      const std::set<TargetType>& universe = ExpandValidTargets(target);
70 71 72 73 74 75 76 77 78 79 80 81 82 83
      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()));
84
    }
85
  }
86

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

  // 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);
    }
115 116
  }

Y
Yan Chunwei 已提交
117 118 119 120 121 122 123 124 125 126 127
  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;

 private:
  const Kind kind_;
  std::string name_;
  std::string doc_;
128
  std::set<TargetType> bound_targets_;
129
  std::set<TargetType> excluded_targets_;
130
  std::unordered_map<std::string, std::set<lite_api::Place>> bound_kernels_;
Y
Yan Chunwei 已提交
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
};

// 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