2 * Copyright © 2020 Valve Corporation
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:
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
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
27 #include <llvm-c/Target.h>
31 ac_shader_config config
;
32 radv_shader_info info
;
33 std::unique_ptr
<Program
> program
;
37 const char *subvariant
= "";
39 void create_program(enum chip_class chip_class
, Stage stage
, unsigned wave_size
, enum radeon_family family
)
41 memset(&config
, 0, sizeof(config
));
42 info
.wave_size
= wave_size
;
44 program
.reset(new Program
);
45 aco::init_program(program
.get(), stage
, &info
, chip_class
, family
, &config
);
47 Block
*block
= program
->create_and_insert_block();
48 block
->kind
= block_kind_top_level
;
50 bld
= Builder(program
.get(), &program
->blocks
[0]);
52 config
.float_mode
= program
->blocks
[0].fp_mode
.val
;
55 bool setup_cs(const char *input_spec
, enum chip_class chip_class
,
56 enum radeon_family family
, unsigned wave_size
)
58 const char *old_subvariant
= subvariant
;
60 if (!set_variant(chip_class
, old_subvariant
))
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;
68 create_program(chip_class
, compute_cs
, wave_size
, family
);
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
]);
78 exec_input
= bld
.tmp(program
->lane_mask
);
79 startpgm
->definitions
[num_inputs
] = bld
.exec(Definition(exec_input
));
80 bld
.insert(std::move(startpgm
));
86 void finish_program(Program
*program
)
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
);
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
);
106 void finish_validator_test()
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");
114 fprintf(output
, "Validation failed\n");
117 void finish_opt_test()
119 finish_program(program
.get());
120 if (!aco::validate(program
.get(), output
)) {
121 fail_test("Validation before optimization failed");
124 aco::optimize(program
.get());
125 if (!aco::validate(program
.get(), output
)) {
126 fail_test("Validation after optimization failed");
129 aco_print_program(program
.get(), output
);
132 void finish_to_hw_instr_test()
134 finish_program(program
.get());
135 aco::lower_to_hw_instr(program
.get());
136 aco_print_program(program
.get(), output
);
139 void finish_assembler_test()
141 finish_program(program
.get());
142 std::vector
<uint32_t> binary
;
143 unsigned exec_size
= emit_program(program
.get(), binary
);
145 /* we could use CLRX for disassembly but that would require it to be
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
);
155 fputs(ss
.str().c_str(), output
);
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
);
163 void writeout(unsigned i
, Temp tmp
)
166 bld
.pseudo(aco_opcode::p_unit_test
, Operand(i
), tmp
);
168 bld
.pseudo(aco_opcode::p_unit_test
, Operand(i
));