xref: /aosp_15_r20/external/mesa3d/src/intel/compiler/elk/elk_test_eu_compact.cpp (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © 2012 Intel Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  */
23 
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <stdbool.h>
27 #include "util/ralloc.h"
28 #include "elk_disasm.h"
29 #include "elk_eu.h"
30 
31 #include <gtest/gtest.h>
32 
33 struct CompactParams {
34    unsigned verx10;
35    unsigned align;
36 };
37 
38 std::string
get_compact_params_name(const testing::TestParamInfo<CompactParams> p)39 get_compact_params_name(const testing::TestParamInfo<CompactParams> p)
40 {
41    CompactParams params = p.param;
42    std::stringstream ss;
43    ss << params.verx10 << "_";
44    switch (params.align) {
45    case ELK_ALIGN_1:
46       ss << "Align_1";
47       break;
48    case ELK_ALIGN_16:
49       ss << "Align_16";
50       break;
51    default:
52       unreachable("invalid align");
53    }
54    return ss.str();
55 }
56 
57 static bool
test_compact_instruction(struct elk_codegen * p,elk_inst src)58 test_compact_instruction(struct elk_codegen *p, elk_inst src)
59 {
60    elk_compact_inst dst;
61    memset(&dst, 0xd0, sizeof(dst));
62 
63    if (elk_try_compact_instruction(p->isa, &dst, &src)) {
64       elk_inst uncompacted;
65 
66       elk_uncompact_instruction(p->isa, &uncompacted, &dst);
67       if (memcmp(&uncompacted, &src, sizeof(src))) {
68 	 elk_debug_compact_uncompact(p->isa, &src, &uncompacted);
69 	 return false;
70       }
71    } else {
72       elk_compact_inst unchanged;
73       memset(&unchanged, 0xd0, sizeof(unchanged));
74       /* It's not supposed to change dst unless it compacted. */
75       if (memcmp(&unchanged, &dst, sizeof(dst))) {
76 	 fprintf(stderr, "Failed to compact, but dst changed\n");
77 	 fprintf(stderr, "  Instruction: ");
78 	 elk_disassemble_inst(stderr, p->isa, &src, false, 0, NULL);
79 	 return false;
80       }
81    }
82 
83    return true;
84 }
85 
86 /**
87  * When doing fuzz testing, pad bits won't round-trip.
88  *
89  * This sort of a superset of skip_bit, which is testing for changing bits that
90  * aren't worth testing for fuzzing.  We also just want to clear bits that
91  * become meaningless once fuzzing twiddles a related bit.
92  */
93 static void
clear_pad_bits(const struct elk_isa_info * isa,elk_inst * inst)94 clear_pad_bits(const struct elk_isa_info *isa, elk_inst *inst)
95 {
96    const struct intel_device_info *devinfo = isa->devinfo;
97 
98    if (elk_inst_opcode(isa, inst) != ELK_OPCODE_SEND &&
99        elk_inst_opcode(isa, inst) != ELK_OPCODE_SENDC &&
100        elk_inst_src0_reg_file(devinfo, inst) != ELK_IMMEDIATE_VALUE &&
101        elk_inst_src1_reg_file(devinfo, inst) != ELK_IMMEDIATE_VALUE) {
102       elk_inst_set_bits(inst, 127, 111, 0);
103    }
104 
105    if (devinfo->ver == 8 && devinfo->platform != INTEL_PLATFORM_CHV &&
106        elk_is_3src(isa, elk_inst_opcode(isa, inst))) {
107       elk_inst_set_bits(inst, 105, 105, 0);
108       elk_inst_set_bits(inst, 84, 84, 0);
109       elk_inst_set_bits(inst, 36, 35, 0);
110    }
111 }
112 
113 static bool
skip_bit(const struct elk_isa_info * isa,elk_inst * src,int bit)114 skip_bit(const struct elk_isa_info *isa, elk_inst *src, int bit)
115 {
116    const struct intel_device_info *devinfo = isa->devinfo;
117 
118    /* pad bit */
119    if (bit == 7)
120       return true;
121 
122    /* The compact bit -- uncompacted can't have it set. */
123    if (bit == 29)
124       return true;
125 
126    if (elk_is_3src(isa, elk_inst_opcode(isa, src))) {
127       if (devinfo->platform == INTEL_PLATFORM_CHV) {
128          if (bit == 127)
129             return true;
130       } else {
131          if (bit >= 126 && bit <= 127)
132             return true;
133 
134          if (bit == 105)
135             return true;
136 
137          if (bit == 84)
138             return true;
139 
140          if (bit >= 35 && bit <= 36)
141             return true;
142       }
143    } else {
144       if (bit == 47)
145          return true;
146 
147       if (devinfo->ver >= 8) {
148          if (bit == 11)
149             return true;
150 
151          if (bit == 95)
152             return true;
153       } else {
154          if (devinfo->ver < 7 && bit == 90)
155             return true;
156 
157          if (bit >= 91 && bit <= 95)
158             return true;
159       }
160    }
161 
162    /* sometimes these are pad bits. */
163    if (elk_inst_opcode(isa, src) != ELK_OPCODE_SEND &&
164        elk_inst_opcode(isa, src) != ELK_OPCODE_SENDC &&
165        elk_inst_src0_reg_file(devinfo, src) != ELK_IMMEDIATE_VALUE &&
166        elk_inst_src1_reg_file(devinfo, src) != ELK_IMMEDIATE_VALUE &&
167        bit >= 121) {
168       return true;
169    }
170 
171    return false;
172 }
173 
174 static bool
test_fuzz_compact_instruction(struct elk_codegen * p,elk_inst src)175 test_fuzz_compact_instruction(struct elk_codegen *p, elk_inst src)
176 {
177    for (int bit0 = 0; bit0 < 128; bit0++) {
178       if (skip_bit(p->isa, &src, bit0))
179 	 continue;
180 
181       for (int bit1 = 0; bit1 < 128; bit1++) {
182          elk_inst instr = src;
183 	 uint64_t *bits = instr.data;
184 
185          if (skip_bit(p->isa, &src, bit1))
186 	    continue;
187 
188 	 bits[bit0 / 64] ^= (1ull << (bit0 & 63));
189 	 bits[bit1 / 64] ^= (1ull << (bit1 & 63));
190 
191          clear_pad_bits(p->isa, &instr);
192 
193          if (!elk_validate_instruction(p->isa, &instr, 0, sizeof(elk_inst), NULL))
194             continue;
195 
196 	 if (!test_compact_instruction(p, instr)) {
197 	    printf("  twiddled bits for fuzzing %d, %d\n", bit0, bit1);
198 	    return false;
199 	 }
200       }
201    }
202 
203    return true;
204 }
205 
206 class CompactTestFixture : public testing::TestWithParam<CompactParams> {
207 protected:
SetUp()208    virtual void SetUp() {
209       CompactParams params = GetParam();
210       mem_ctx = ralloc_context(NULL);
211       devinfo = rzalloc(mem_ctx, intel_device_info);
212       p = rzalloc(mem_ctx, elk_codegen);
213 
214       devinfo->verx10 = params.verx10;
215       devinfo->ver = devinfo->verx10 / 10;
216 
217       elk_init_isa_info(&isa, devinfo);
218       elk_init_codegen(&isa, p, p);
219       elk_set_default_predicate_control(p, ELK_PREDICATE_NONE);
220       elk_set_default_access_mode(p, params.align);
221    };
222 
TearDown()223    virtual void TearDown() {
224       EXPECT_EQ(p->nr_insn, 1);
225       EXPECT_TRUE(test_compact_instruction(p, p->store[0]));
226       EXPECT_TRUE(test_fuzz_compact_instruction(p, p->store[0]));
227 
228       ralloc_free(mem_ctx);
229    };
230 
231    void *mem_ctx;
232    struct elk_isa_info isa;
233    intel_device_info *devinfo;
234    elk_codegen *p;
235 };
236 
237 class Instructions : public CompactTestFixture {};
238 
239 INSTANTIATE_TEST_SUITE_P(
240    CompactTest,
241    Instructions,
242    testing::Values(
243       CompactParams{ 50,  ELK_ALIGN_1 }, CompactParams{ 50, ELK_ALIGN_16 },
244       CompactParams{ 60,  ELK_ALIGN_1 }, CompactParams{ 60, ELK_ALIGN_16 },
245       CompactParams{ 70,  ELK_ALIGN_1 }, CompactParams{ 70, ELK_ALIGN_16 },
246       CompactParams{ 75,  ELK_ALIGN_1 }, CompactParams{ 75, ELK_ALIGN_16 },
247       CompactParams{ 80,  ELK_ALIGN_1 }, CompactParams{ 80, ELK_ALIGN_16 }
248    ),
249    get_compact_params_name);
250 
251 class InstructionsBeforeIvyBridge : public CompactTestFixture {};
252 
253 INSTANTIATE_TEST_SUITE_P(
254    CompactTest,
255    InstructionsBeforeIvyBridge,
256    testing::Values(
257       CompactParams{ 50,  ELK_ALIGN_1 }, CompactParams{ 50, ELK_ALIGN_16 },
258       CompactParams{ 60,  ELK_ALIGN_1 }, CompactParams{ 60, ELK_ALIGN_16 }
259    ),
260    get_compact_params_name);
261 
262 
TEST_P(Instructions,ADD_GRF_GRF_GRF)263 TEST_P(Instructions, ADD_GRF_GRF_GRF)
264 {
265    struct elk_reg g0 = elk_vec8_grf(0, 0);
266    struct elk_reg g2 = elk_vec8_grf(2, 0);
267    struct elk_reg g4 = elk_vec8_grf(4, 0);
268 
269    elk_ADD(p, g0, g2, g4);
270 }
271 
TEST_P(Instructions,ADD_GRF_GRF_IMM)272 TEST_P(Instructions, ADD_GRF_GRF_IMM)
273 {
274    struct elk_reg g0 = elk_vec8_grf(0, 0);
275    struct elk_reg g2 = elk_vec8_grf(2, 0);
276 
277    elk_ADD(p, g0, g2, elk_imm_f(1.0));
278 }
279 
TEST_P(Instructions,ADD_GRF_GRF_IMM_d)280 TEST_P(Instructions, ADD_GRF_GRF_IMM_d)
281 {
282    struct elk_reg g0 = retype(elk_vec8_grf(0, 0), ELK_REGISTER_TYPE_D);
283    struct elk_reg g2 = retype(elk_vec8_grf(2, 0), ELK_REGISTER_TYPE_D);
284 
285    elk_ADD(p, g0, g2, elk_imm_d(1));
286 }
287 
TEST_P(Instructions,MOV_GRF_GRF)288 TEST_P(Instructions, MOV_GRF_GRF)
289 {
290    struct elk_reg g0 = elk_vec8_grf(0, 0);
291    struct elk_reg g2 = elk_vec8_grf(2, 0);
292 
293    elk_MOV(p, g0, g2);
294 }
295 
TEST_P(InstructionsBeforeIvyBridge,ADD_MRF_GRF_GRF)296 TEST_P(InstructionsBeforeIvyBridge, ADD_MRF_GRF_GRF)
297 {
298    struct elk_reg m6 = elk_vec8_reg(ELK_MESSAGE_REGISTER_FILE, 6, 0);
299    struct elk_reg g2 = elk_vec8_grf(2, 0);
300    struct elk_reg g4 = elk_vec8_grf(4, 0);
301 
302    elk_ADD(p, m6, g2, g4);
303 }
304 
TEST_P(Instructions,ADD_vec1_GRF_GRF_GRF)305 TEST_P(Instructions, ADD_vec1_GRF_GRF_GRF)
306 {
307    struct elk_reg g0 = elk_vec1_grf(0, 0);
308    struct elk_reg g2 = elk_vec1_grf(2, 0);
309    struct elk_reg g4 = elk_vec1_grf(4, 0);
310 
311    elk_ADD(p, g0, g2, g4);
312 }
313 
TEST_P(InstructionsBeforeIvyBridge,PLN_MRF_GRF_GRF)314 TEST_P(InstructionsBeforeIvyBridge, PLN_MRF_GRF_GRF)
315 {
316    struct elk_reg m6 = elk_vec8_reg(ELK_MESSAGE_REGISTER_FILE, 6, 0);
317    struct elk_reg interp = elk_vec1_grf(2, 0);
318    struct elk_reg g4 = elk_vec8_grf(4, 0);
319 
320    elk_PLN(p, m6, interp, g4);
321 }
322 
TEST_P(Instructions,f0_0_MOV_GRF_GRF)323 TEST_P(Instructions, f0_0_MOV_GRF_GRF)
324 {
325    struct elk_reg g0 = elk_vec8_grf(0, 0);
326    struct elk_reg g2 = elk_vec8_grf(2, 0);
327 
328    elk_push_insn_state(p);
329    elk_set_default_predicate_control(p, ELK_PREDICATE_NORMAL);
330    elk_MOV(p, g0, g2);
331    elk_pop_insn_state(p);
332 }
333 
334 /* The handling of f0.1 vs f0.0 changes between gfx6 and gfx7.  Explicitly test
335  * it, so that we run the fuzzing can run over all the other bits that might
336  * interact with it.
337  */
TEST_P(Instructions,f0_1_MOV_GRF_GRF)338 TEST_P(Instructions, f0_1_MOV_GRF_GRF)
339 {
340    struct elk_reg g0 = elk_vec8_grf(0, 0);
341    struct elk_reg g2 = elk_vec8_grf(2, 0);
342 
343    elk_push_insn_state(p);
344    elk_set_default_predicate_control(p, ELK_PREDICATE_NORMAL);
345    elk_inst *mov = elk_MOV(p, g0, g2);
346    elk_inst_set_flag_subreg_nr(p->devinfo, mov, 1);
347    elk_pop_insn_state(p);
348 }
349