• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2020-2021 Collabora Ltd.
3  * SPDX-License-Identifier: MIT
4  */
5 
6 #ifndef __AGX_TEST_H
7 #define __AGX_TEST_H
8 
9 #include <inttypes.h>
10 #include <stdio.h>
11 #include "agx_builder.h"
12 #include "agx_compiler.h"
13 
14 /* Helper to generate a agx_builder suitable for creating test instructions */
15 static inline agx_builder *
agx_test_builder(void * memctx)16 agx_test_builder(void *memctx)
17 {
18    agx_context *ctx = rzalloc(memctx, agx_context);
19    list_inithead(&ctx->blocks);
20 
21    agx_block *blk = rzalloc(ctx, agx_block);
22    util_dynarray_init(&blk->predecessors, NULL);
23 
24    list_addtail(&blk->link, &ctx->blocks);
25    list_inithead(&blk->instructions);
26 
27    agx_builder *b = rzalloc(memctx, agx_builder);
28    b->shader = ctx;
29    b->cursor = agx_after_block(blk);
30 
31    return b;
32 }
33 
34 /* Helper to compare for logical equality of instructions. Need to compare the
35  * pointers, then compare raw data.
36  */
37 static inline bool
agx_instr_equal(agx_instr * A,agx_instr * B)38 agx_instr_equal(agx_instr *A, agx_instr *B)
39 {
40    unsigned pointers = sizeof(struct list_head) + sizeof(agx_index *) * 2;
41 
42    if (A->nr_srcs != B->nr_srcs)
43       return false;
44 
45    if (memcmp(A->src, B->src, A->nr_srcs * sizeof(agx_index)))
46       return false;
47 
48    if (A->nr_dests != B->nr_dests)
49       return false;
50 
51    if (memcmp(A->dest, B->dest, A->nr_dests * sizeof(agx_index)))
52       return false;
53 
54    return memcmp((uint8_t *)A + pointers, (uint8_t *)B + pointers,
55                  sizeof(agx_instr) - pointers) == 0;
56 }
57 
58 static inline bool
agx_block_equal(agx_block * A,agx_block * B)59 agx_block_equal(agx_block *A, agx_block *B)
60 {
61    if (list_length(&A->instructions) != list_length(&B->instructions))
62       return false;
63 
64    list_pair_for_each_entry(agx_instr, insA, insB, &A->instructions,
65                             &B->instructions, link) {
66       if (!agx_instr_equal(insA, insB))
67          return false;
68    }
69 
70    return true;
71 }
72 
73 static inline bool
agx_shader_equal(agx_context * A,agx_context * B)74 agx_shader_equal(agx_context *A, agx_context *B)
75 {
76    if (list_length(&A->blocks) != list_length(&B->blocks))
77       return false;
78 
79    list_pair_for_each_entry(agx_block, blockA, blockB, &A->blocks, &B->blocks,
80                             link) {
81       if (!agx_block_equal(blockA, blockB))
82          return false;
83    }
84 
85    return true;
86 }
87 
88 #define ASSERT_SHADER_EQUAL(A, B)                                              \
89    if (!agx_shader_equal(A, B)) {                                              \
90       ADD_FAILURE();                                                           \
91       fprintf(stderr, "Pass produced unexpected results");                     \
92       fprintf(stderr, "  Actual:\n");                                          \
93       agx_print_shader(A, stderr);                                             \
94       fprintf(stderr, " Expected:\n");                                         \
95       agx_print_shader(B, stderr);                                             \
96       fprintf(stderr, "\n");                                                   \
97    }
98 
99 #define INSTRUCTION_CASE(instr, expected, pass)                                \
100    do {                                                                        \
101       agx_builder *A = agx_test_builder(mem_ctx);                              \
102       agx_builder *B = agx_test_builder(mem_ctx);                              \
103       {                                                                        \
104          agx_builder *b = A;                                                   \
105          instr;                                                                \
106       }                                                                        \
107       {                                                                        \
108          agx_builder *b = B;                                                   \
109          expected;                                                             \
110       }                                                                        \
111       pass(A->shader);                                                         \
112       ASSERT_SHADER_EQUAL(A->shader, B->shader);                               \
113    } while (0)
114 
115 #endif
116