f2b7ec786abe8eeec8c540bd7759c2218566cb60
[mesa.git] / src / amd / compiler / tests / helpers.cpp
1 /*
2 * Copyright © 2020 Valve 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 "helpers.h"
25 #include <stdio.h>
26 #include <sstream>
27 #include <llvm-c/Target.h>
28
29 using namespace aco;
30
31 ac_shader_config config;
32 radv_shader_info info;
33 std::unique_ptr<Program> program;
34 Builder bld(NULL);
35 Temp inputs[16];
36 Temp exec_input;
37 const char *subvariant = "";
38
39 void create_program(enum chip_class chip_class, Stage stage, unsigned wave_size, enum radeon_family family)
40 {
41 memset(&config, 0, sizeof(config));
42 info.wave_size = wave_size;
43
44 program.reset(new Program);
45 aco::init_program(program.get(), stage, &info, chip_class, family, &config);
46
47 Block *block = program->create_and_insert_block();
48 block->kind = block_kind_top_level;
49
50 bld = Builder(program.get(), &program->blocks[0]);
51
52 config.float_mode = program->blocks[0].fp_mode.val;
53 }
54
55 bool setup_cs(const char *input_spec, enum chip_class chip_class,
56 enum radeon_family family, unsigned wave_size)
57 {
58 const char *old_subvariant = subvariant;
59 subvariant = "";
60 if (!set_variant(chip_class, old_subvariant))
61 return false;
62
63 memset(&info, 0, sizeof(info));
64 info.cs.block_size[0] = 1;
65 info.cs.block_size[1] = 1;
66 info.cs.block_size[2] = 1;
67
68 create_program(chip_class, compute_cs, wave_size, family);
69
70 if (input_spec) {
71 unsigned num_inputs = DIV_ROUND_UP(strlen(input_spec), 3u);
72 aco_ptr<Instruction> startpgm{create_instruction<Pseudo_instruction>(aco_opcode::p_startpgm, Format::PSEUDO, 0, num_inputs + 1)};
73 for (unsigned i = 0; i < num_inputs; i++) {
74 RegClass cls(input_spec[i * 3] == 'v' ? RegType::vgpr : RegType::sgpr, input_spec[i * 3 + 1] - '0');
75 inputs[i] = bld.tmp(cls);
76 startpgm->definitions[i] = Definition(inputs[i]);
77 }
78 exec_input = bld.tmp(program->lane_mask);
79 startpgm->definitions[num_inputs] = bld.exec(Definition(exec_input));
80 bld.insert(std::move(startpgm));
81 }
82
83 return true;
84 }
85
86 void finish_program(Program *program)
87 {
88 for (Block& BB : program->blocks) {
89 for (unsigned idx : BB.linear_preds)
90 program->blocks[idx].linear_succs.emplace_back(BB.index);
91 for (unsigned idx : BB.logical_preds)
92 program->blocks[idx].logical_succs.emplace_back(BB.index);
93 }
94
95 for (Block& block : program->blocks) {
96 if (block.linear_succs.size() == 0) {
97 block.kind |= block_kind_uniform;
98 Builder bld(program, &block);
99 if (program->wb_smem_l1_on_end)
100 bld.smem(aco_opcode::s_dcache_wb, false);
101 bld.sopp(aco_opcode::s_endpgm);
102 }
103 }
104 }
105
106 void finish_validator_test()
107 {
108 finish_program(program.get());
109 aco_print_program(program.get(), output);
110 fprintf(output, "Validation results:\n");
111 if (aco::validate(program.get(), output))
112 fprintf(output, "Validation passed\n");
113 else
114 fprintf(output, "Validation failed\n");
115 }
116
117 void finish_opt_test()
118 {
119 finish_program(program.get());
120 if (!aco::validate(program.get(), output)) {
121 fail_test("Validation before optimization failed");
122 return;
123 }
124 aco::optimize(program.get());
125 if (!aco::validate(program.get(), output)) {
126 fail_test("Validation after optimization failed");
127 return;
128 }
129 aco_print_program(program.get(), output);
130 }
131
132 void finish_to_hw_instr_test()
133 {
134 finish_program(program.get());
135 aco::lower_to_hw_instr(program.get());
136 aco_print_program(program.get(), output);
137 }
138
139 void finish_assembler_test()
140 {
141 finish_program(program.get());
142 std::vector<uint32_t> binary;
143 unsigned exec_size = emit_program(program.get(), binary);
144
145 /* we could use CLRX for disassembly but that would require it to be
146 * installed */
147 if (program->chip_class == GFX10_3 && LLVM_VERSION_MAJOR < 9) {
148 skip_test("LLVM 11 needed for GFX10_3 disassembly");
149 } else if (program->chip_class == GFX10 && LLVM_VERSION_MAJOR < 9) {
150 skip_test("LLVM 9 needed for GFX10 disassembly");
151 } else if (program->chip_class >= GFX8) {
152 std::ostringstream ss;
153 print_asm(program.get(), binary, exec_size / 4u, ss);
154
155 fputs(ss.str().c_str(), output);
156 } else {
157 //TODO: maybe we should use CLRX and skip this test if it's not available?
158 for (uint32_t dword : binary)
159 fprintf(output, "%.8x\n", dword);
160 }
161 }
162
163 void writeout(unsigned i, Temp tmp)
164 {
165 if (tmp.id())
166 bld.pseudo(aco_opcode::p_unit_test, Operand(i), tmp);
167 else
168 bld.pseudo(aco_opcode::p_unit_test, Operand(i));
169 }
170