eliminate_concat_test.cpp 15 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2015-2022 Advanced Micro Devices, Inc. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
Paul's avatar
Paul committed
24
25
#include <migraphx/eliminate_concat.hpp>
#include <migraphx/dead_code_elimination.hpp>
26
#include <migraphx/pass_manager.hpp>
27
28
29
#include <migraphx/op/concat.hpp>
#include <migraphx/op/load.hpp>
#include <migraphx/op/identity.hpp>
Shucai Xiao's avatar
Shucai Xiao committed
30
31
#include <migraphx/op/normalize_attribute.hpp>
#include <migraphx/normalize_attributes.hpp>
32
33
34
35
36
#include <basic_ops.hpp>
#include <test.hpp>

struct concat
{
Scott Thornton's avatar
Scott Thornton committed
37
    concat(std::size_t axis) { op.axis = axis; }
Paul's avatar
Paul committed
38
    migraphx::op::concat op;
39
40
41
42
43
44
45

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

Shucai Xiao's avatar
Shucai Xiao committed
46
47
48
49
50
51
52
    migraphx::value attributes() const
    {
        migraphx::value normalize;
        normalize["axis"] = migraphx::value::array{migraphx::op::normalize_attribute::include_min};
        return {{"normalize_axes", normalize}};
    }

53
    std::string name() const { return "eliminate_concat::concat"; }
Shucai Xiao's avatar
Shucai Xiao committed
54
    migraphx::shape normalize_compute_shape(std::vector<migraphx::shape> inputs) const
55
    {
56
        inputs.pop_back();
Shucai Xiao's avatar
Shucai Xiao committed
57
        return op.normalize_compute_shape(std::move(inputs));
58
    }
Paul's avatar
Paul committed
59
    migraphx::argument compute(migraphx::context&,
Paul's avatar
Paul committed
60
61
                               const migraphx::shape& output_shape,
                               const std::vector<migraphx::argument>&) const
62
63
64
65
66
    {
        return {output_shape};
    }
};

Scott Thornton's avatar
Scott Thornton committed
67
struct concat_test_optimization
68
69
{
    /// A unique name used to identify the concat optimization
Scott Thornton's avatar
Scott Thornton committed
70
    std::string name() const { return "eliminate_concat::concat"; }
71
    /// A unique name used to identify the allocate operator
Scott Thornton's avatar
Scott Thornton committed
72
    std::string allocate() const { return "allocate"; }
73
    /// Return the lowered concat operator
Paul's avatar
Paul committed
74
    migraphx::op::concat get_concat(const migraphx::operation& op) const
75
    {
Paul's avatar
Paul committed
76
        return migraphx::any_cast<concat>(op).op;
77
78
79
    }
};

Paul Fultz II's avatar
Paul Fultz II committed
80
void run_pass(migraphx::module& m)
81
{
Paul Fultz II's avatar
Paul Fultz II committed
82
    migraphx::run_passes(m,
83
84
85
                         {migraphx::eliminate_concat{concat_test_optimization{}},
                          migraphx::dead_code_elimination{}});
}
86
87
88

struct allocate
{
Paul's avatar
Paul committed
89
    migraphx::shape s{};
90
91
92
93
94
95
96

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

97
    std::string name() const { return "allocate"; }
Paul's avatar
Paul committed
98
    migraphx::shape compute_shape(const std::vector<migraphx::shape>& inputs) const
99
    {
100
        migraphx::check_shapes{inputs, *this}.has(0);
101
102
        return s;
    }
Paul's avatar
Paul committed
103
    migraphx::argument compute(migraphx::context&,
Paul's avatar
Paul committed
104
105
                               const migraphx::shape& output_shape,
                               const std::vector<migraphx::argument>&) const
106
107
108
109
110
    {
        return {output_shape};
    }
};

Paul's avatar
Paul committed
111
struct simple_op
112
{
Paul's avatar
Paul committed
113
    std::string name() const { return "simple_op"; }
Paul's avatar
Paul committed
114
    migraphx::shape compute_shape(const std::vector<migraphx::shape>& inputs) const
115
    {
116
        migraphx::check_shapes{inputs, *this}.has(1);
117
118
        return inputs.at(0);
    }
Paul's avatar
Paul committed
119
    migraphx::argument compute(migraphx::context&,
Paul's avatar
Paul committed
120
121
                               const migraphx::shape&,
                               const std::vector<migraphx::argument>& args) const
122
123
124
    {
        return args.at(0);
    }
Paul's avatar
Paul committed
125
    int output_alias(const std::vector<migraphx::shape>&) const { return 0; }
126
127
};

Paul's avatar
Paul committed
128
template <class... Ts>
Paul's avatar
Paul committed
129
130
131
132
133
migraphx::shape create_shape(Ts... xs)
{
    return migraphx::shape{migraphx::shape::float_type, {std::size_t(xs)...}};
}

Paul's avatar
Paul committed
134
using load     = migraphx::op::load;
Paul's avatar
Paul committed
135
136
137
138
139
using identity = migraphx::op::identity;

TEST_CASE(simple)
{
    auto create_test_program = [] {
Paul Fultz II's avatar
Paul Fultz II committed
140
        migraphx::module m;
141

Paul Fultz II's avatar
Paul Fultz II committed
142
143
144
145
        auto a1          = m.add_instruction(allocate{create_shape(1)});
        auto m1          = m.add_instruction(simple_op{}, a1);
        auto a2          = m.add_instruction(allocate{create_shape(1)});
        auto m2          = m.add_instruction(simple_op{}, a2);
Paul's avatar
Paul committed
146
        std::size_t axis = 0;
Paul Fultz II's avatar
Paul Fultz II committed
147
148
149
        auto a3          = m.add_instruction(allocate{create_shape(2)});
        m.add_instruction(concat(axis), m1, m2, a3);
        return m;
Paul's avatar
Paul committed
150
151
    };
    auto create_control_program = [] {
Paul Fultz II's avatar
Paul Fultz II committed
152
153
154
155
156
157
158
159
160
        migraphx::module m;

        auto a1 = m.add_instruction(allocate{create_shape(2)});
        auto l1 = m.add_instruction(load{create_shape(1), 0}, a1);
        auto m1 = m.add_instruction(simple_op{}, l1);
        auto l2 = m.add_instruction(load{create_shape(1), 4}, a1);
        auto m2 = m.add_instruction(simple_op{}, l2);
        m.add_instruction(identity{}, a1, m1, m2);
        return m;
Paul's avatar
Paul committed
161
162
    };

Paul Fultz II's avatar
Paul Fultz II committed
163
164
165
    auto m1 = create_test_program();
    auto m2 = create_control_program();
    run_pass(m1);
Paul's avatar
Paul committed
166

Paul Fultz II's avatar
Paul Fultz II committed
167
    EXPECT(m1 == m2);
Paul's avatar
Paul committed
168
169
}

170
171
172
TEST_CASE(negative_axis1)
{
    auto create_test_program = [] {
Paul Fultz II's avatar
Paul Fultz II committed
173
        migraphx::module m;
174

Paul Fultz II's avatar
Paul Fultz II committed
175
176
177
178
        auto a1          = m.add_instruction(allocate{create_shape(2, 2)});
        auto m1          = m.add_instruction(simple_op{}, a1);
        auto a2          = m.add_instruction(allocate{create_shape(2, 2)});
        auto m2          = m.add_instruction(simple_op{}, a2);
179
        std::size_t axis = -1;
Paul Fultz II's avatar
Paul Fultz II committed
180
181
182
        auto a3          = m.add_instruction(allocate{create_shape(4, 2)});
        m.add_instruction(concat(axis), m1, m2, a3);
        return m;
183
184
185
    };
    auto create_control_program = create_test_program;

Paul Fultz II's avatar
Paul Fultz II committed
186
187
188
    auto m1 = create_test_program();
    auto m2 = create_control_program();
    run_pass(m1);
189

Paul Fultz II's avatar
Paul Fultz II committed
190
    EXPECT(m1 == m2);
191
192
193
194
195
}

TEST_CASE(negative_axis2)
{
    auto create_test_program = [] {
Paul Fultz II's avatar
Paul Fultz II committed
196
        migraphx::module m;
197

Paul Fultz II's avatar
Paul Fultz II committed
198
199
200
201
        auto a1          = m.add_instruction(allocate{create_shape(2, 2)});
        auto m1          = m.add_instruction(simple_op{}, a1);
        auto a2          = m.add_instruction(allocate{create_shape(2, 2)});
        auto m2          = m.add_instruction(simple_op{}, a2);
202
        std::size_t axis = -2;
Paul Fultz II's avatar
Paul Fultz II committed
203
204
205
        auto a3          = m.add_instruction(allocate{create_shape(4, 2)});
        m.add_instruction(concat(axis), m1, m2, a3);
        return m;
206
207
    };
    auto create_control_program = [] {
Paul Fultz II's avatar
Paul Fultz II committed
208
209
210
211
212
213
214
215
216
        migraphx::module m;

        auto a1 = m.add_instruction(allocate{create_shape(4, 2)});
        auto l1 = m.add_instruction(load{create_shape(2, 2), 0}, a1);
        auto m1 = m.add_instruction(simple_op{}, l1);
        auto l2 = m.add_instruction(load{create_shape(2, 2), 16}, a1);
        auto m2 = m.add_instruction(simple_op{}, l2);
        m.add_instruction(identity{}, a1, m1, m2);
        return m;
217
218
    };

Paul Fultz II's avatar
Paul Fultz II committed
219
220
221
    auto m1 = create_test_program();
    auto m2 = create_control_program();
    run_pass(m1);
222

Paul Fultz II's avatar
Paul Fultz II committed
223
    EXPECT(m1 == m2);
224
225
226
227
228
}

TEST_CASE(negative_axis3)
{
    auto create_test_program = [] {
Paul Fultz II's avatar
Paul Fultz II committed
229
        migraphx::module m;
230

Paul Fultz II's avatar
Paul Fultz II committed
231
232
233
234
        auto a1          = m.add_instruction(allocate{create_shape(1, 2, 2)});
        auto m1          = m.add_instruction(simple_op{}, a1);
        auto a2          = m.add_instruction(allocate{create_shape(1, 2, 2)});
        auto m2          = m.add_instruction(simple_op{}, a2);
235
        std::size_t axis = -2;
Paul Fultz II's avatar
Paul Fultz II committed
236
237
238
        auto a3          = m.add_instruction(allocate{create_shape(1, 4, 2)});
        m.add_instruction(concat(axis), m1, m2, a3);
        return m;
239
240
    };
    auto create_control_program = [] {
Paul Fultz II's avatar
Paul Fultz II committed
241
242
243
244
245
246
247
248
249
        migraphx::module m;

        auto a1 = m.add_instruction(allocate{create_shape(1, 4, 2)});
        auto l1 = m.add_instruction(load{create_shape(1, 2, 2), 0}, a1);
        auto m1 = m.add_instruction(simple_op{}, l1);
        auto l2 = m.add_instruction(load{create_shape(1, 2, 2), 16}, a1);
        auto m2 = m.add_instruction(simple_op{}, l2);
        m.add_instruction(identity{}, a1, m1, m2);
        return m;
250
251
    };

Paul Fultz II's avatar
Paul Fultz II committed
252
253
254
    auto m1 = create_test_program();
    auto m2 = create_control_program();
    run_pass(m1);
255

Paul Fultz II's avatar
Paul Fultz II committed
256
    EXPECT(m1 == m2);
257
258
}

259
260
261
TEST_CASE(reversed)
{
    auto create_test_program = [] {
Paul Fultz II's avatar
Paul Fultz II committed
262
        migraphx::module m;
263

Paul Fultz II's avatar
Paul Fultz II committed
264
265
266
267
        auto a1          = m.add_instruction(allocate{create_shape(1)});
        auto m1          = m.add_instruction(simple_op{}, a1);
        auto a2          = m.add_instruction(allocate{create_shape(1)});
        auto m2          = m.add_instruction(simple_op{}, a2);
268
        std::size_t axis = 0;
Paul Fultz II's avatar
Paul Fultz II committed
269
270
271
        auto a3          = m.add_instruction(allocate{create_shape(2)});
        m.add_instruction(concat(axis), m2, m1, a3);
        return m;
272
273
    };
    auto create_control_program = [] {
Paul Fultz II's avatar
Paul Fultz II committed
274
275
276
277
278
279
280
281
282
        migraphx::module m;

        auto a1 = m.add_instruction(allocate{create_shape(2)});
        auto l1 = m.add_instruction(load{create_shape(1), 4}, a1);
        auto m1 = m.add_instruction(simple_op{}, l1);
        auto l2 = m.add_instruction(load{create_shape(1), 0}, a1);
        auto m2 = m.add_instruction(simple_op{}, l2);
        m.add_instruction(identity{}, a1, m2, m1);
        return m;
283
284
    };

Paul Fultz II's avatar
Paul Fultz II committed
285
286
287
    auto m1 = create_test_program();
    auto m2 = create_control_program();
    run_pass(m1);
288

Paul Fultz II's avatar
Paul Fultz II committed
289
    EXPECT(m1 == m2);
290
291
}

Paul's avatar
Paul committed
292
293
TEST_CASE(nested)
{
Paul Fultz II's avatar
Paul Fultz II committed
294
295
296
297
298
    auto concat_test_program = [](auto& m) {
        auto a1          = m.add_instruction(allocate{create_shape(1)});
        auto m1          = m.add_instruction(simple_op{}, a1);
        auto a2          = m.add_instruction(allocate{create_shape(1)});
        auto m2          = m.add_instruction(simple_op{}, a2);
Paul's avatar
Paul committed
299
        std::size_t axis = 0;
Paul Fultz II's avatar
Paul Fultz II committed
300
301
        auto a3          = m.add_instruction(allocate{create_shape(2)});
        return m.add_instruction(concat(axis), m1, m2, a3);
Paul's avatar
Paul committed
302
303
    };
    auto create_test_program = [&] {
Paul Fultz II's avatar
Paul Fultz II committed
304
305
306
        migraphx::module m;
        auto concat1     = concat_test_program(m);
        auto concat2     = concat_test_program(m);
Paul's avatar
Paul committed
307
        std::size_t axis = 0;
Paul Fultz II's avatar
Paul Fultz II committed
308
309
310
        auto a1          = m.add_instruction(allocate{create_shape(4)});
        m.add_instruction(concat(axis), concat1, concat2, a1);
        return m;
Paul's avatar
Paul committed
311
    };
Paul Fultz II's avatar
Paul Fultz II committed
312
313
314
315
316
317
    auto concat_control_program = [](auto& m, auto a1) {
        auto l1 = m.add_instruction(load{create_shape(1), 0}, a1);
        auto m1 = m.add_instruction(simple_op{}, l1);
        auto l2 = m.add_instruction(load{create_shape(1), 4}, a1);
        auto m2 = m.add_instruction(simple_op{}, l2);
        return m.add_instruction(identity{}, a1, m1, m2);
Paul's avatar
Paul committed
318
319
    };
    auto create_control_program = [&] {
Paul Fultz II's avatar
Paul Fultz II committed
320
321
322
323
324
325
326
327
        migraphx::module m;
        auto a1      = m.add_instruction(allocate{create_shape(4)});
        auto l1      = m.add_instruction(load{create_shape(2), 0}, a1);
        auto concat1 = concat_control_program(m, l1);
        auto l2      = m.add_instruction(load{create_shape(2), 8}, a1);
        auto concat2 = concat_control_program(m, l2);
        m.add_instruction(identity{}, a1, concat1, concat2);
        return m;
Paul's avatar
Paul committed
328
329
    };

Paul Fultz II's avatar
Paul Fultz II committed
330
331
332
    auto m1 = create_test_program();
    auto m2 = create_control_program();
    run_pass(m1);
Paul's avatar
Paul committed
333

Paul Fultz II's avatar
Paul Fultz II committed
334
    EXPECT(m1 == m2);
Paul's avatar
Paul committed
335
336
}

Paul's avatar
Paul committed
337
TEST_CASE(basic)
338
{
Paul's avatar
Paul committed
339
    auto create_test_program = [] {
Paul Fultz II's avatar
Paul Fultz II committed
340
341
342
343
344
345
346
347
348
349
        migraphx::module m;
        auto a1 =
            m.add_instruction(allocate{migraphx::shape{migraphx::shape::float_type, {1, 2, 8, 8}}});
        auto m1 = m.add_instruction(simple_op{}, a1);
        auto a2 =
            m.add_instruction(allocate{migraphx::shape{migraphx::shape::float_type, {1, 3, 8, 8}}});
        auto m2 = m.add_instruction(simple_op{}, a2);
        auto a3 =
            m.add_instruction(allocate{migraphx::shape{migraphx::shape::float_type, {1, 5, 8, 8}}});
        auto p3          = m.add_instruction(simple_op{}, a3);
350
        std::size_t axis = 1;
Paul Fultz II's avatar
Paul Fultz II committed
351
        auto a4          = m.add_instruction(
Paul's avatar
Paul committed
352
            allocate{migraphx::shape{migraphx::shape::float_type, {1, 10, 8, 8}}});
Paul Fultz II's avatar
Paul Fultz II committed
353
354
        m.add_instruction(concat(axis), m1, m2, p3, a4);
        return m;
355
    };
Paul's avatar
Paul committed
356
    auto create_control_program = [] {
Paul Fultz II's avatar
Paul Fultz II committed
357
358
        migraphx::module m;
        auto a1 = m.add_instruction(
Paul's avatar
Paul committed
359
            allocate{migraphx::shape{migraphx::shape::float_type, {1, 10, 8, 8}}});
Paul Fultz II's avatar
Paul Fultz II committed
360
        auto l1 = m.add_instruction(
Paul's avatar
Paul committed
361
            load{migraphx::shape{migraphx::shape::float_type, {1, 2, 8, 8}}, 0}, {a1});
Paul Fultz II's avatar
Paul Fultz II committed
362
363
        auto m1 = m.add_instruction(simple_op{}, l1);
        auto l2 = m.add_instruction(
Paul's avatar
Paul committed
364
            load{migraphx::shape{migraphx::shape::float_type, {1, 3, 8, 8}}, 512}, {a1});
Paul Fultz II's avatar
Paul Fultz II committed
365
366
        auto m2 = m.add_instruction(simple_op{}, l2);
        auto l3 = m.add_instruction(
Paul's avatar
Paul committed
367
            load{migraphx::shape{migraphx::shape::float_type, {1, 5, 8, 8}}, 1280}, {a1});
Paul Fultz II's avatar
Paul Fultz II committed
368
369
370
        auto p3 = m.add_instruction(simple_op{}, l3);
        m.add_instruction(identity{}, {a1, m1, m2, p3});
        return m;
371
372
    };

Paul Fultz II's avatar
Paul Fultz II committed
373
374
375
    auto m1 = create_test_program();
    auto m2 = create_control_program();
    run_pass(m1);
376

Paul Fultz II's avatar
Paul Fultz II committed
377
    EXPECT(m1 == m2);
378
379
}

Paul's avatar
Paul committed
380
TEST_CASE(wont_work)
381
{
Paul's avatar
Paul committed
382
    auto create_test_program = [] {
Paul Fultz II's avatar
Paul Fultz II committed
383
384
385
386
387
388
389
390
391
392
        migraphx::module m;
        auto a1 =
            m.add_instruction(allocate{migraphx::shape{migraphx::shape::float_type, {2, 2, 8, 8}}});
        auto m1 = m.add_instruction(simple_op{}, a1);
        auto a2 =
            m.add_instruction(allocate{migraphx::shape{migraphx::shape::float_type, {2, 3, 8, 8}}});
        auto m2 = m.add_instruction(simple_op{}, a2);
        auto a3 =
            m.add_instruction(allocate{migraphx::shape{migraphx::shape::float_type, {2, 5, 8, 8}}});
        auto p3          = m.add_instruction(simple_op{}, a3);
393
        std::size_t axis = 1;
Paul Fultz II's avatar
Paul Fultz II committed
394
        auto a4          = m.add_instruction(
Paul's avatar
Paul committed
395
            allocate{migraphx::shape{migraphx::shape::float_type, {2, 10, 8, 8}}});
Paul Fultz II's avatar
Paul Fultz II committed
396
397
        m.add_instruction(concat(axis), m1, m2, p3, a4);
        return m;
398
    };
Paul's avatar
Paul committed
399
    auto create_control_program = [] {
Paul Fultz II's avatar
Paul Fultz II committed
400
401
402
403
404
405
406
407
408
409
        migraphx::module m;
        auto a1 =
            m.add_instruction(allocate{migraphx::shape{migraphx::shape::float_type, {2, 2, 8, 8}}});
        auto m1 = m.add_instruction(simple_op{}, a1);
        auto a2 =
            m.add_instruction(allocate{migraphx::shape{migraphx::shape::float_type, {2, 3, 8, 8}}});
        auto m2 = m.add_instruction(simple_op{}, a2);
        auto a3 =
            m.add_instruction(allocate{migraphx::shape{migraphx::shape::float_type, {2, 5, 8, 8}}});
        auto p3          = m.add_instruction(simple_op{}, a3);
410
        std::size_t axis = 1;
Paul Fultz II's avatar
Paul Fultz II committed
411
        auto a4          = m.add_instruction(
Paul's avatar
Paul committed
412
            allocate{migraphx::shape{migraphx::shape::float_type, {2, 10, 8, 8}}});
Paul Fultz II's avatar
Paul Fultz II committed
413
414
        m.add_instruction(concat(axis), m1, m2, p3, a4);
        return m;
415
416
    };

Paul Fultz II's avatar
Paul Fultz II committed
417
418
419
    auto m1 = create_test_program();
    auto m2 = create_control_program();
    run_pass(m1);
420

Paul Fultz II's avatar
Paul Fultz II committed
421
    EXPECT(m1 == m2);
422
423
}

Paul's avatar
Paul committed
424
int main(int argc, const char* argv[]) { test::run(argc, argv); }