blob: c704bcbc466b1f0105fa649d97b3be7a1bcb0206 [file]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
/*!
*
* \file annotate.cc
*
* \brief Annotating the graph with simulated quantize operators.
*/
#include <tvm/relay/analysis.h>
#include <tvm/relay/transform.h>
#include "./quantize.h"
namespace tvm {
namespace relay {
namespace quantize {
using namespace relay::transform;
class QAnnotateExpr;
class QAnnotateExprNode : public TempExprNode {
public:
Expr expr;
QAnnotateKind kind;
void VisitAttrs(tvm::AttrVisitor* v) {
v->Visit("expr", &expr);
v->Visit("kind", &kind);
}
Expr Realize() const final;
static constexpr const char* _type_key = "relay.QAnnotateExpr";
TVM_DECLARE_FINAL_OBJECT_INFO(QAnnotateExprNode, TempExprNode);
};
class QAnnotateExpr : public TempExpr {
public:
/*!
* \brief The constructor
* \param expr The original relay expression.
* \param kind The annotation kind.
*/
TVM_DLL QAnnotateExpr(Expr expr, QAnnotateKind kind);
TVM_DEFINE_OBJECT_REF_METHODS(QAnnotateExpr, TempExpr, QAnnotateExprNode);
};
Expr QAnnotateExprNode::Realize() const { return expr; }
QAnnotateExpr::QAnnotateExpr(Expr expr, QAnnotateKind kind) {
auto rnode = make_object<QAnnotateExprNode>();
rnode->expr = std::move(expr);
rnode->kind = kind;
data_ = std::move(rnode);
}
TVM_REGISTER_GLOBAL("relay._quantize.make_annotate_expr").set_body_typed([](Expr expr, int kind) {
return QAnnotateExpr(expr, static_cast<QAnnotateKind>(kind));
});
Pass QuantizeAnnotate() {
// TODO(tvm-teams): since partition has added cast_hint in different
// branches, try to remove this in the future.
std::function<Expr(const Expr&)> fmulti_ref = [](const Expr& e) {
if (e->IsInstance<TempExprNode>()) {
const auto* n = e.as<QAnnotateExprNode>();
ICHECK(n);
const PackedFunc* f = runtime::Registry::Get("relay.quantize.attach_simulated_quantize");
Expr ret = (*f)(n->expr, static_cast<int>(kQInput));
return static_cast<Expr>(QAnnotateExpr(ret, kQInput));
}
return e;
};
runtime::TypedPackedFunc<Function(Function, IRModule, PassContext)> pass_func =
[=](Function f, IRModule m, PassContext pc) {
auto func = Downcast<Function>(ForwardRewrite(f, "FQAnnotateRewrite", nullptr, fmulti_ref));
auto new_params = func->params;
for (const auto& x : FreeVars(func)) {
new_params.push_back(x);
}
return WithFields(func, new_params);
};
return CreateFunctionPass(pass_func, 1, "QuantizeAnnotate", {});
}
TVM_REGISTER_GLOBAL("relay._quantize.QuantizeAnnotate").set_body_typed(QuantizeAnnotate);
TVM_REGISTER_NODE_TYPE(QAnnotateExprNode);
} // namespace quantize
} // namespace relay
} // namespace tvm