xref: /aosp_15_r20/external/mesa3d/src/asahi/compiler/test/agx_test.h (revision 6104692788411f58d303aa86923a9ff6ecaded22)
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    ctx->num_blocks = 1;
24 
25    list_addtail(&blk->link, &ctx->blocks);
26    list_inithead(&blk->instructions);
27 
28    agx_builder *b = rzalloc(memctx, agx_builder);
29    b->shader = ctx;
30    b->cursor = agx_after_block(blk);
31 
32    return b;
33 }
34 
35 static inline agx_block *
agx_test_block(agx_context * ctx)36 agx_test_block(agx_context *ctx)
37 {
38    agx_block *blk = rzalloc(ctx, agx_block);
39 
40    util_dynarray_init(&blk->predecessors, blk);
41    list_addtail(&blk->link, &ctx->blocks);
42    list_inithead(&blk->instructions);
43 
44    blk->index = ctx->num_blocks++;
45 
46    return blk;
47 }
48 
49 /* Helper to compare for logical equality of instructions. Need to compare the
50  * pointers, then compare raw data.
51  */
52 static inline bool
agx_instr_equal(agx_instr * A,agx_instr * B)53 agx_instr_equal(agx_instr *A, agx_instr *B)
54 {
55    unsigned pointers = sizeof(struct list_head) + sizeof(agx_index *) * 2;
56 
57    if (A->nr_srcs != B->nr_srcs)
58       return false;
59 
60    if (memcmp(A->src, B->src, A->nr_srcs * sizeof(agx_index)))
61       return false;
62 
63    if (A->nr_dests != B->nr_dests)
64       return false;
65 
66    if (memcmp(A->dest, B->dest, A->nr_dests * sizeof(agx_index)))
67       return false;
68 
69    return memcmp((uint8_t *)A + pointers, (uint8_t *)B + pointers,
70                  sizeof(agx_instr) - pointers) == 0;
71 }
72 
73 static inline bool
agx_block_equal(agx_block * A,agx_block * B)74 agx_block_equal(agx_block *A, agx_block *B)
75 {
76    if (list_length(&A->instructions) != list_length(&B->instructions))
77       return false;
78 
79    list_pair_for_each_entry(agx_instr, insA, insB, &A->instructions,
80                             &B->instructions, link) {
81       if (!agx_instr_equal(insA, insB))
82          return false;
83    }
84 
85    return true;
86 }
87 
88 static inline bool
agx_shader_equal(agx_context * A,agx_context * B)89 agx_shader_equal(agx_context *A, agx_context *B)
90 {
91    if (list_length(&A->blocks) != list_length(&B->blocks))
92       return false;
93 
94    list_pair_for_each_entry(agx_block, blockA, blockB, &A->blocks, &B->blocks,
95                             link) {
96       if (!agx_block_equal(blockA, blockB))
97          return false;
98    }
99 
100    return true;
101 }
102 
103 #define ASSERT_SHADER_EQUAL(A, B)                                              \
104    if (!agx_shader_equal(A, B)) {                                              \
105       ADD_FAILURE();                                                           \
106       fprintf(stderr, "Pass produced unexpected results");                     \
107       fprintf(stderr, "  Actual:\n");                                          \
108       agx_print_shader(A, stderr);                                             \
109       fprintf(stderr, " Expected:\n");                                         \
110       agx_print_shader(B, stderr);                                             \
111       fprintf(stderr, "\n");                                                   \
112    }
113 
114 #define INSTRUCTION_CASE(instr, expected, pass)                                \
115    do {                                                                        \
116       agx_builder *A = agx_test_builder(mem_ctx);                              \
117       agx_builder *B = agx_test_builder(mem_ctx);                              \
118       {                                                                        \
119          agx_builder *b = A;                                                   \
120          instr;                                                                \
121       }                                                                        \
122       {                                                                        \
123          agx_builder *b = B;                                                   \
124          expected;                                                             \
125       }                                                                        \
126       pass(A->shader);                                                         \
127       ASSERT_SHADER_EQUAL(A->shader, B->shader);                               \
128    } while (0)
129 
130 #endif
131