#include <algorithm>
#include <memory>
#include <set>
#include <string>
#include <vector>
#include "graph/interface/value.hpp"
#include "graph/backend/dnnl/passes/utils.hpp"
#include "graph/backend/dnnl/utils.hpp"
namespace dnnl {
namespace impl {
namespace graph {
namespace dnnl_impl {
namespace {
bool has_scratchpad(const op_t *op) {
const static std::set<op_kind_t> no_scratchpad_ops {
op_kind::_constant_scales,
op_kind::_constant_zps,
op_kind::_add_zps,
op_kind::_sub_zps,
op_kind::_to_group,
op_kind::_from_group,
op_kind::_permute,
op_kind::_squeeze,
op_kind::_unsqueeze,
op_kind::_transpose,
op_kind::_reshape,
op_kind::_gen_index,
op_kind::_mask,
};
const static std::set<op_kind_t> may_have_scratchpad_ops {
op_kind::_mul_scales,
op_kind::_reorder,
};
const op_kind_t kind = op->get_kind();
const bool no_scratchpad = no_scratchpad_ops.count(kind)
|| (may_have_scratchpad_ops.count(kind) && op->num_outputs() == 1);
return !no_scratchpad;
}
};
status_t constant_propagation(std::shared_ptr<subgraph_t> &sg) {
using op_t = op_t;
using ltw = logical_tensor_wrapper_t;
bool changed;
do {
changed = false;
auto ret = topo_order_visit(sg->get_output_ops(), [&](op_t *op) {
size_t scpad_num = has_scratchpad(op) ? 1 : 0;
bool all_inputs_are_constant = true;
for (const auto &in : op->get_input_values()) {
if (ltw(in->get_logical_tensor()).property_type()
!= property_type::constant) {
all_inputs_are_constant = false;
break;
}
}
bool all_outputs_are_constant = true;
for (size_t i = 0; i < op->num_outputs() - scpad_num; i++) {
auto out = op->get_output_value(i);
if (ltw(out->get_logical_tensor()).property_type()
!= property_type::constant) {
all_outputs_are_constant = false;
break;
}
}
const bool is_constant
= all_inputs_are_constant || all_outputs_are_constant;
op->set_attr<bool>(op_attr::is_constant, is_constant);
if (all_inputs_are_constant && !all_outputs_are_constant) {
for (size_t i = 0; i < op->num_outputs() - scpad_num; i++) {
auto out = op->get_output_value(i);
out->set_property(property_type::constant);
}
changed = changed || true;
} else if (!all_inputs_are_constant && all_outputs_are_constant) {
for (auto &in : op->get_input_values()) {
in->set_property(property_type::constant);
}
changed = changed || true;
} else {
changed = changed || false;
}
return status::success;
});
if (ret != status::success) return ret;
} while (changed);
auto sg_outs = sg->get_output_values();
for (auto &out : sg_outs) {
if (ltw(out->get_logical_tensor()).property_type()
!= property_type::constant)
continue;
out->set_property(property_type::variable);
out->get_producer().set_attr<bool>(op_attr::is_constant, false);
}
return status::success;
}
} } } }