pco: NIR translation and PCO IR pass boilerplate

Signed-off-by: Simon Perretta <simon.perretta@imgtec.com>
Acked-by: Frank Binns <frank.binns@imgtec.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/32258>
This commit is contained in:
Simon Perretta
2024-05-13 17:38:21 +01:00
committed by Marge Bot
parent f179e5a220
commit 3c51c6ac17
8 changed files with 427 additions and 7 deletions
+2
View File
@@ -199,6 +199,7 @@ MacroBlockEnd: ''
ForEachMacros: [
'foreach_instr',
'foreach_instr_safe',
'foreach_list_typed',
'hash_table_foreach',
'LIST_FOR_EACH_ENTRY',
'LIST_FOR_EACH_ENTRY_FROM',
@@ -220,6 +221,7 @@ ForEachMacros: [
'nir_foreach_block_safe',
'nir_foreach_block_unstructured',
'nir_foreach_function',
'nir_foreach_function_with_impl',
'nir_foreach_instr',
'nir_foreach_instr_safe',
'nir_foreach_shader_in_variable',
+1
View File
@@ -7,6 +7,7 @@ libpowervr_compiler_files = files(
'pco.c',
'pco_binary.c',
'pco_debug.c',
'pco_end.c',
'pco_ir.c',
'pco_nir.c',
'pco_trans_nir.c',
+138
View File
@@ -12,9 +12,13 @@
#include "pco.h"
#include "pco_internal.h"
#include "util/list.h"
#include "util/macros.h"
#include "util/ralloc.h"
#include <assert.h>
#include <stdbool.h>
/**
* \brief Allocates and sets up a PCO compiler context.
*
@@ -65,6 +69,140 @@ const nir_shader_compiler_options *pco_nir_options(pco_ctx *ctx)
return &ctx->nir_options;
}
/**
* \brief Allocates and sets up a PCO shader from a NIR shader.
*
* \param[in] ctx PCO compiler context.
* \param[in] nir The NIR shader.
* \return The PCO shader, or NULL on failure.
*/
pco_shader *pco_shader_create(pco_ctx *ctx, nir_shader *nir, void *mem_ctx)
{
pco_shader *shader = rzalloc_size(mem_ctx, sizeof(*shader));
shader->ctx = ctx;
shader->nir = nir;
shader->stage = nir->info.stage;
shader->name = ralloc_strdup(shader, nir->info.name);
shader->is_internal = nir->info.internal;
shader->is_grouped = false;
list_inithead(&shader->funcs);
return shader;
}
/**
* \brief Sets up a PCO cf node.
*
* \param[in,out] cf_node PCO cf node.
* \param[in] type CF node type.
*/
static inline void init_cf_node(pco_cf_node *cf_node,
enum pco_cf_node_type type)
{
cf_node->type = type;
cf_node->parent = NULL;
}
/**
* \brief Allocates and sets up a PCO function.
*
* \param[in,out] shader PCO shader.
* \param[in] type The function type.
* \param[in] num_params The number of parameters.
* \return The PCO function, or NULL on failure.
*/
pco_func *pco_func_create(pco_shader *shader,
enum pco_func_type type,
unsigned num_params)
{
pco_func *func = rzalloc_size(shader, sizeof(*func));
pco_func *preamble = pco_preamble(shader);
/* Add the function to the shader; preamble goes first, then entrypoint.
* The rest of the functions will get appended.
*/
if (type == PCO_FUNC_TYPE_PREAMBLE) {
assert(!preamble);
list_add(&func->link, &shader->funcs);
} else if (type == PCO_FUNC_TYPE_ENTRYPOINT) {
assert(!pco_entrypoint(shader));
list_add(&func->link, !preamble ? &shader->funcs : &preamble->link);
} else {
list_addtail(&func->link, &shader->funcs);
}
init_cf_node(&func->cf_node, PCO_CF_NODE_TYPE_FUNC);
func->parent_shader = shader;
func->type = type;
func->index = shader->next_func++;
list_inithead(&func->body);
func->num_params = num_params;
if (num_params) {
func->params =
rzalloc_array_size(func, sizeof(*func->params), num_params);
}
return func;
}
/**
* \brief Allocates and sets up a PCO block.
*
* \param[in,out] func Parent function.
* \return The PCO block, or NULL on failure.
*/
pco_block *pco_block_create(pco_func *func)
{
pco_block *block = rzalloc_size(func, sizeof(*block));
init_cf_node(&block->cf_node, PCO_CF_NODE_TYPE_BLOCK);
block->parent_func = func;
list_inithead(&block->instrs);
block->index = func->next_block++;
return block;
}
/**
* \brief Allocates and sets up a PCO if construct.
*
* \param[in,out] func Parent function.
* \return The PCO if construct, or NULL on failure.
*/
pco_if *pco_if_create(pco_func *func)
{
pco_if *pif = rzalloc_size(func, sizeof(*pif));
init_cf_node(&pif->cf_node, PCO_CF_NODE_TYPE_IF);
pif->parent_func = func;
list_inithead(&pif->then_body);
list_inithead(&pif->else_body);
pif->index = func->next_if++;
return pif;
}
/**
* \brief Allocates and sets up a PCO loop.
*
* \param[in,out] func Parent function.
* \return The PCO loop, or NULL on failure.
*/
pco_loop *pco_loop_create(pco_func *func)
{
pco_loop *loop = rzalloc_size(func, sizeof(*loop));
init_cf_node(&loop->cf_node, PCO_CF_NODE_TYPE_LOOP);
loop->parent_func = func;
list_inithead(&loop->body);
loop->index = func->next_loop++;
return loop;
}
/**
* \brief Allocates and sets up a PCO instruction.
*
+43
View File
@@ -0,0 +1,43 @@
/*
* Copyright © 2024 Imagination Technologies Ltd.
*
* SPDX-License-Identifier: MIT
*/
/**
* \file pco_end.c
*
* \brief PCO shader ending pass.
*/
#include "pco.h"
#include "pco_builder.h"
#include "pco_internal.h"
#include "util/macros.h"
#include <stdbool.h>
/**
* \brief Processes end of shader instruction(s).
*
* \param[in,out] shader PCO shader.
*/
bool pco_end(pco_shader *shader)
{
/* TODO: Support for multiple end points. */
pco_func *entry = pco_entrypoint(shader);
pco_block *last_block = pco_last_block(entry);
pco_instr *last_instr = pco_last_instr(last_block);
pco_builder b =
pco_builder_create(entry, pco_cursor_after_block(last_block));
if (last_instr && pco_instr_has_end(last_instr)) {
pco_instr_set_end(last_instr, true);
return true;
}
pco_nop(&b, .end = true);
return true;
}
+41 -5
View File
@@ -292,7 +292,7 @@ typedef struct _pco_func {
pco_shader *parent_shader; /** Shader containing the function. */
bool is_entrypoint;
enum pco_func_type type; /** Function type. */
unsigned index; /** Function index. */
const char *name; /** Function name. */
@@ -372,6 +372,13 @@ struct pco_ref_mod_info {
};
extern const struct pco_ref_mod_info pco_ref_mod_info[_PCO_REF_MOD_COUNT];
pco_shader *pco_shader_create(pco_ctx *ctx, nir_shader *nir, void *mem_ctx);
pco_func *pco_func_create(pco_shader *shader,
enum pco_func_type type,
unsigned num_params);
pco_block *pco_block_create(pco_func *func);
pco_if *pco_if_create(pco_func *func);
pco_loop *pco_loop_create(pco_func *func);
pco_instr *pco_instr_create(pco_func *func,
enum pco_op op,
unsigned num_dests,
@@ -412,20 +419,46 @@ PCO_DEFINE_CAST(pco_cf_node_as_func,
type,
PCO_CF_NODE_TYPE_FUNC)
/**
* \brief Returns the preamble function of a PCO shader.
*
* \param[in] shader The PCO shader.
* \return The preamble function, or NULL if the shader has no preamble.
*/
static inline pco_func *pco_preamble(pco_shader *shader)
{
if (list_is_empty(&shader->funcs))
return NULL;
pco_func *func = list_first_entry(&shader->funcs, pco_func, link);
if (func->type == PCO_FUNC_TYPE_PREAMBLE)
return func;
return NULL;
}
/**
* \brief Returns the entrypoint function of a PCO shader.
*
* \param[in] shader The PCO shader.
* \return The entrypoint function, or NULL if the shader has no functions.
* \return The entrypoint function, or NULL if the shader has no entrypoint.
*/
static inline pco_func *pco_entrypoint(pco_shader *shader)
{
if (list_is_empty(&shader->funcs))
return NULL;
pco_func *func = list_first_entry(&shader->funcs, pco_func, link);
assert(func->is_entrypoint);
return func;
/* Entrypoint will either be the first or second function in the shader,
* depending on whether or not there is a preamble.
*/
pco_func *preamble = pco_preamble(shader);
pco_func *func = !preamble ? list_first_entry(&shader->funcs, pco_func, link)
: list_entry(preamble->link.next, pco_func, link);
if (func->type == PCO_FUNC_TYPE_ENTRYPOINT)
return func;
return NULL;
}
/* Motions. */
@@ -582,4 +615,7 @@ static inline pco_igrp *pco_prev_igrp(pco_igrp *igrp)
return list_entry(igrp->link.prev, pco_igrp, link);
}
/* PCO IR passes. */
bool pco_end(pco_shader *shader);
#endif /* PCO_INTERNAL_H */
+22
View File
@@ -12,9 +12,29 @@
#include "pco.h"
#include "pco_internal.h"
#include "util/u_debug.h"
#include <stdbool.h>
#include <stdio.h>
static inline bool pco_should_skip_pass(const char *pass)
{
return comma_separated_list_contains(pco_skip_passes, pass);
}
#define PCO_PASS(progress, shader, pass, ...) \
do { \
if (pco_should_skip_pass(#pass)) { \
fprintf(stdout, "Skipping pass '%s'\n", #pass); \
break; \
} \
\
if (pass(shader, ##__VA_ARGS__)) { \
UNUSED bool _; \
progress = true; \
} \
} while (0)
/**
* \brief Runs passes on a PCO shader.
*
@@ -23,5 +43,7 @@
*/
void pco_process_ir(pco_ctx *ctx, pco_shader *shader)
{
PCO_PASS(_, shader, pco_end);
puts("finishme: pco_process_ir");
}
+7
View File
@@ -20,6 +20,13 @@ REF_TYPE = enum_type('ref_type', [
'drc',
])
FUNC_TYPE = enum_type('func_type', [
'callable',
'preamble',
'entrypoint',
'phase_change',
])
# Ref mods.
RM_ONEMINUS = ref_mod('oneminus', BaseType.bool)
RM_CLAMP = ref_mod('clamp', BaseType.bool)
+173 -2
View File
@@ -10,12 +10,174 @@
* \brief NIR translation functions.
*/
#include "compiler/glsl/list.h"
#include "pco.h"
#include "pco_builder.h"
#include "pco_internal.h"
#include "util/bitset.h"
#include "util/list.h"
#include "util/macros.h"
#include "util/ralloc.h"
#include <assert.h>
#include <stdio.h>
/** Translation context. */
typedef struct _trans_ctx {
pco_ctx *pco_ctx; /** PCO compiler context. */
pco_shader *shader; /** Current shader. */
pco_func *func; /** Current function. */
pco_builder b; /** Builder. */
BITSET_WORD *float_types; /** NIR SSA float vars. */
BITSET_WORD *int_types; /** NIR SSA int vars. */
} trans_ctx;
/* Forward declarations. */
static pco_block *trans_cf_nodes(trans_ctx *tctx,
pco_cf_node *parent_cf_node,
struct list_head *cf_node_list,
struct exec_list *nir_cf_node_list);
/**
* \brief Translates a NIR block into PCO.
*
* \param[in] tctx Translation context.
* \param[in] nblock The nir block.
* \return The PCO block.
*/
static pco_block *trans_block(trans_ctx *tctx, nir_block *nblock)
{
pco_block *block = pco_block_create(tctx->func);
tctx->b = pco_builder_create(tctx->func, pco_cursor_after_block(block));
return block;
}
/**
* \brief Translates a NIR if into PCO.
*
* \param[in] tctx Translation context.
* \param[in] nif The nir if.
* \return The PCO if.
*/
static pco_if *trans_if(trans_ctx *tctx, nir_if *nif)
{
pco_if *pif = pco_if_create(tctx->func);
unreachable("finishme: trans_if");
return pif;
}
/**
* \brief Translates a NIR loop into PCO.
*
* \param[in] tctx Translation context.
* \param[in] nloop The nir loop.
* \return The PCO loop.
*/
static pco_loop *trans_loop(trans_ctx *tctx, nir_loop *nloop)
{
pco_loop *loop = pco_loop_create(tctx->func);
unreachable("finishme: trans_loop");
return loop;
}
/**
* \brief Translates a NIR function into PCO.
*
* \param[in] tctx Translation context.
* \param[in] impl The nir function impl.
* \return The PCO function.
*/
static pco_func *trans_func(trans_ctx *tctx, nir_function_impl *impl)
{
nir_function *nfunc = impl->function;
enum pco_func_type func_type = PCO_FUNC_TYPE_CALLABLE;
if (nfunc->is_preamble)
func_type = PCO_FUNC_TYPE_PREAMBLE;
else if (nfunc->is_entrypoint)
func_type = PCO_FUNC_TYPE_ENTRYPOINT;
pco_func *func = pco_func_create(tctx->shader, func_type, nfunc->num_params);
tctx->func = func;
func->name = ralloc_strdup(func, nfunc->name);
func->next_ssa = impl->ssa_alloc;
/* TODO: Function parameter support. */
assert(func->num_params == 0 && func->params == NULL);
/* Gather types. */
tctx->float_types =
rzalloc_array(NULL, BITSET_WORD, BITSET_WORDS(impl->ssa_alloc));
tctx->int_types =
rzalloc_array(NULL, BITSET_WORD, BITSET_WORDS(impl->ssa_alloc));
nir_gather_types(impl, tctx->float_types, tctx->int_types);
trans_cf_nodes(tctx, &func->cf_node, &func->body, &impl->body);
ralloc_free(tctx->float_types);
ralloc_free(tctx->int_types);
return func;
}
/**
* \brief Translates NIR control flow nodes into PCO.
*
* \param[in] tctx Translation context.
* \param[in] parent_cf_node The parent cf node.
* \param[in] cf_node_list The PCO cf node list.
* \param[in,out] nir_cf_node_list The NIR cf node list.
* \return The first block from the cf nodes.
*/
static pco_block *trans_cf_nodes(trans_ctx *tctx,
pco_cf_node *parent_cf_node,
struct list_head *cf_node_list,
struct exec_list *nir_cf_node_list)
{
pco_block *start_block = NULL;
pco_cf_node *cf_node;
foreach_list_typed (nir_cf_node, ncf_node, node, nir_cf_node_list) {
switch (ncf_node->type) {
case nir_cf_node_block: {
pco_block *block = trans_block(tctx, nir_cf_node_as_block(ncf_node));
cf_node = &block->cf_node;
if (!start_block)
start_block = block;
break;
}
case nir_cf_node_if: {
pco_if *pif = trans_if(tctx, nir_cf_node_as_if(ncf_node));
cf_node = &pif->cf_node;
break;
}
case nir_cf_node_loop: {
pco_loop *loop = trans_loop(tctx, nir_cf_node_as_loop(ncf_node));
cf_node = &loop->cf_node;
break;
}
default:
unreachable();
}
cf_node->parent = parent_cf_node;
list_addtail(&cf_node->link, cf_node_list);
}
return start_block;
}
/**
* \brief Translates a NIR shader into a PCO shader.
*
@@ -26,6 +188,15 @@
*/
pco_shader *pco_trans_nir(pco_ctx *ctx, nir_shader *nir, void *mem_ctx)
{
puts("finishme: pco_trans_nir");
return ralloc_context(mem_ctx);
pco_shader *shader = pco_shader_create(ctx, nir, mem_ctx);
trans_ctx tctx = {
.pco_ctx = ctx,
.shader = shader,
};
nir_foreach_function_with_impl (func, impl, nir) {
trans_func(&tctx, impl);
}
return shader;
}