xref: /aosp_15_r20/external/mesa3d/src/freedreno/ir3/tests/delay.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright © 2020 Google, Inc.
3*61046927SAndroid Build Coastguard Worker  * SPDX-License-Identifier: MIT
4*61046927SAndroid Build Coastguard Worker  */
5*61046927SAndroid Build Coastguard Worker 
6*61046927SAndroid Build Coastguard Worker #include <err.h>
7*61046927SAndroid Build Coastguard Worker #include <stdio.h>
8*61046927SAndroid Build Coastguard Worker 
9*61046927SAndroid Build Coastguard Worker #include "ir3.h"
10*61046927SAndroid Build Coastguard Worker #include "ir3_assembler.h"
11*61046927SAndroid Build Coastguard Worker #include "ir3_shader.h"
12*61046927SAndroid Build Coastguard Worker 
13*61046927SAndroid Build Coastguard Worker /*
14*61046927SAndroid Build Coastguard Worker  * A test for delay-slot calculation.  Each test specifies ir3 assembly
15*61046927SAndroid Build Coastguard Worker  * for one or more instructions and the last instruction that consumes
16*61046927SAndroid Build Coastguard Worker  * the previously produced values.  And the expected number of delay
17*61046927SAndroid Build Coastguard Worker  * slots that would be needed before that last instruction.  Any source
18*61046927SAndroid Build Coastguard Worker  * registers in the last instruction which are not written in a previous
19*61046927SAndroid Build Coastguard Worker  * instruction are not counted.
20*61046927SAndroid Build Coastguard Worker  */
21*61046927SAndroid Build Coastguard Worker 
22*61046927SAndroid Build Coastguard Worker /* clang-format off */
23*61046927SAndroid Build Coastguard Worker #define TEST(n, ...) { # __VA_ARGS__, n }
24*61046927SAndroid Build Coastguard Worker /* clang-format on */
25*61046927SAndroid Build Coastguard Worker 
26*61046927SAndroid Build Coastguard Worker static const struct test {
27*61046927SAndroid Build Coastguard Worker    const char *asmstr;
28*61046927SAndroid Build Coastguard Worker    unsigned expected_delay;
29*61046927SAndroid Build Coastguard Worker } tests[] = {
30*61046927SAndroid Build Coastguard Worker    /* clang-format off */
31*61046927SAndroid Build Coastguard Worker    TEST(6,
32*61046927SAndroid Build Coastguard Worker       add.f r0.x, r2.x, r2.y
33*61046927SAndroid Build Coastguard Worker       rsq r0.x, r0.x
34*61046927SAndroid Build Coastguard Worker    ),
35*61046927SAndroid Build Coastguard Worker    TEST(3,
36*61046927SAndroid Build Coastguard Worker       mov.f32f32 r0.x, c0.x
37*61046927SAndroid Build Coastguard Worker       mov.f32f32 r0.y, c0.y
38*61046927SAndroid Build Coastguard Worker       add.f r0.x, r0.x, r0.y
39*61046927SAndroid Build Coastguard Worker    ),
40*61046927SAndroid Build Coastguard Worker    TEST(2,
41*61046927SAndroid Build Coastguard Worker       mov.f32f32 r0.x, c0.x
42*61046927SAndroid Build Coastguard Worker       mov.f32f32 r0.y, c0.y
43*61046927SAndroid Build Coastguard Worker       mov.f32f32 r0.z, c0.z
44*61046927SAndroid Build Coastguard Worker       mad.f32 r0.x, r0.x, r0.y, r0.z
45*61046927SAndroid Build Coastguard Worker    ),
46*61046927SAndroid Build Coastguard Worker    TEST(0,
47*61046927SAndroid Build Coastguard Worker       mov.f32f32 r0.x, c0.x
48*61046927SAndroid Build Coastguard Worker       rcp r0.x, r0.y
49*61046927SAndroid Build Coastguard Worker       add.f r0.x, r0.x, c0.x
50*61046927SAndroid Build Coastguard Worker    ),
51*61046927SAndroid Build Coastguard Worker    TEST(2,
52*61046927SAndroid Build Coastguard Worker       mov.f32f32 r0.x, c0.x
53*61046927SAndroid Build Coastguard Worker       mov.f32f32 r0.y, c0.y
54*61046927SAndroid Build Coastguard Worker       (rpt1)add.f r0.x, (r)r0.x, (r)c0.x
55*61046927SAndroid Build Coastguard Worker    ),
56*61046927SAndroid Build Coastguard Worker    TEST(2,
57*61046927SAndroid Build Coastguard Worker       (rpt1)mov.f32f32 r0.x, c0.x
58*61046927SAndroid Build Coastguard Worker       (rpt1)add.f r0.x, (r)r0.x, (r)c0.x
59*61046927SAndroid Build Coastguard Worker    ),
60*61046927SAndroid Build Coastguard Worker    TEST(3,
61*61046927SAndroid Build Coastguard Worker       mov.f32f32 r0.y, c0.y
62*61046927SAndroid Build Coastguard Worker       mov.f32f32 r0.x, c0.x
63*61046927SAndroid Build Coastguard Worker       (rpt1)add.f r0.x, (r)r0.x, (r)c0.x
64*61046927SAndroid Build Coastguard Worker    ),
65*61046927SAndroid Build Coastguard Worker    TEST(1,
66*61046927SAndroid Build Coastguard Worker       (rpt2)mov.f32f32 r0.x, (r)c0.x
67*61046927SAndroid Build Coastguard Worker       add.f r0.x, r0.x, c0.x
68*61046927SAndroid Build Coastguard Worker    ),
69*61046927SAndroid Build Coastguard Worker    TEST(2,
70*61046927SAndroid Build Coastguard Worker       (rpt2)mov.f32f32 r0.x, (r)c0.x
71*61046927SAndroid Build Coastguard Worker       add.f r0.x, r0.x, r0.y
72*61046927SAndroid Build Coastguard Worker    ),
73*61046927SAndroid Build Coastguard Worker    TEST(2,
74*61046927SAndroid Build Coastguard Worker       (rpt1)mov.f32f32 r0.x, (r)c0.x
75*61046927SAndroid Build Coastguard Worker       (rpt1)add.f r0.x, (r)r0.x, c0.x
76*61046927SAndroid Build Coastguard Worker    ),
77*61046927SAndroid Build Coastguard Worker    TEST(1,
78*61046927SAndroid Build Coastguard Worker       (rpt1)mov.f32f32 r0.y, (r)c0.x
79*61046927SAndroid Build Coastguard Worker       (rpt1)add.f r0.x, (r)r0.x, c0.x
80*61046927SAndroid Build Coastguard Worker    ),
81*61046927SAndroid Build Coastguard Worker    TEST(3,
82*61046927SAndroid Build Coastguard Worker       (rpt1)mov.f32f32 r0.x, (r)c0.x
83*61046927SAndroid Build Coastguard Worker       (rpt1)add.f r0.x, (r)r0.y, c0.x
84*61046927SAndroid Build Coastguard Worker    ),
85*61046927SAndroid Build Coastguard Worker    /* clang-format on */
86*61046927SAndroid Build Coastguard Worker };
87*61046927SAndroid Build Coastguard Worker 
88*61046927SAndroid Build Coastguard Worker static struct ir3_shader *
parse_asm(struct ir3_compiler * c,const char * asmstr)89*61046927SAndroid Build Coastguard Worker parse_asm(struct ir3_compiler *c, const char *asmstr)
90*61046927SAndroid Build Coastguard Worker {
91*61046927SAndroid Build Coastguard Worker    struct ir3_kernel_info info = {};
92*61046927SAndroid Build Coastguard Worker    FILE *in = fmemopen((void *)asmstr, strlen(asmstr), "r");
93*61046927SAndroid Build Coastguard Worker    struct ir3_shader *shader = ir3_parse_asm(c, &info, in);
94*61046927SAndroid Build Coastguard Worker 
95*61046927SAndroid Build Coastguard Worker    fclose(in);
96*61046927SAndroid Build Coastguard Worker 
97*61046927SAndroid Build Coastguard Worker    if (!shader)
98*61046927SAndroid Build Coastguard Worker       errx(-1, "assembler failed");
99*61046927SAndroid Build Coastguard Worker 
100*61046927SAndroid Build Coastguard Worker    return shader;
101*61046927SAndroid Build Coastguard Worker }
102*61046927SAndroid Build Coastguard Worker 
103*61046927SAndroid Build Coastguard Worker /**
104*61046927SAndroid Build Coastguard Worker  * ir3_delay_calc_* relies on the src/dst wrmask being correct even for ALU
105*61046927SAndroid Build Coastguard Worker  * instructions, so this sets it here.
106*61046927SAndroid Build Coastguard Worker  *
107*61046927SAndroid Build Coastguard Worker  * Note that this is not clever enough to know how many src/dst there are
108*61046927SAndroid Build Coastguard Worker  * for various tex/mem instructions.  But the rules for tex consuming alu
109*61046927SAndroid Build Coastguard Worker  * are the same as sfu consuming alu.
110*61046927SAndroid Build Coastguard Worker  */
111*61046927SAndroid Build Coastguard Worker static void
fixup_wrmask(struct ir3 * ir)112*61046927SAndroid Build Coastguard Worker fixup_wrmask(struct ir3 *ir)
113*61046927SAndroid Build Coastguard Worker {
114*61046927SAndroid Build Coastguard Worker    struct ir3_block *block = ir3_start_block(ir);
115*61046927SAndroid Build Coastguard Worker 
116*61046927SAndroid Build Coastguard Worker    foreach_instr_safe (instr, &block->instr_list) {
117*61046927SAndroid Build Coastguard Worker       instr->dsts[0]->wrmask = MASK(instr->repeat + 1);
118*61046927SAndroid Build Coastguard Worker       foreach_src (reg, instr) {
119*61046927SAndroid Build Coastguard Worker          if (reg->flags & (IR3_REG_CONST | IR3_REG_IMMED))
120*61046927SAndroid Build Coastguard Worker             continue;
121*61046927SAndroid Build Coastguard Worker 
122*61046927SAndroid Build Coastguard Worker          if (reg->flags & IR3_REG_R)
123*61046927SAndroid Build Coastguard Worker             reg->wrmask = MASK(instr->repeat + 1);
124*61046927SAndroid Build Coastguard Worker          else
125*61046927SAndroid Build Coastguard Worker             reg->wrmask = 1;
126*61046927SAndroid Build Coastguard Worker       }
127*61046927SAndroid Build Coastguard Worker    }
128*61046927SAndroid Build Coastguard Worker }
129*61046927SAndroid Build Coastguard Worker 
130*61046927SAndroid Build Coastguard Worker /* Calculate the number of nops added before the last instruction by
131*61046927SAndroid Build Coastguard Worker  * ir3_legalize.
132*61046927SAndroid Build Coastguard Worker  */
133*61046927SAndroid Build Coastguard Worker static unsigned
calc_nops(struct ir3_block * block,struct ir3_instruction * last)134*61046927SAndroid Build Coastguard Worker calc_nops(struct ir3_block *block, struct ir3_instruction *last)
135*61046927SAndroid Build Coastguard Worker {
136*61046927SAndroid Build Coastguard Worker    unsigned nops = 0;
137*61046927SAndroid Build Coastguard Worker 
138*61046927SAndroid Build Coastguard Worker    foreach_instr_rev (instr, &block->instr_list) {
139*61046927SAndroid Build Coastguard Worker       if (instr == last)
140*61046927SAndroid Build Coastguard Worker          continue;
141*61046927SAndroid Build Coastguard Worker 
142*61046927SAndroid Build Coastguard Worker       if (instr->opc == OPC_NOP) {
143*61046927SAndroid Build Coastguard Worker          nops += 1 + instr->repeat;
144*61046927SAndroid Build Coastguard Worker       } else {
145*61046927SAndroid Build Coastguard Worker          if (is_alu(instr))
146*61046927SAndroid Build Coastguard Worker             nops += instr->nop;
147*61046927SAndroid Build Coastguard Worker          break;
148*61046927SAndroid Build Coastguard Worker       }
149*61046927SAndroid Build Coastguard Worker    }
150*61046927SAndroid Build Coastguard Worker 
151*61046927SAndroid Build Coastguard Worker    return nops;
152*61046927SAndroid Build Coastguard Worker }
153*61046927SAndroid Build Coastguard Worker 
154*61046927SAndroid Build Coastguard Worker int
main(int argc,char ** argv)155*61046927SAndroid Build Coastguard Worker main(int argc, char **argv)
156*61046927SAndroid Build Coastguard Worker {
157*61046927SAndroid Build Coastguard Worker    struct ir3_compiler *c;
158*61046927SAndroid Build Coastguard Worker    int result = 0;
159*61046927SAndroid Build Coastguard Worker 
160*61046927SAndroid Build Coastguard Worker    struct fd_dev_id dev_id = {
161*61046927SAndroid Build Coastguard Worker          .gpu_id = 630,
162*61046927SAndroid Build Coastguard Worker    };
163*61046927SAndroid Build Coastguard Worker 
164*61046927SAndroid Build Coastguard Worker    c = ir3_compiler_create(NULL, &dev_id, fd_dev_info_raw(&dev_id), &(struct ir3_compiler_options){});
165*61046927SAndroid Build Coastguard Worker 
166*61046927SAndroid Build Coastguard Worker    for (int i = 0; i < ARRAY_SIZE(tests); i++) {
167*61046927SAndroid Build Coastguard Worker       const struct test *test = &tests[i];
168*61046927SAndroid Build Coastguard Worker       struct ir3_shader *shader = parse_asm(c, test->asmstr);
169*61046927SAndroid Build Coastguard Worker       struct ir3 *ir = shader->variants->ir;
170*61046927SAndroid Build Coastguard Worker 
171*61046927SAndroid Build Coastguard Worker       fixup_wrmask(ir);
172*61046927SAndroid Build Coastguard Worker 
173*61046927SAndroid Build Coastguard Worker       ir3_debug_print(ir, "AFTER fixup_wrmask");
174*61046927SAndroid Build Coastguard Worker 
175*61046927SAndroid Build Coastguard Worker       struct ir3_block *block =
176*61046927SAndroid Build Coastguard Worker          list_first_entry(&ir->block_list, struct ir3_block, node);
177*61046927SAndroid Build Coastguard Worker       struct ir3_instruction *last = NULL;
178*61046927SAndroid Build Coastguard Worker 
179*61046927SAndroid Build Coastguard Worker       foreach_instr_rev (instr, &block->instr_list) {
180*61046927SAndroid Build Coastguard Worker          if (is_meta(instr))
181*61046927SAndroid Build Coastguard Worker             continue;
182*61046927SAndroid Build Coastguard Worker          last = instr;
183*61046927SAndroid Build Coastguard Worker          break;
184*61046927SAndroid Build Coastguard Worker       }
185*61046927SAndroid Build Coastguard Worker 
186*61046927SAndroid Build Coastguard Worker       int max_bary;
187*61046927SAndroid Build Coastguard Worker       ir3_legalize(ir, shader->variants, &max_bary);
188*61046927SAndroid Build Coastguard Worker 
189*61046927SAndroid Build Coastguard Worker       unsigned n = calc_nops(block, last);
190*61046927SAndroid Build Coastguard Worker 
191*61046927SAndroid Build Coastguard Worker       if (n != test->expected_delay) {
192*61046927SAndroid Build Coastguard Worker          printf("%d: FAIL: Expected delay %u, but got %u, for:\n%s\n", i,
193*61046927SAndroid Build Coastguard Worker                 test->expected_delay, n, test->asmstr);
194*61046927SAndroid Build Coastguard Worker          result = -1;
195*61046927SAndroid Build Coastguard Worker       } else {
196*61046927SAndroid Build Coastguard Worker          printf("%d: PASS\n", i);
197*61046927SAndroid Build Coastguard Worker       }
198*61046927SAndroid Build Coastguard Worker 
199*61046927SAndroid Build Coastguard Worker       ir3_shader_destroy(shader);
200*61046927SAndroid Build Coastguard Worker    }
201*61046927SAndroid Build Coastguard Worker 
202*61046927SAndroid Build Coastguard Worker    ir3_compiler_destroy(c);
203*61046927SAndroid Build Coastguard Worker 
204*61046927SAndroid Build Coastguard Worker    return result;
205*61046927SAndroid Build Coastguard Worker }
206