eval_test.cpp 16.7 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

Paul's avatar
Paul committed
25
26
27
#include <migraphx/program.hpp>
#include <migraphx/iterator_for.hpp>
#include <migraphx/instruction.hpp>
Paul's avatar
Paul committed
28
#include <migraphx/stringutils.hpp>
29
#include <migraphx/compile_options.hpp>
30
#include <migraphx/make_op.hpp>
Paul's avatar
Paul committed
31
#include <sstream>
Paul's avatar
Paul committed
32
#include "test.hpp"
Paul's avatar
Paul committed
33
#include <basic_ops.hpp>
Paul's avatar
Paul committed
34

Paul's avatar
Paul committed
35
36
struct id_target
{
Paul's avatar
Paul committed
37
38
39
40
41
    struct context
    {
        void finish() const {}
    };
    migraphx::context ctx = context{};
Paul's avatar
Paul committed
42
    std::string name() const { return "id"; }
43
44
45
46
47
    std::vector<migraphx::pass> get_passes(migraphx::context&,
                                           const migraphx::compile_options&) const
    {
        return {};
    }
Paul's avatar
Paul committed
48
49
50
51
52
    migraphx::context get_context() const { return ctx; }
};

struct id_ctx_op
{
53
    std::string name() const { return ""; }
Paul's avatar
Paul committed
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
    migraphx::argument
    compute(id_target::context&, const migraphx::shape&, std::vector<migraphx::argument> args) const
    {
        if(args.empty())
            return {};
        return args.front();
    }

    migraphx::shape compute_shape(std::vector<migraphx::shape> inputs) const
    {
        if(inputs.empty())
            return {};
        return inputs.front();
    }
    int output_alias(const std::vector<migraphx::shape>&) const { return 0; }
};

struct id_ctx_final_op
{
    std::string name() const { return "id_ctx_final_op"; }
Paul's avatar
Paul committed
74
    migraphx::argument compute(const migraphx::shape&, std::vector<migraphx::argument> args) const
Paul's avatar
Paul committed
75
76
77
78
79
80
    {
        if(args.empty())
            return {};
        return args.front();
    }

Paul's avatar
Paul committed
81
82
83
    void finalize(id_target::context&, const migraphx::shape&, const std::vector<migraphx::shape>&)
    {
    }
Paul's avatar
Paul committed
84
85
86
87
88
89
90
91

    migraphx::shape compute_shape(std::vector<migraphx::shape> inputs) const
    {
        if(inputs.empty())
            return {};
        return inputs.front();
    }
    int output_alias(const std::vector<migraphx::shape>&) const { return 0; }
Paul's avatar
Paul committed
92
93
};

Paul's avatar
Paul committed
94
95
struct reverse_pass
{
Paul's avatar
Paul committed
96
    std::string name() const { return "reverse_pass"; }
Paul's avatar
Paul committed
97

Shucai Xiao's avatar
Shucai Xiao committed
98
    void apply(migraphx::module& m) const { std::reverse(m.begin(), m.end()); }
Paul's avatar
Paul committed
99
100
101
102
103
};

struct reverse_target
{
    std::string name() const { return "reverse"; }
104
105
106
107
108
    std::vector<migraphx::pass> get_passes(migraphx::context&,
                                           const migraphx::compile_options&) const
    {
        return {reverse_pass{}};
    }
Paul's avatar
Paul committed
109
110
111
112
113
114
115
    migraphx::context get_context() const { return {}; }
};

struct invert_pass
{
    std::string name() const { return "invert_pass"; }

116
    void apply(migraphx::module& m) const
Paul's avatar
Paul committed
117
    {
118
        for(auto ins : migraphx::iterator_for(m))
Paul's avatar
Paul committed
119
        {
120
            if(ins->name() == "sum")
Paul's avatar
Paul committed
121
            {
122
                m.replace_instruction(ins, minus_op{}, ins->inputs());
Paul's avatar
Paul committed
123
            }
124
            else if(ins->name() == "minus")
Paul's avatar
Paul committed
125
            {
126
                m.replace_instruction(ins, sum_op{}, ins->inputs());
Paul's avatar
Paul committed
127
128
129
130
131
            }
        }
    }
};

Paul's avatar
Paul committed
132
struct invert_target
Paul's avatar
Paul committed
133
{
Paul's avatar
Paul committed
134
    std::string name() const { return "invert"; }
135
136
137
138
139
    std::vector<migraphx::pass> get_passes(migraphx::context&,
                                           const migraphx::compile_options&) const
    {
        return {invert_pass{}};
    }
Paul's avatar
Paul committed
140
    migraphx::context get_context() const { return {}; }
Paul's avatar
Paul committed
141
142
};

Paul's avatar
Paul committed
143
struct double_invert_target
Paul's avatar
Paul committed
144
{
Paul's avatar
Paul committed
145
    std::string name() const { return "double_invert"; }
146
147
    std::vector<migraphx::pass> get_passes(migraphx::context&,
                                           const migraphx::compile_options&) const
Paul's avatar
Paul committed
148
    {
Paul's avatar
Paul committed
149
        return {invert_pass{}, invert_pass{}};
Paul's avatar
Paul committed
150
    }
Paul's avatar
Paul committed
151
    migraphx::context get_context() const { return {}; }
Paul's avatar
Paul committed
152
153
};

Paul's avatar
Paul committed
154
TEST_CASE(literal_test1)
Paul's avatar
Paul committed
155
{
Paul's avatar
Paul committed
156
    migraphx::program p;
157
158
159
    auto* mm = p.get_main_module();
    auto one = mm->add_literal(1);
    auto two = mm->add_literal(2);
160
    mm->add_instruction(migraphx::make_op("add"), one, two);
161
    auto result = p.eval({}).back();
Paul's avatar
Paul committed
162
163
    EXPECT(result == migraphx::literal{3});
    EXPECT(result != migraphx::literal{4});
Paul's avatar
Paul committed
164
165
}

Paul's avatar
Paul committed
166
TEST_CASE(literal_test2)
Paul's avatar
Paul committed
167
{
Paul's avatar
Paul committed
168
    migraphx::program p;
169
170
171
    auto* mm  = p.get_main_module();
    auto one  = mm->add_literal(1);
    auto two  = mm->add_literal(2);
172
173
    auto sum1 = mm->add_instruction(migraphx::make_op("add"), one, two);
    mm->add_instruction(migraphx::make_op("add"), sum1, two);
Paul's avatar
Paul committed
174

175
    auto result = p.eval({}).back();
Paul's avatar
Paul committed
176
177
    EXPECT(result == migraphx::literal{5});
    EXPECT(result != migraphx::literal{3});
Paul's avatar
Paul committed
178
179
}

Paul's avatar
Paul committed
180
TEST_CASE(print_test)
Paul's avatar
Paul committed
181
{
Paul's avatar
Paul committed
182
    migraphx::program p;
183
184
185
    auto* mm = p.get_main_module();
    auto x   = mm->add_parameter("x", {migraphx::shape::int32_type});
    auto two = mm->add_literal(2);
186
    mm->add_instruction(migraphx::make_op("add"), x, two);
Paul's avatar
Paul committed
187
188
189
190

    std::stringstream ss;
    ss << p;
    std::string s = ss.str();
191
    EXPECT(not s.empty());
Paul's avatar
Paul committed
192
193
}

Paul's avatar
Paul committed
194
TEST_CASE(param_test)
Paul's avatar
Paul committed
195
{
Paul's avatar
Paul committed
196
    migraphx::program p;
197
198
199
    auto* mm = p.get_main_module();
    auto x   = mm->add_parameter("x", {migraphx::shape::int32_type});
    auto y   = mm->add_parameter("y", {migraphx::shape::int32_type});
Paul's avatar
Paul committed
200

201
    mm->add_instruction(migraphx::make_op("add"), x, y);
202
203
204
    auto result = p.eval({{"x", migraphx::literal{1}.get_argument()},
                          {"y", migraphx::literal{2}.get_argument()}})
                      .back();
Paul's avatar
Paul committed
205
206
    EXPECT(result == migraphx::literal{3});
    EXPECT(result != migraphx::literal{4});
Paul's avatar
Paul committed
207
208
}

Paul's avatar
Paul committed
209
TEST_CASE(param_error_test)
Khalique's avatar
Khalique committed
210
{
Paul's avatar
Paul committed
211
    migraphx::program p;
212
213
214
    auto* mm = p.get_main_module();
    auto x   = mm->add_parameter("x", {migraphx::shape::int32_type});
    auto y   = mm->add_parameter("y", {migraphx::shape::int32_type});
Khalique's avatar
Khalique committed
215

216
    mm->add_instruction(sum_op{}, x, y);
Paul's avatar
Paul committed
217
    EXPECT(test::throws<migraphx::exception>(
Khalique's avatar
Khalique committed
218
        [&] {
Paul's avatar
Paul committed
219
            p.eval({{"x", migraphx::literal{1}.get_argument()}});
Khalique's avatar
Khalique committed
220
        },
221
        "Parameter not found: y"));
Khalique's avatar
Khalique committed
222
223
}

Paul's avatar
Paul committed
224
225
226
TEST_CASE(param_error_shape_test)
{
    migraphx::program p;
227
228
229
    auto* mm = p.get_main_module();
    auto x   = mm->add_parameter("x", {migraphx::shape::int32_type, {1, 1}});
    auto y   = mm->add_parameter("y", {migraphx::shape::int32_type, {1, 1}});
Paul's avatar
Paul committed
230

231
    mm->add_instruction(migraphx::make_op("add"), x, y);
Paul's avatar
Paul committed
232
233
234
235
236
237
238
239
240
241
    EXPECT(test::throws<migraphx::exception>(
        [&] {
            p.eval({
                {"x", migraphx::literal{1}.get_argument()},
                {"y", migraphx::literal{{migraphx::shape::int32_type, {1, 1}}, {2}}.get_argument()},
            });
        },
        "Incorrect shape {int32_type, {1}, {0}} for parameter: x"));
}

Paul's avatar
Paul committed
242
TEST_CASE(get_param1)
Paul's avatar
Paul committed
243
244
{
    migraphx::program p;
245
    auto* mm = p.get_main_module();
Paul's avatar
Paul committed
246
    migraphx::shape s{migraphx::shape::int32_type, {1, 2}};
247
248
    auto x = mm->add_parameter("x", s);
    auto y = mm->add_parameter("y", s);
249
    mm->add_instruction(migraphx::make_op("add"), x, y);
Paul's avatar
Paul committed
250
251
    EXPECT(bool{p.get_parameter("x") == x});
    EXPECT(bool{p.get_parameter("y") == y});
Shucai Xiao's avatar
Shucai Xiao committed
252
    EXPECT(bool{p.get_parameter("nonexistent") == mm->end()});
Paul's avatar
Paul committed
253
}
Paul's avatar
Paul committed
254

Paul's avatar
Paul committed
255
256
257
TEST_CASE(get_param2)
{
    migraphx::program p;
258
259
260
    auto* mm = p.get_main_module();
    auto one = mm->add_literal(1);
    auto two = mm->add_literal(2);
261
    mm->add_instruction(migraphx::make_op("add"), one, two);
Shucai Xiao's avatar
Shucai Xiao committed
262
    EXPECT(bool{p.get_parameter("nonexistent") == mm->end()});
Paul's avatar
Paul committed
263
}
Paul's avatar
Paul committed
264

Paul's avatar
Paul committed
265
266
267
TEST_CASE(get_param_shapes)
{
    migraphx::program p;
268
    auto* mm = p.get_main_module();
Paul's avatar
Paul committed
269
    migraphx::shape s{migraphx::shape::int32_type, {1, 2}};
270
271
    auto x = mm->add_parameter("x", s);
    auto y = mm->add_parameter("y", s);
272
    mm->add_instruction(migraphx::make_op("add"), x, y);
Paul's avatar
Paul committed
273
274
275
276
    auto m = p.get_parameter_shapes();
    EXPECT(m.count("nonexistent") == 0);
    EXPECT(m.at("x") == s);
    EXPECT(m.at("y") == s);
Paul's avatar
Paul committed
277
278
}

Paul's avatar
Paul committed
279
TEST_CASE(replace_test)
Paul's avatar
Paul committed
280
{
Paul's avatar
Paul committed
281
    migraphx::program p;
282
283
284
    auto* mm = p.get_main_module();
    auto one = mm->add_literal(1);
    auto two = mm->add_literal(2);
285
286
    auto sum = mm->add_instruction(migraphx::make_op("add"), one, two);
    mm->replace_instruction(sum, migraphx::make_op("sub"), two, one);
Shucai Xiao's avatar
Shucai Xiao committed
287
    EXPECT(bool{p.validate() == mm->end()});
Paul's avatar
Paul committed
288

289
    auto result = p.eval({}).back();
Paul's avatar
Paul committed
290
291
    EXPECT(result == migraphx::literal{1});
    EXPECT(result != migraphx::literal{3});
Paul's avatar
Paul committed
292
293
}

Paul's avatar
Paul committed
294
TEST_CASE(replace_ins_test)
Paul's avatar
Paul committed
295
{
Paul's avatar
Paul committed
296
    migraphx::program p;
297
298
299
    auto* mm   = p.get_main_module();
    auto one   = mm->add_literal(1);
    auto two   = mm->add_literal(2);
300
301
    auto sum   = mm->add_instruction(migraphx::make_op("add"), one, two);
    auto minus = mm->add_instruction(migraphx::make_op("sub"), two, one);
302
    mm->replace_instruction(sum, minus);
Shucai Xiao's avatar
Shucai Xiao committed
303
    EXPECT(bool{p.validate() == mm->end()});
Paul's avatar
Paul committed
304

305
    auto result = p.eval({}).back();
Paul's avatar
Paul committed
306
307
    EXPECT(result == migraphx::literal{1});
    EXPECT(result != migraphx::literal{3});
Paul's avatar
Paul committed
308
309
}

Paul's avatar
Paul committed
310
TEST_CASE(replace_ins_test2)
Paul's avatar
Paul committed
311
{
Paul's avatar
Paul committed
312
    migraphx::program p;
313
314
315
    auto* mm   = p.get_main_module();
    auto one   = mm->add_literal(1);
    auto two   = mm->add_literal(2);
316
317
    auto sum   = mm->add_instruction(migraphx::make_op("add"), one, two);
    auto minus = mm->add_instruction(migraphx::make_op("sub"), two, one);
318
319
    mm->add_instruction(pass_op{}, minus);
    mm->replace_instruction(two, sum);
Shucai Xiao's avatar
Shucai Xiao committed
320
    EXPECT(bool{p.validate() == mm->end()});
Paul's avatar
Paul committed
321

322
    auto result = p.eval({}).back();
Paul's avatar
Paul committed
323
324
    EXPECT(result == migraphx::literal{2});
    EXPECT(result != migraphx::literal{3});
Paul's avatar
Paul committed
325
326
}

Paul's avatar
Paul committed
327
328
329
TEST_CASE(replace_op_test)
{
    migraphx::program p;
330
331
332
    auto* mm = p.get_main_module();
    auto one = mm->add_literal(1);
    auto two = mm->add_literal(2);
333
334
    auto sum = mm->add_instruction(migraphx::make_op("add"), two, one);
    sum->replace(migraphx::make_op("sub"));
Shucai Xiao's avatar
Shucai Xiao committed
335
    EXPECT(bool{p.validate() == mm->end()});
Paul's avatar
Paul committed
336

337
    auto result = p.eval({}).back();
Paul's avatar
Paul committed
338
339
340
341
342
343
344
    EXPECT(result == migraphx::literal{1});
    EXPECT(result != migraphx::literal{3});
}

TEST_CASE(replace_op_recompute_shape_throw)
{
    migraphx::program p;
345
346
347
    auto* mm = p.get_main_module();
    auto one = mm->add_literal(1);
    auto two = mm->add_literal(2);
348
    auto sum = mm->add_instruction(migraphx::make_op("add"), one, two);
Paul's avatar
Paul committed
349
    EXPECT(test::throws<migraphx::exception>([&] { sum->replace(unary_pass_op{}); }));
Paul's avatar
Paul committed
350
351
}

Paul's avatar
Paul committed
352
TEST_CASE(insert_replace_test)
Paul's avatar
Paul committed
353
{
Paul's avatar
Paul committed
354
    migraphx::program p;
355
356
357
    auto* mm  = p.get_main_module();
    auto one  = mm->add_literal(1);
    auto two  = mm->add_literal(2);
358
359
    auto sum1 = mm->add_instruction(migraphx::make_op("add"), one, two);
    mm->add_instruction(migraphx::make_op("add"), sum1, two);
360

361
362
    auto sum0 = mm->insert_instruction(sum1, migraphx::make_op("add"), two, two);
    mm->replace_instruction(sum1, migraphx::make_op("sub"), sum0, two);
Shucai Xiao's avatar
Shucai Xiao committed
363
    EXPECT(bool{p.validate() == mm->end()});
Paul's avatar
Paul committed
364

365
    auto result = p.eval({}).back();
Paul's avatar
Paul committed
366
367
    EXPECT(result == migraphx::literal{4});
    EXPECT(result != migraphx::literal{5});
Paul's avatar
Paul committed
368
369
}

Paul's avatar
Paul committed
370
371
372
TEST_CASE(remove_test1)
{
    migraphx::program p;
373
374
375
    auto* mm     = p.get_main_module();
    auto one     = mm->add_literal(1);
    auto two     = mm->add_literal(2);
376
377
    auto sum     = mm->add_instruction(migraphx::make_op("add"), one, two);
    auto removed = mm->add_instruction(migraphx::make_op("sub"), sum, one);
378
    mm->remove_instruction(removed);
Shucai Xiao's avatar
Shucai Xiao committed
379
    EXPECT(bool{p.validate() == mm->end()});
Paul's avatar
Paul committed
380

381
    auto result = p.eval({}).back();
Paul's avatar
Paul committed
382
383
384
385
386
387
388
    EXPECT(result == migraphx::literal{3});
    EXPECT(result != migraphx::literal{1});
}

TEST_CASE(remove_test2)
{
    migraphx::program p;
389
390
391
    auto* mm     = p.get_main_module();
    auto one     = mm->add_literal(1);
    auto two     = mm->add_literal(2);
392
393
    auto removed = mm->add_instruction(migraphx::make_op("sub"), two, one);
    mm->add_instruction(migraphx::make_op("add"), one, two);
394
    mm->remove_instruction(removed);
Shucai Xiao's avatar
Shucai Xiao committed
395
    EXPECT(bool{p.validate() == mm->end()});
Paul's avatar
Paul committed
396

397
    auto result = p.eval({}).back();
Paul's avatar
Paul committed
398
399
400
401
    EXPECT(result == migraphx::literal{3});
    EXPECT(result != migraphx::literal{1});
}

Paul's avatar
Paul committed
402
TEST_CASE(target_test)
Paul's avatar
Paul committed
403
{
Paul's avatar
Paul committed
404
    migraphx::program p;
405
406
407
    auto* mm = p.get_main_module();
    auto one = mm->add_literal(1);
    auto two = mm->add_literal(2);
408
    mm->add_instruction(migraphx::make_op("add"), one, two);
Paul's avatar
Paul committed
409
    p.compile(id_target{});
410
    auto result = p.eval({}).back();
Paul's avatar
Paul committed
411
412
    EXPECT(result == migraphx::literal{3});
    EXPECT(result != migraphx::literal{4});
Paul's avatar
Paul committed
413
414
}

Paul's avatar
Paul committed
415
TEST_CASE(invert_target_test)
Paul's avatar
Paul committed
416
{
Paul's avatar
Paul committed
417
    migraphx::program p;
418
419
420
421
    auto* mm = p.get_main_module();
    auto one = mm->add_literal(1);
    auto two = mm->add_literal(2);
    mm->add_instruction(sum_op{}, two, one);
Paul's avatar
Paul committed
422
    p.compile(invert_target{});
423
    auto result = p.eval({}).back();
Paul's avatar
Paul committed
424
425
    EXPECT(result == migraphx::literal{1});
    EXPECT(result != migraphx::literal{4});
Paul's avatar
Paul committed
426
427
}

Paul's avatar
Paul committed
428
TEST_CASE(double_invert_target_test)
Paul's avatar
Paul committed
429
{
Paul's avatar
Paul committed
430
    migraphx::program p;
431
432
433
434
    auto* mm = p.get_main_module();
    auto one = mm->add_literal(1);
    auto two = mm->add_literal(2);
    mm->add_instruction(sum_op{}, two, one);
Paul's avatar
Paul committed
435
    p.compile(double_invert_target{});
436
    auto result = p.eval({}).back();
Paul's avatar
Paul committed
437
438
    EXPECT(result == migraphx::literal{3});
    EXPECT(result != migraphx::literal{4});
Paul's avatar
Paul committed
439
440
}

Paul's avatar
Paul committed
441
442
443
TEST_CASE(reverse_target_test)
{
    migraphx::program p;
444
445
446
447
    auto* mm = p.get_main_module();
    auto one = mm->add_literal(1);
    auto two = mm->add_literal(2);
    mm->add_instruction(sum_op{}, one, two);
Paul's avatar
Paul committed
448
    EXPECT(test::throws<migraphx::exception>([&] { p.compile(reverse_target{}); }));
Paul's avatar
Paul committed
449
450
}

Paul's avatar
Paul committed
451
452
// Check that the program doesnt modify the context directly, and only the operators modify the
// context
Paul's avatar
Paul committed
453
454
455
TEST_CASE(eval_context1)
{
    migraphx::program p;
456
    auto* mm = p.get_main_module();
Paul's avatar
Paul committed
457
458
    id_target t{};
    EXPECT(is_shared(t.ctx, t.get_context()));
459
460
461
    auto one = mm->add_literal(1);
    auto two = mm->add_literal(2);
    mm->add_instruction(sum_op{}, one, two);
Paul's avatar
Paul committed
462
463
    p.compile(t);
    EXPECT(is_shared(t.ctx, p.get_context()));
464
    p.eval({}).back();
Paul's avatar
Paul committed
465
466
467
468
469
470
    EXPECT(is_shared(t.ctx, p.get_context()));
}

TEST_CASE(eval_context2)
{
    migraphx::program p;
471
    auto* mm = p.get_main_module();
Paul's avatar
Paul committed
472
473
    id_target t{};
    EXPECT(is_shared(t.ctx, t.get_context()));
474
475
476
    auto one = mm->add_literal(1);
    auto two = mm->add_literal(2);
    mm->add_instruction(id_ctx_op{}, one, two);
Paul's avatar
Paul committed
477
478
    p.compile(t);
    EXPECT(is_shared(t.ctx, p.get_context()));
479
    p.eval({}).back();
Paul's avatar
Paul committed
480
481
482
483
484
485
486
    // id_ctx_op will modify the context
    EXPECT(not is_shared(t.ctx, p.get_context()));
}

TEST_CASE(eval_context3)
{
    migraphx::program p;
487
    auto* mm = p.get_main_module();
Paul's avatar
Paul committed
488
489
    id_target t{};
    EXPECT(is_shared(t.ctx, t.get_context()));
490
491
492
    auto one = mm->add_literal(1);
    auto two = mm->add_literal(2);
    mm->add_instruction(id_ctx_final_op{}, one, two);
Paul's avatar
Paul committed
493
494
495
496
    p.compile(t);
    // Finalizer will modify the context
    EXPECT(not is_shared(t.ctx, p.get_context()));
    auto ctx = p.get_context();
497
    p.eval({}).back();
Paul's avatar
Paul committed
498
499
500
501
    EXPECT(is_shared(ctx, p.get_context()));
    EXPECT(not is_shared(t.ctx, p.get_context()));
}

Paul's avatar
Paul committed
502
503
504
505
506
507
struct cout_redirect
{
    cout_redirect()                     = delete;
    cout_redirect(const cout_redirect&) = delete;
    template <class T>
    cout_redirect(T& stream) : old(std::cout.rdbuf(stream.rdbuf()))
Paul's avatar
Paul committed
508
509
    {
    }
Paul's avatar
Paul committed
510
    ~cout_redirect() { std::cout.rdbuf(old); }
Paul's avatar
Paul committed
511

Paul's avatar
Paul committed
512
513
    private:
    std::streambuf* old;
Paul's avatar
Paul committed
514
515
};

Paul's avatar
Paul committed
516
template <class F>
Paul's avatar
Paul committed
517
518
519
520
521
522
523
524
525
526
527
std::string capture_output(F f)
{
    std::stringstream ss;
    cout_redirect cr{ss};
    f();
    return ss.str();
}

TEST_CASE(debug_print_test)
{
    migraphx::program p;
528
529
    auto* mm                                    = p.get_main_module();
    auto one                                    = mm->add_literal(1);
Paul's avatar
Paul committed
530
    std::vector<migraphx::instruction_ref> onev = {one};
Paul's avatar
Paul committed
531
532

    migraphx::program p2;
533
534
    auto* mm2 = p2.get_main_module();
    auto one2 = mm2->add_literal(1);
Paul's avatar
Paul committed
535

Shucai Xiao's avatar
Shucai Xiao committed
536
537
538
539
540
    auto program_out = migraphx::trim(capture_output([&] { mm->debug_print(); }));
    auto ins_out     = migraphx::trim(capture_output([&] { mm->debug_print(one); }));
    auto inss_out    = migraphx::trim(capture_output([&] { mm->debug_print(onev); }));
    auto end_out     = migraphx::trim(capture_output([&] { mm->debug_print(mm->end()); }));
    auto p2_ins_out  = migraphx::trim(capture_output([&] { mm->debug_print(one2); }));
Paul's avatar
Paul committed
541
542
543
544

    EXPECT(program_out == ins_out);
    EXPECT(inss_out == ins_out);
    EXPECT(end_out == "End instruction");
Shucai Xiao's avatar
Shucai Xiao committed
545
    EXPECT(p2_ins_out == "Instruction not part of module");
Paul's avatar
Paul committed
546
547
}

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