list.h is a nicer and more familiar set of list functions/macros.
#include "vc4_context.h"
#include "vc4_screen.h"
-#define container_of(ptr, type, field) \
- (type*)((char*)ptr - offsetof(type, field))
-
static struct vc4_bo *
vc4_bo_from_cache(struct vc4_screen *screen, uint32_t size, const char *name)
{
struct vc4_bo *bo = NULL;
pipe_mutex_lock(cache->lock);
- if (!is_empty_list(&cache->size_list[page_index])) {
- struct simple_node *node = first_elem(&cache->size_list[page_index]);
- bo = container_of(node, struct vc4_bo, size_list);
+ if (!list_empty(&cache->size_list[page_index])) {
+ struct vc4_bo *bo = LIST_ENTRY(struct vc4_bo,
+ cache->size_list[page_index].next,
+ size_list);
/* Check that the BO has gone idle. If not, then we want to
* allocate something new instead, since we assume that the
}
pipe_reference_init(&bo->reference, 1);
- remove_from_list(&bo->time_list);
- remove_from_list(&bo->size_list);
+ list_del(&bo->time_list);
+ list_del(&bo->size_list);
bo->name = name;
}
static void
free_stale_bos(struct vc4_screen *screen, time_t time)
{
- while (!is_empty_list(&screen->bo_cache.time_list)) {
- struct simple_node *node =
- first_elem(&screen->bo_cache.time_list);
- struct vc4_bo *bo = container_of(node, struct vc4_bo, time_list);
+ struct vc4_bo_cache *cache = &screen->bo_cache;
+ list_for_each_entry_safe(struct vc4_bo, bo, &cache->time_list,
+ time_list) {
/* If it's more than a second old, free it. */
if (time - bo->free_time > 2) {
- remove_from_list(&bo->time_list);
- remove_from_list(&bo->size_list);
+ list_del(&bo->time_list);
+ list_del(&bo->size_list);
vc4_bo_free(bo);
} else {
break;
}
if (cache->size_list_size <= page_index) {
- struct simple_node *new_list =
- ralloc_array(screen, struct simple_node, page_index + 1);
+ struct list_head *new_list =
+ ralloc_array(screen, struct list_head, page_index + 1);
/* Move old list contents over (since the array has moved, and
- * therefore the pointers to the list heads have to change.
+ * therefore the pointers to the list heads have to change).
*/
for (int i = 0; i < cache->size_list_size; i++) {
- struct simple_node *old_head = &cache->size_list[i];
- if (is_empty_list(old_head))
- make_empty_list(&new_list[i]);
+ struct list_head *old_head = &cache->size_list[i];
+ if (list_empty(old_head))
+ list_inithead(&new_list[i]);
else {
new_list[i].next = old_head->next;
new_list[i].prev = old_head->prev;
}
}
for (int i = cache->size_list_size; i < page_index + 1; i++)
- make_empty_list(&new_list[i]);
+ list_inithead(&new_list[i]);
cache->size_list = new_list;
cache->size_list_size = page_index + 1;
}
bo->free_time = time;
- insert_at_tail(&cache->size_list[page_index], &bo->size_list);
- insert_at_tail(&cache->time_list, &bo->time_list);
+ list_addtail(&bo->size_list, &cache->size_list[page_index]);
+ list_addtail(&bo->time_list, &cache->time_list);
free_stale_bos(screen, time);
}
struct vc4_screen *screen = vc4_screen(pscreen);
struct vc4_bo_cache *cache = &screen->bo_cache;
- while (!is_empty_list(&cache->time_list)) {
- struct simple_node *node = first_elem(&cache->time_list);
- struct vc4_bo *bo = container_of(node, struct vc4_bo, time_list);
-
- remove_from_list(&bo->time_list);
- remove_from_list(&bo->size_list);
+ list_for_each_entry_safe(struct vc4_bo, bo, &cache->time_list,
+ time_list) {
+ list_del(&bo->time_list);
+ list_del(&bo->size_list);
vc4_bo_free(bo);
}
}
#endif
/** Entry in the linked list of buffers freed, by age. */
- struct simple_node time_list;
+ struct list_head time_list;
/** Entry in the per-page-count linked list of buffers freed (by age). */
- struct simple_node size_list;
+ struct list_head size_list;
/** Approximate second when the bo was freed. */
time_t free_time;
/**
qir_opt_algebraic(struct vc4_compile *c)
{
bool progress = false;
- struct simple_node *node;
-
- foreach(node, &c->instructions) {
- struct qinst *inst = (struct qinst *)node;
+ list_for_each_entry(struct qinst, inst, &c->instructions, link) {
switch (inst->op) {
case QOP_SEL_X_Y_ZS:
case QOP_SEL_X_Y_ZC:
qir_opt_constant_folding(struct vc4_compile *c)
{
bool progress = false;
- struct simple_node *node;
- foreach(node, &c->instructions) {
- struct qinst *inst = (struct qinst *)node;
+ list_for_each_entry(struct qinst, inst, &c->instructions, link) {
if (constant_fold(c, inst))
progress = true;
}
qir_opt_copy_propagation(struct vc4_compile *c)
{
bool progress = false;
- struct simple_node *node;
bool debug = false;
struct qreg *movs = calloc(c->num_temps, sizeof(struct qreg));
- foreach(node, &c->instructions) {
- struct qinst *inst = (struct qinst *)node;
-
+ list_for_each_entry(struct qinst, inst, &c->instructions, link) {
for (int i = 0; i < qir_get_op_nsrc(inst->op); i++) {
int index = inst->src[i].index;
if (inst->src[i].file == QFILE_TEMP &&
qir_opt_cse(struct vc4_compile *c)
{
bool progress = false;
- struct simple_node *node, *t;
uint32_t sf_count = 0, r4_count = 0;
struct hash_table *ht = _mesa_hash_table_create(NULL, NULL,
if (!ht)
return false;
- foreach_s(node, t, &c->instructions) {
- struct qinst *inst = (struct qinst *)node;
-
+ list_for_each_entry_safe(struct qinst, inst, &c->instructions, link) {
if (qir_has_side_effects(c, inst) ||
qir_has_side_effect_reads(c, inst)) {
continue;
/* Whether we're eliminating texture setup currently. */
bool dce_tex = false;
- struct simple_node *node, *t;
+ struct list_head *node, *t;
for (node = c->instructions.prev, t = node->prev;
&c->instructions != node;
node = t, t = t->prev) {
qir_opt_small_immediates(struct vc4_compile *c)
{
bool progress = false;
- struct simple_node *node;
-
- foreach(node, &c->instructions) {
- struct qinst *inst = (struct qinst *)node;
+ list_for_each_entry(struct qinst, inst, &c->instructions, link) {
/* The small immediate value sits in the raddr B field, so we
* can't have 2 small immediates in one instruction (unless
* they're the same value, but that should be optimized away
return false;
bool progress = false;
- struct simple_node *node;
struct qinst *vpm_writes[64] = { 0 };
uint32_t use_count[c->num_temps];
uint32_t vpm_write_count = 0;
memset(&use_count, 0, sizeof(use_count));
- foreach(node, &c->instructions) {
- struct qinst *inst = (struct qinst *)node;
-
+ list_for_each_entry(struct qinst, inst, &c->instructions, link) {
switch (inst->dst.file) {
case QFILE_VPM:
vpm_writes[vpm_write_count++] = inst;
* to maintain the order of the VPM writes.
*/
assert(!vpm_writes[i]->sf);
- move_to_tail(&vpm_writes[i]->link, &inst->link);
+ list_del(&inst->link);
+ list_addtail(&inst->link, &vpm_writes[i]->link);
qir_remove_instruction(c, vpm_writes[i]);
c->defs[inst->dst.index] = NULL;
shader->program_id = vc4->next_compiled_program_id++;
if (stage == QSTAGE_FRAG) {
bool input_live[c->num_input_semantics];
- struct simple_node *node;
memset(input_live, 0, sizeof(input_live));
- foreach(node, &c->instructions) {
- struct qinst *inst = (struct qinst *)node;
+ list_for_each_entry(struct qinst, inst, &c->instructions, link) {
for (int i = 0; i < qir_get_op_nsrc(inst->op); i++) {
if (inst->src[i].file == QFILE_VARY)
input_live[inst->src[i].index] = true;
*/
#include "util/u_memory.h"
-#include "util/simple_list.h"
#include "util/ralloc.h"
#include "vc4_qir.h"
void
qir_dump(struct vc4_compile *c)
{
- struct simple_node *node;
-
- foreach(node, &c->instructions) {
- struct qinst *inst = (struct qinst *)node;
+ list_for_each_entry(struct qinst, inst, &c->instructions, link) {
qir_dump_inst(c, inst);
fprintf(stderr, "\n");
}
if (inst->dst.file == QFILE_TEMP)
c->defs[inst->dst.index] = inst;
- insert_at_tail(&c->instructions, &inst->link);
+ list_addtail(&inst->link, &c->instructions);
}
bool
{
struct vc4_compile *c = rzalloc(NULL, struct vc4_compile);
- make_empty_list(&c->instructions);
+ list_inithead(&c->instructions);
c->output_position_index = -1;
c->output_clipvertex_index = -1;
if (qinst->dst.file == QFILE_TEMP)
c->defs[qinst->dst.index] = NULL;
- remove_from_list(&qinst->link);
+ list_del(&qinst->link);
free(qinst->src);
free(qinst);
}
void
qir_compile_destroy(struct vc4_compile *c)
{
- while (!is_empty_list(&c->instructions)) {
+ while (!list_empty(&c->instructions)) {
struct qinst *qinst =
- (struct qinst *)first_elem(&c->instructions);
+ (struct qinst *)c->instructions.next;
qir_remove_instruction(c, qinst);
}
qir_SF(struct vc4_compile *c, struct qreg src)
{
struct qinst *last_inst = NULL;
- if (!is_empty_list(&c->instructions))
+ if (!list_empty(&c->instructions))
last_inst = (struct qinst *)c->instructions.prev;
if (!last_inst ||
#include "util/macros.h"
#include "glsl/nir/nir.h"
-#include "util/simple_list.h"
+#include "util/list.h"
#include "util/u_math.h"
enum qfile {
};
struct queued_qpu_inst {
- struct simple_node link;
+ struct list_head link;
uint64_t inst;
};
struct qinst {
- struct simple_node link;
+ struct list_head link;
enum qop op;
struct qreg dst;
struct qreg undef;
enum qstage stage;
uint32_t num_temps;
- struct simple_node instructions;
+ struct list_head instructions;
uint32_t immediates[1024];
- struct simple_node qpu_inst_list;
+ struct list_head qpu_inst_list;
uint64_t *qpu_insts;
uint32_t qpu_inst_count;
uint32_t qpu_inst_size;
void
qir_lower_uniforms(struct vc4_compile *c)
{
- struct simple_node *node;
struct hash_table *ht =
_mesa_hash_table_create(c, index_hash, index_compare);
* than one uniform referenced, and add those uniform values to the
* ht.
*/
- foreach(node, &c->instructions) {
- struct qinst *inst = (struct qinst *)node;
+ list_for_each_entry(struct qinst, inst, &c->instructions, link) {
uint32_t nsrc = qir_get_op_nsrc(inst->op);
uint32_t count = 0;
struct qreg temp = qir_get_temp(c);
struct qreg unif = { QFILE_UNIF, max_index };
struct qinst *mov = qir_inst(QOP_MOV, temp, unif, c->undef);
- insert_at_head(&c->instructions, &mov->link);
+ list_add(&mov->link, &c->instructions);
c->defs[temp.index] = mov;
- foreach(node, &c->instructions) {
- struct qinst *inst = (struct qinst *)node;
+ list_for_each_entry(struct qinst, inst, &c->instructions, link) {
uint32_t nsrc = qir_get_op_nsrc(inst->op);
uint32_t count = 0;
{
struct queued_qpu_inst *q = rzalloc(c, struct queued_qpu_inst);
q->inst = inst;
- insert_at_tail(&c->qpu_inst_list, &q->link);
+ list_addtail(&q->link, &c->qpu_inst_list);
}
static uint64_t *
last_inst(struct vc4_compile *c)
{
struct queued_qpu_inst *q =
- (struct queued_qpu_inst *)last_elem(&c->qpu_inst_list);
+ (struct queued_qpu_inst *)c->qpu_inst_list.prev;
return &q->inst;
}
QPU_UNPACK_16B_TO_F32,
};
- make_empty_list(&c->qpu_inst_list);
+ list_inithead(&c->qpu_inst_list);
switch (c->stage) {
case QSTAGE_VERT:
break;
}
- struct simple_node *node;
- foreach(node, &c->instructions) {
- struct qinst *qinst = (struct qinst *)node;
-
+ list_for_each_entry(struct qinst, qinst, &c->instructions, link) {
#if 0
fprintf(stderr, "translating qinst to qpu: ");
qir_dump_inst(qinst);
struct schedule_node_child;
struct schedule_node {
- struct simple_node link;
+ struct list_head link;
struct queued_qpu_inst *inst;
struct schedule_node_child *children;
uint32_t child_count;
}
static void
-calculate_forward_deps(struct vc4_compile *c, struct simple_node *schedule_list)
+calculate_forward_deps(struct vc4_compile *c, struct list_head *schedule_list)
{
- struct simple_node *node;
struct schedule_state state;
memset(&state, 0, sizeof(state));
state.dir = F;
- foreach(node, schedule_list)
- calculate_deps(&state, (struct schedule_node *)node);
+ list_for_each_entry(struct schedule_node, node, schedule_list, link)
+ calculate_deps(&state, node);
}
static void
-calculate_reverse_deps(struct vc4_compile *c, struct simple_node *schedule_list)
+calculate_reverse_deps(struct vc4_compile *c, struct list_head *schedule_list)
{
- struct simple_node *node;
+ struct list_head *node;
struct schedule_state state;
memset(&state, 0, sizeof(state));
static struct schedule_node *
choose_instruction_to_schedule(struct choose_scoreboard *scoreboard,
- struct simple_node *schedule_list,
+ struct list_head *schedule_list,
struct schedule_node *prev_inst)
{
struct schedule_node *chosen = NULL;
- struct simple_node *node;
int chosen_prio = 0;
- foreach(node, schedule_list) {
- struct schedule_node *n = (struct schedule_node *)node;
+ list_for_each_entry(struct schedule_node, n, schedule_list, link) {
uint64_t inst = n->inst->inst;
/* "An instruction must not read from a location in physical
}
static void
-dump_state(struct simple_node *schedule_list)
+dump_state(struct list_head *schedule_list)
{
- struct simple_node *node;
-
uint32_t i = 0;
- foreach(node, schedule_list) {
- struct schedule_node *n = (struct schedule_node *)node;
+ list_for_each_entry(struct schedule_node, n, schedule_list, link) {
fprintf(stderr, "%3d: ", i++);
vc4_qpu_disasm(&n->inst->inst, 1);
fprintf(stderr, "\n");
}
static void
-mark_instruction_scheduled(struct simple_node *schedule_list,
+mark_instruction_scheduled(struct list_head *schedule_list,
struct schedule_node *node,
bool war_only)
{
child->parent_count--;
if (child->parent_count == 0)
- insert_at_head(schedule_list, &child->link);
+ list_add(&child->link, schedule_list);
node->children[i].node = NULL;
}
}
static void
-schedule_instructions(struct vc4_compile *c, struct simple_node *schedule_list)
+schedule_instructions(struct vc4_compile *c, struct list_head *schedule_list)
{
- struct simple_node *node, *t;
struct choose_scoreboard scoreboard;
/* We reorder the uniforms as we schedule instructions, so save the
}
/* Remove non-DAG heads from the list. */
- foreach_s(node, t, schedule_list) {
- struct schedule_node *n = (struct schedule_node *)node;
-
+ list_for_each_entry_safe(struct schedule_node, n, schedule_list, link) {
if (n->parent_count != 0)
- remove_from_list(&n->link);
+ list_del(&n->link);
}
- while (!is_empty_list(schedule_list)) {
+ while (!list_empty(schedule_list)) {
struct schedule_node *chosen =
choose_instruction_to_schedule(&scoreboard,
schedule_list,
* find an instruction to pair with it.
*/
if (chosen) {
- remove_from_list(&chosen->link);
+ list_del(&chosen->link);
mark_instruction_scheduled(schedule_list, chosen, true);
if (chosen->uniform != -1) {
c->uniform_data[next_uniform] =
schedule_list,
chosen);
if (merge) {
- remove_from_list(&merge->link);
+ list_del(&merge->link);
inst = qpu_merge_inst(inst, merge->inst->inst);
assert(inst != 0);
if (merge->uniform != -1) {
qpu_schedule_instructions(struct vc4_compile *c)
{
void *mem_ctx = ralloc_context(NULL);
- struct simple_node schedule_list;
- struct simple_node *node;
+ struct list_head schedule_list;
- make_empty_list(&schedule_list);
+ list_inithead(&schedule_list);
if (debug) {
fprintf(stderr, "Pre-schedule instructions\n");
- foreach(node, &c->qpu_inst_list) {
- struct queued_qpu_inst *q =
- (struct queued_qpu_inst *)node;
+ list_for_each_entry(struct queued_qpu_inst, q,
+ &c->qpu_inst_list, link) {
vc4_qpu_disasm(&q->inst, 1);
fprintf(stderr, "\n");
}
/* Wrap each instruction in a scheduler structure. */
uint32_t next_uniform = 0;
- while (!is_empty_list(&c->qpu_inst_list)) {
+ while (!list_empty(&c->qpu_inst_list)) {
struct queued_qpu_inst *inst =
(struct queued_qpu_inst *)c->qpu_inst_list.next;
struct schedule_node *n = rzalloc(mem_ctx, struct schedule_node);
} else {
n->uniform = -1;
}
- remove_from_list(&inst->link);
- insert_at_tail(&schedule_list, &n->link);
+ list_del(&inst->link);
+ list_addtail(&n->link, &schedule_list);
}
assert(next_uniform == c->num_uniforms);
calculate_forward_deps(c, &schedule_list);
calculate_reverse_deps(c, &schedule_list);
- foreach(node, &schedule_list) {
- struct schedule_node *n = (struct schedule_node *)node;
+ list_for_each_entry(struct schedule_node, n, &schedule_list, link) {
compute_delay(n);
}
struct qpu_reg *
vc4_register_allocate(struct vc4_context *vc4, struct vc4_compile *c)
{
- struct simple_node *node;
struct node_to_temp_map map[c->num_temps];
uint32_t temp_to_node[c->num_temps];
uint32_t def[c->num_temps];
/* Compute the live ranges so we can figure out interference.
*/
uint32_t ip = 0;
- foreach(node, &c->instructions) {
- struct qinst *inst = (struct qinst *)node;
-
+ list_for_each_entry(struct qinst, inst, &c->instructions, link) {
if (inst->dst.file == QFILE_TEMP) {
def[inst->dst.index] = ip;
use[inst->dst.index] = ip;
}
/* Figure out our register classes and preallocated registers*/
- foreach(node, &c->instructions) {
- struct qinst *inst = (struct qinst *)node;
-
+ list_for_each_entry(struct qinst, inst, &c->instructions, link) {
switch (inst->op) {
case QOP_FRAG_Z:
ra_set_node_reg(g, temp_to_node[inst->dst.index],
uint32_t *uniform_index = NULL;
uint32_t uniform_index_size = 0;
uint32_t next_uniform = 0;
- struct simple_node *node;
- foreach(node, &c->instructions) {
- struct qinst *inst = (struct qinst *)node;
+ list_for_each_entry(struct qinst, inst, &c->instructions, link) {
for (int i = 0; i < qir_get_op_nsrc(inst->op); i++) {
if (inst->src[i].file != QFILE_UNIF)
continue;
pscreen->is_format_supported = vc4_screen_is_format_supported;
screen->fd = fd;
- make_empty_list(&screen->bo_cache.time_list);
+ list_inithead(&screen->bo_cache.time_list);
vc4_fence_init(screen);
struct vc4_bo_cache {
/** List of struct vc4_bo freed, by age. */
- struct simple_node time_list;
+ struct list_head time_list;
/** List of struct vc4_bo freed, per size, by age. */
- struct simple_node *size_list;
+ struct list_head *size_list;
uint32_t size_list_size;
pipe_mutex lock;