fuse_mlir.cpp 4.13 KB
Newer Older
Paul's avatar
Paul committed
1
2
3
4
5
#include <migraphx/gpu/fuse_mlir.hpp>
#include <migraphx/gpu/mlir.hpp>
#include <migraphx/matcher.hpp>
#include <migraphx/pass_manager.hpp>
#include <migraphx/make_op.hpp>
Paul's avatar
Paul committed
6
#include <migraphx/register_op.hpp>
Paul's avatar
Paul committed
7
8
9
10
11
12
13
14

namespace migraphx {
inline namespace MIGRAPHX_INLINE_NS {

struct module;

namespace gpu {

Paul's avatar
Paul committed
15
#ifdef MIGRAPHX_MLIR
Paul's avatar
Paul committed
16
17
18
19
20
21
22
23
24
25
26
struct mlir_conv
{
    operation op = make_op("convolution");

    template <class Self, class F>
    static auto reflect(Self& self, F f)
    {
        return pack(f(self.op, "op"));
    }

    std::string name() const { return "gpu::mlir_conv"; }
Paul's avatar
Paul committed
27
    shape compute_shape(std::vector<shape> inputs, const std::vector<module_ref>& mods) const
Paul's avatar
Paul committed
28
29
30
31
32
33
34
    {
        check_shapes{inputs, *this}.standard();
        if(mods.size() != 1)
            MIGRAPHX_THROW("should have one submodule.");
        if(inputs.size() < 2)
            MIGRAPHX_THROW("should have at least two inputs.");
        auto n = inputs.size();
Paul's avatar
Format  
Paul committed
35
        return op.compute_shape({inputs[n - 2], inputs[n - 1]});
Paul's avatar
Paul committed
36
37
38
39
    }
};
MIGRAPHX_REGISTER_OP(mlir_conv);

Paul's avatar
Paul committed
40
namespace {
Paul's avatar
Paul committed
41
42
43
struct find_conv_pointwise
{
    // Find a convolution followed by a pointwise operation.
Paul's avatar
Paul committed
44
    auto matcher() const
Paul's avatar
Paul committed
45
    {
Paul's avatar
Format  
Paul committed
46
47
48
        auto convolution =
            match::skip(match::name("contiguous"))(match::name("convolution").bind("convolution"));
        return match::name("pointwise")(match::any_of[match::inputs()](convolution.bind("x")));
Paul's avatar
Paul committed
49
50
    }

Paul's avatar
Paul committed
51
    void apply(module_pass_manager& mpm, const match::matcher_result& r) const
Paul's avatar
Paul committed
52
    {
Paul's avatar
Format  
Paul committed
53
        auto ins      = r.result;
Paul's avatar
Paul committed
54
        auto conv_ins = r.instructions["convolution"];
Paul's avatar
Format  
Paul committed
55
        auto x_ins    = r.instructions["x"]; // input after contiguous
Paul's avatar
Format  
Paul committed
56
        auto* pm      = ins->module_inputs().front();
Paul's avatar
Format  
Paul committed
57
        auto names    = pm->get_parameter_names();
Paul's avatar
Paul committed
58
        // Whitelist pointwise operators
Paul's avatar
Format  
Paul committed
59
60
61
62
        if(std::any_of(pm->begin(), pm->end(), [](const auto& i) {
               return not contains({"@literal", "@param", "@return", "convolution", "add", "relu"},
                                   i.name());
           }))
Paul's avatar
Paul committed
63
            return;
Paul's avatar
Paul committed
64
        // Only fuse with fp32 for now
Paul's avatar
Format  
Paul committed
65
66
67
        if(std::any_of(ins->inputs().begin(), ins->inputs().end(), [&](auto i) {
               return i->get_shape().type() != shape::type_t::float_type;
           }))
Paul's avatar
Paul committed
68
            return;
Paul's avatar
Paul committed
69
        std::sort(names.begin(), names.end());
Paul's avatar
Paul committed
70
71
        module_ref mm = mpm.create_module("mlir_" + pm->name());
        mm->set_bypass();
Paul's avatar
Paul committed
72
        std::unordered_map<instruction_ref, instruction_ref> param_map;
Paul's avatar
Paul committed
73
        auto x    = mm->add_parameter("x" + std::to_string(names.size()),
Paul's avatar
Format  
Paul committed
74
                                   conv_ins->inputs().at(0)->get_shape());
Paul's avatar
Paul committed
75
        auto w    = mm->add_parameter("x" + std::to_string(names.size() + 1),
Paul's avatar
Format  
Paul committed
76
                                   conv_ins->inputs().at(1)->get_shape());
Paul's avatar
Paul committed
77
        auto conv = mm->add_instruction(conv_ins->get_operator(), {x, w});
Paul's avatar
Format  
Paul committed
78
79
80
81
82
83
84
85
        std::transform(names.begin(),
                       names.end(),
                       ins->inputs().begin(),
                       std::inserter(param_map, param_map.end()),
                       [&](auto name, auto input) {
                           if(input == x_ins)
                               return std::make_pair(pm->get_parameter(name), conv);
                           return std::make_pair(pm->get_parameter(name),
Paul's avatar
Paul committed
86
                                                 mm->add_parameter(name, input->get_shape()));
Paul's avatar
Format  
Paul committed
87
                       });
Paul's avatar
Paul committed
88
        mm->add_return(mm->insert_module_instructions(mm->end(), pm, param_map));
Paul's avatar
Paul committed
89

Paul's avatar
Paul committed
90
        std::vector<instruction_ref> inputs;
Paul's avatar
Format  
Paul committed
91
92
93
94
        std::copy_if(ins->inputs().begin(),
                     ins->inputs().end(),
                     std::back_inserter(inputs),
                     [&](auto input) { return input != conv_ins; });
Paul's avatar
Paul committed
95
        inputs.insert(inputs.end(), conv_ins->inputs().begin(), conv_ins->inputs().end());
Paul's avatar
Paul committed
96
97
        mpm.get_module().replace_instruction(
            ins, mlir_conv{conv_ins->get_operator()}, inputs, {mm});
Paul's avatar
Paul committed
98
99
    }
};
Paul's avatar
Format  
Paul committed
100
} // namespace
Paul's avatar
Paul committed
101

Paul's avatar
Paul committed
102
103
#endif

Paul's avatar
Format  
Paul committed
104
105
void fuse_mlir::apply(module_pass_manager& mpm) const
{
Paul's avatar
Paul committed
106
#ifdef MIGRAPHX_MLIR
Paul's avatar
Format  
Paul committed
107
    match::find_matches(mpm, find_conv_pointwise{});
Paul's avatar
Paul committed
108
109
110
#else
    (void)mpm;
#endif
Paul's avatar
Format  
Paul committed
111
}
Paul's avatar
Paul committed
112

Paul's avatar
Format  
Paul committed
113
} // namespace gpu
Paul's avatar
Paul committed
114
115
116

} // namespace MIGRAPHX_INLINE_NS
} // namespace migraphx