pan/bi: Walk through the NIR control flow graph
[mesa.git] / src / panfrost / bifrost / bifrost_compile.c
1 /*
2 * Copyright (C) 2020 Collabora Ltd.
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 FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 *
23 * Authors (Collabora):
24 * Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
25 */
26
27 #include "main/mtypes.h"
28 #include "compiler/glsl/glsl_to_nir.h"
29 #include "compiler/nir_types.h"
30 #include "main/imports.h"
31 #include "compiler/nir/nir_builder.h"
32
33 #include "disassemble.h"
34 #include "bifrost_compile.h"
35 #include "compiler.h"
36 #include "bi_quirks.h"
37 #include "bi_print.h"
38
39 static bi_block *emit_cf_list(bi_context *ctx, struct exec_list *list);
40
41 static bi_block *
42 create_empty_block(bi_context *ctx)
43 {
44 bi_block *blk = rzalloc(ctx, bi_block);
45
46 blk->predecessors = _mesa_set_create(blk,
47 _mesa_hash_pointer,
48 _mesa_key_pointer_equal);
49
50 blk->name = ctx->block_name_count++;
51
52 return blk;
53 }
54
55 static bi_block *
56 emit_block(bi_context *ctx, nir_block *block)
57 {
58 ctx->current_block = create_empty_block(ctx);
59 list_addtail(&ctx->current_block->link, &ctx->blocks);
60 list_inithead(&ctx->current_block->instructions);
61
62 nir_foreach_instr(instr, block) {
63 //emit_instr(ctx, instr);
64 ++ctx->instruction_count;
65 }
66
67 return ctx->current_block;
68 }
69
70 static bi_block *
71 emit_cf_list(bi_context *ctx, struct exec_list *list)
72 {
73 bi_block *start_block = NULL;
74
75 foreach_list_typed(nir_cf_node, node, node, list) {
76 switch (node->type) {
77 case nir_cf_node_block: {
78 bi_block *block = emit_block(ctx, nir_cf_node_as_block(node));
79
80 if (!start_block)
81 start_block = block;
82
83 break;
84 }
85
86 #if 0
87 case nir_cf_node_if:
88 emit_if(ctx, nir_cf_node_as_if(node));
89 break;
90
91 case nir_cf_node_loop:
92 emit_loop(ctx, nir_cf_node_as_loop(node));
93 break;
94 #endif
95
96 default:
97 unreachable("Unknown control flow");
98 }
99 }
100
101 return start_block;
102 }
103
104 static int
105 glsl_type_size(const struct glsl_type *type, bool bindless)
106 {
107 return glsl_count_attribute_slots(type, false);
108 }
109
110 static void
111 bi_optimize_nir(nir_shader *nir)
112 {
113 bool progress;
114 unsigned lower_flrp = 16 | 32 | 64;
115
116 NIR_PASS(progress, nir, nir_lower_regs_to_ssa);
117 NIR_PASS(progress, nir, nir_lower_idiv, nir_lower_idiv_fast);
118
119 nir_lower_tex_options lower_tex_options = {
120 .lower_txs_lod = true,
121 .lower_txp = ~0,
122 .lower_tex_without_implicit_lod = true,
123 .lower_txd = true,
124 };
125
126 NIR_PASS(progress, nir, nir_lower_tex, &lower_tex_options);
127
128 do {
129 progress = false;
130
131 NIR_PASS(progress, nir, nir_lower_var_copies);
132 NIR_PASS(progress, nir, nir_lower_vars_to_ssa);
133
134 NIR_PASS(progress, nir, nir_copy_prop);
135 NIR_PASS(progress, nir, nir_opt_remove_phis);
136 NIR_PASS(progress, nir, nir_opt_dce);
137 NIR_PASS(progress, nir, nir_opt_dead_cf);
138 NIR_PASS(progress, nir, nir_opt_cse);
139 NIR_PASS(progress, nir, nir_opt_peephole_select, 64, false, true);
140 NIR_PASS(progress, nir, nir_opt_algebraic);
141 NIR_PASS(progress, nir, nir_opt_constant_folding);
142
143 if (lower_flrp != 0) {
144 bool lower_flrp_progress = false;
145 NIR_PASS(lower_flrp_progress,
146 nir,
147 nir_lower_flrp,
148 lower_flrp,
149 false /* always_precise */,
150 nir->options->lower_ffma);
151 if (lower_flrp_progress) {
152 NIR_PASS(progress, nir,
153 nir_opt_constant_folding);
154 progress = true;
155 }
156
157 /* Nothing should rematerialize any flrps, so we only
158 * need to do this lowering once.
159 */
160 lower_flrp = 0;
161 }
162
163 NIR_PASS(progress, nir, nir_opt_undef);
164 NIR_PASS(progress, nir, nir_opt_loop_unroll,
165 nir_var_shader_in |
166 nir_var_shader_out |
167 nir_var_function_temp);
168 } while (progress);
169
170 NIR_PASS(progress, nir, nir_opt_algebraic_late);
171
172 /* Take us out of SSA */
173 NIR_PASS(progress, nir, nir_lower_locals_to_regs);
174 NIR_PASS(progress, nir, nir_convert_from_ssa, true);
175 }
176
177 void
178 bifrost_compile_shader_nir(nir_shader *nir, bifrost_program *program, unsigned product_id)
179 {
180 bi_context *ctx = rzalloc(NULL, bi_context);
181 ctx->nir = nir;
182 ctx->stage = nir->info.stage;
183 ctx->quirks = bifrost_get_quirks(product_id);
184 list_inithead(&ctx->blocks);
185
186 /* Lower gl_Position pre-optimisation, but after lowering vars to ssa
187 * (so we don't accidentally duplicate the epilogue since mesa/st has
188 * messed with our I/O quite a bit already) */
189
190 NIR_PASS_V(nir, nir_lower_vars_to_ssa);
191
192 if (ctx->stage == MESA_SHADER_VERTEX) {
193 NIR_PASS_V(nir, nir_lower_viewport_transform);
194 NIR_PASS_V(nir, nir_lower_point_size, 1.0, 1024.0);
195 }
196
197 NIR_PASS_V(nir, nir_split_var_copies);
198 NIR_PASS_V(nir, nir_lower_global_vars_to_local);
199 NIR_PASS_V(nir, nir_lower_var_copies);
200 NIR_PASS_V(nir, nir_lower_vars_to_ssa);
201 NIR_PASS_V(nir, nir_lower_io, nir_var_all, glsl_type_size, 0);
202 NIR_PASS_V(nir, nir_lower_ssbo);
203
204 /* We have to lower ALU to scalar ourselves since viewport
205 * transformations produce vector ops */
206 NIR_PASS_V(nir, nir_lower_alu_to_scalar, NULL, NULL);
207
208 bi_optimize_nir(nir);
209 nir_print_shader(nir, stdout);
210
211 nir_foreach_function(func, nir) {
212 if (!func->impl)
213 continue;
214
215 emit_cf_list(ctx, &func->impl->body);
216 break; /* TODO: Multi-function shaders */
217 }
218
219 bi_print_shader(ctx, stdout);
220
221 ralloc_free(ctx);
222 }