unreachable("not reached");
}
- brw_compact_instructions(&c.func, 0, 0, NULL);
+ brw_compact_instructions(&c.func, 0, NULL);
*prog_data = c.prog_data;
/* brw_eu_compact.c */
void brw_init_compaction_tables(const struct gen_device_info *devinfo);
void brw_compact_instructions(struct brw_codegen *p, int start_offset,
- int num_annotations, struct annotation *annotation);
+ struct disasm_info *disasm);
void brw_uncompact_instruction(const struct gen_device_info *devinfo,
brw_inst *dst, brw_compact_inst *src);
bool brw_try_compact_instruction(const struct gen_device_info *devinfo,
/* brw_eu_validate.c */
bool brw_validate_instructions(const struct gen_device_info *devinfo,
const void *assembly, int start_offset, int end_offset,
- struct annotation_info *annotation);
+ struct disasm_info *disasm);
static inline int
next_offset(const struct gen_device_info *devinfo, void *store, int offset)
void
brw_compact_instructions(struct brw_codegen *p, int start_offset,
- int num_annotations, struct annotation *annotation)
+ struct disasm_info *disasm)
{
if (unlikely(INTEL_DEBUG & DEBUG_NO_COMPACTION))
return;
/* For an instruction at byte offset 8*i after compaction, this was its IP
* (in 16-byte units) before compaction.
*/
- int old_ip[(p->next_insn_offset - start_offset) / sizeof(brw_compact_inst)];
+ int old_ip[(p->next_insn_offset - start_offset) / sizeof(brw_compact_inst) + 1];
if (devinfo->gen == 4 && !devinfo->is_g4x)
return;
}
}
+ /* Add an entry for the ending offset of the program. This greatly
+ * simplifies the linked list walk at the end of the function.
+ */
+ old_ip[offset / sizeof(brw_compact_inst)] =
+ (p->next_insn_offset - start_offset) / sizeof(brw_inst);
+
/* Fix up control flow offsets. */
p->next_insn_offset = start_offset + offset;
for (offset = 0; offset < p->next_insn_offset - start_offset;
}
p->nr_insn = p->next_insn_offset / sizeof(brw_inst);
- /* Update the instruction offsets for each annotation. */
- if (annotation) {
- for (int offset = 0, i = 0; i < num_annotations; i++) {
+ /* Update the instruction offsets for each group. */
+ if (disasm) {
+ int offset = 0;
+
+ foreach_list_typed(struct inst_group, group, link, &disasm->group_list) {
while (start_offset + old_ip[offset / sizeof(brw_compact_inst)] *
- sizeof(brw_inst) != annotation[i].offset) {
+ sizeof(brw_inst) != group->offset) {
assert(start_offset + old_ip[offset / sizeof(brw_compact_inst)] *
- sizeof(brw_inst) < annotation[i].offset);
+ sizeof(brw_inst) < group->offset);
offset = next_offset(devinfo, store, offset);
}
- annotation[i].offset = start_offset + offset;
+ group->offset = start_offset + offset;
offset = next_offset(devinfo, store, offset);
}
-
- annotation[num_annotations].offset = p->next_insn_offset;
}
}
bool
brw_validate_instructions(const struct gen_device_info *devinfo,
const void *assembly, int start_offset, int end_offset,
- struct annotation_info *annotation)
+ struct disasm_info *disasm)
{
bool valid = true;
CHECK(special_requirements_for_handling_double_precision_data_types);
}
- if (error_msg.str && annotation) {
- annotation_insert_error(annotation, src_offset, error_msg.str);
+ if (error_msg.str && disasm) {
+ disasm_insert_error(disasm, src_offset, error_msg.str);
}
valid = valid && error_msg.len == 0;
free(error_msg.str);
int spill_count = 0, fill_count = 0;
int loop_count = 0;
- struct annotation_info annotation;
- memset(&annotation, 0, sizeof(annotation));
+ struct disasm_info *disasm_info = disasm_initialize(devinfo, cfg);
foreach_block_and_inst (block, fs_inst, inst, cfg) {
struct brw_reg src[3], dst;
}
if (unlikely(debug_flag))
- annotate(p->devinfo, &annotation, cfg, inst, p->next_insn_offset);
+ disasm_annotate(disasm_info, inst, p->next_insn_offset);
/* If the instruction writes to more than one register, it needs to be
* explicitly marked as compressed on Gen <= 5. On Gen >= 6 the
*/
if (!patch_discard_jumps_to_fb_writes()) {
if (unlikely(debug_flag)) {
- annotation.ann_count--;
+ disasm_info->use_tail = true;
}
}
break;
}
brw_set_uip_jip(p, start_offset);
- annotation_finalize(&annotation, p->next_insn_offset);
+
+ /* end of program sentinel */
+ disasm_new_inst_group(disasm_info, p->next_insn_offset);
#ifndef NDEBUG
bool validated =
brw_validate_instructions(devinfo, p->store,
start_offset,
p->next_insn_offset,
- &annotation);
+ disasm_info);
int before_size = p->next_insn_offset - start_offset;
- brw_compact_instructions(p, start_offset, annotation.ann_count,
- annotation.ann);
+ brw_compact_instructions(p, start_offset, disasm_info);
int after_size = p->next_insn_offset - start_offset;
if (unlikely(debug_flag)) {
spill_count, fill_count, promoted_constants, before_size, after_size,
100.0f * (before_size - after_size) / before_size);
- dump_assembly(p->store, annotation.ann_count, annotation.ann,
- p->devinfo);
- ralloc_free(annotation.mem_ctx);
+ dump_assembly(p->store, disasm_info);
+ ralloc_free(disasm_info);
}
assert(validated);
const char *stage_abbrev = _mesa_shader_stage_to_abbrev(nir->info.stage);
bool debug_flag = INTEL_DEBUG &
intel_debug_flag_for_shader_stage(nir->info.stage);
- struct annotation_info annotation;
- memset(&annotation, 0, sizeof(annotation));
+ struct disasm_info *disasm_info = disasm_initialize(devinfo, cfg);
int spill_count = 0, fill_count = 0;
int loop_count = 0;
struct brw_reg src[3], dst;
if (unlikely(debug_flag))
- annotate(p->devinfo, &annotation, cfg, inst, p->next_insn_offset);
+ disasm_annotate(disasm_info, inst, p->next_insn_offset);
for (unsigned int i = 0; i < 3; i++) {
src[i] = inst->src[i].as_brw_reg();
}
brw_set_uip_jip(p, 0);
- annotation_finalize(&annotation, p->next_insn_offset);
+
+ /* end of program sentinel */
+ disasm_new_inst_group(disasm_info, p->next_insn_offset);
#ifndef NDEBUG
bool validated =
#endif
brw_validate_instructions(devinfo, p->store,
0, p->next_insn_offset,
- &annotation);
+ disasm_info);
int before_size = p->next_insn_offset;
- brw_compact_instructions(p, 0, annotation.ann_count, annotation.ann);
+ brw_compact_instructions(p, 0, disasm_info);
int after_size = p->next_insn_offset;
if (unlikely(debug_flag)) {
spill_count, fill_count, before_size, after_size,
100.0f * (before_size - after_size) / before_size);
- dump_assembly(p->store, annotation.ann_count, annotation.ann,
- p->devinfo);
- ralloc_free(annotation.mem_ctx);
+ dump_assembly(p->store, disasm_info);
+ ralloc_free(disasm_info);
}
assert(validated);
__attribute__((weak)) void nir_print_instr(const nir_instr *instr, FILE *fp) {}
void
-dump_assembly(void *assembly, int num_annotations, struct annotation *annotation,
- const struct gen_device_info *devinfo)
+dump_assembly(void *assembly, struct disasm_info *disasm)
{
+ const struct gen_device_info *devinfo = disasm->devinfo;
const char *last_annotation_string = NULL;
const void *last_annotation_ir = NULL;
- for (int i = 0; i < num_annotations; i++) {
- int start_offset = annotation[i].offset;
- int end_offset = annotation[i + 1].offset;
+ foreach_list_typed(struct inst_group, group, link, &disasm->group_list) {
+ struct exec_node *next_node = exec_node_get_next(&group->link);
+ if (exec_node_is_tail_sentinel(next_node))
+ break;
- if (annotation[i].block_start) {
- fprintf(stderr, " START B%d", annotation[i].block_start->num);
+ struct inst_group *next =
+ exec_node_data(struct inst_group, next_node, link);
+
+ int start_offset = group->offset;
+ int end_offset = next->offset;
+
+ if (group->block_start) {
+ fprintf(stderr, " START B%d", group->block_start->num);
foreach_list_typed(struct bblock_link, predecessor_link, link,
- &annotation[i].block_start->parents) {
+ &group->block_start->parents) {
struct bblock_t *predecessor_block = predecessor_link->block;
fprintf(stderr, " <-B%d", predecessor_block->num);
}
- fprintf(stderr, " (%u cycles)\n", annotation[i].block_start->cycle_count);
+ fprintf(stderr, " (%u cycles)\n", group->block_start->cycle_count);
}
- if (last_annotation_ir != annotation[i].ir) {
- last_annotation_ir = annotation[i].ir;
+ if (last_annotation_ir != group->ir) {
+ last_annotation_ir = group->ir;
if (last_annotation_ir) {
fprintf(stderr, " ");
- nir_print_instr(annotation[i].ir, stderr);
+ nir_print_instr(group->ir, stderr);
fprintf(stderr, "\n");
}
}
- if (last_annotation_string != annotation[i].annotation) {
- last_annotation_string = annotation[i].annotation;
+ if (last_annotation_string != group->annotation) {
+ last_annotation_string = group->annotation;
if (last_annotation_string)
fprintf(stderr, " %s\n", last_annotation_string);
}
brw_disassemble(devinfo, assembly, start_offset, end_offset, stderr);
- if (annotation[i].error) {
- fputs(annotation[i].error, stderr);
+ if (group->error) {
+ fputs(group->error, stderr);
}
- if (annotation[i].block_end) {
- fprintf(stderr, " END B%d", annotation[i].block_end->num);
+ if (group->block_end) {
+ fprintf(stderr, " END B%d", group->block_end->num);
foreach_list_typed(struct bblock_link, successor_link, link,
- &annotation[i].block_end->children) {
+ &group->block_end->children) {
struct bblock_t *successor_block = successor_link->block;
fprintf(stderr, " ->B%d", successor_block->num);
}
fprintf(stderr, "\n");
}
-static bool
-annotation_array_ensure_space(struct annotation_info *annotation)
+struct disasm_info *
+disasm_initialize(const struct gen_device_info *devinfo,
+ const struct cfg_t *cfg)
{
- if (annotation->ann_size <= annotation->ann_count) {
- int old_size = annotation->ann_size;
- annotation->ann_size = MAX2(1024, annotation->ann_size * 2);
- annotation->ann = reralloc(annotation->mem_ctx, annotation->ann,
- struct annotation, annotation->ann_size);
- if (!annotation->ann)
- return false;
-
- memset(annotation->ann + old_size, 0,
- (annotation->ann_size - old_size) * sizeof(struct annotation));
- }
-
- return true;
+ struct disasm_info *disasm = ralloc(NULL, struct disasm_info);
+ exec_list_make_empty(&disasm->group_list);
+ disasm->devinfo = devinfo;
+ disasm->cfg = cfg;
+ disasm->cur_block = 0;
+ disasm->use_tail = false;
+ return disasm;
}
-void annotate(const struct gen_device_info *devinfo,
- struct annotation_info *annotation, const struct cfg_t *cfg,
- struct backend_instruction *inst, unsigned offset)
+struct inst_group *
+disasm_new_inst_group(struct disasm_info *disasm, unsigned next_inst_offset)
{
- if (annotation->mem_ctx == NULL)
- annotation->mem_ctx = ralloc_context(NULL);
+ struct inst_group *tail = rzalloc(disasm, struct inst_group);
+ tail->offset = next_inst_offset;
+ exec_list_push_tail(&disasm->group_list, &tail->link);
+ return tail;
+}
- if (!annotation_array_ensure_space(annotation))
- return;
+void
+disasm_annotate(struct disasm_info *disasm,
+ struct backend_instruction *inst, unsigned offset)
+{
+ const struct gen_device_info *devinfo = disasm->devinfo;
+ const struct cfg_t *cfg = disasm->cfg;
+
+ struct inst_group *group;
+ if (!disasm->use_tail) {
+ group = disasm_new_inst_group(disasm, offset);
+ disasm->use_tail = false;
+ } else {
+ group = exec_node_data(struct inst_group,
+ exec_list_get_tail_raw(&disasm->group_list), link);
+ }
- struct annotation *ann = &annotation->ann[annotation->ann_count++];
- ann->offset = offset;
if ((INTEL_DEBUG & DEBUG_ANNOTATION) != 0) {
- ann->ir = inst->ir;
- ann->annotation = inst->annotation;
+ group->ir = inst->ir;
+ group->annotation = inst->annotation;
}
- if (bblock_start(cfg->blocks[annotation->cur_block]) == inst) {
- ann->block_start = cfg->blocks[annotation->cur_block];
+ if (bblock_start(cfg->blocks[disasm->cur_block]) == inst) {
+ group->block_start = cfg->blocks[disasm->cur_block];
}
/* There is no hardware DO instruction on Gen6+, so since DO always
* a corresponding hardware instruction to disassemble.
*/
if (devinfo->gen >= 6 && inst->opcode == BRW_OPCODE_DO) {
- annotation->ann_count--;
+ disasm->use_tail = true;
}
- if (bblock_end(cfg->blocks[annotation->cur_block]) == inst) {
- ann->block_end = cfg->blocks[annotation->cur_block];
- annotation->cur_block++;
- }
-}
-
-void
-annotation_finalize(struct annotation_info *annotation,
- unsigned next_inst_offset)
-{
- if (!annotation->ann_count)
- return;
-
- if (annotation->ann_count == annotation->ann_size) {
- annotation->ann = reralloc(annotation->mem_ctx, annotation->ann,
- struct annotation, annotation->ann_size + 1);
+ if (bblock_end(cfg->blocks[disasm->cur_block]) == inst) {
+ group->block_end = cfg->blocks[disasm->cur_block];
+ disasm->cur_block++;
}
- annotation->ann[annotation->ann_count].offset = next_inst_offset;
}
void
-annotation_insert_error(struct annotation_info *annotation, unsigned offset,
- const char *error)
+disasm_insert_error(struct disasm_info *disasm, unsigned offset,
+ const char *error)
{
- if (!annotation->ann_count)
- return;
-
- /* We may have to split an annotation, so ensure we have enough space
- * allocated for that case up front.
- */
- if (!annotation_array_ensure_space(annotation))
- return;
-
- assume(annotation->ann_count > 0);
+ foreach_list_typed(struct inst_group, cur, link, &disasm->group_list) {
+ struct exec_node *next_node = exec_node_get_next(&cur->link);
+ if (exec_node_is_tail_sentinel(next_node))
+ break;
- for (int i = 0; i < annotation->ann_count; i++) {
- struct annotation *cur = &annotation->ann[i];
- struct annotation *next = &annotation->ann[i + 1];
+ struct inst_group *next =
+ exec_node_data(struct inst_group, next_node, link);
if (next->offset <= offset)
continue;
if (offset + sizeof(brw_inst) != next->offset) {
- memmove(next, cur,
- (annotation->ann_count - i + 2) * sizeof(struct annotation));
+ struct inst_group *new = ralloc(disasm, struct inst_group);
+ memcpy(new, cur, sizeof(struct inst_group));
+
cur->error = NULL;
cur->error_length = 0;
cur->block_end = NULL;
- next->offset = offset + sizeof(brw_inst);
- next->block_start = NULL;
- annotation->ann_count++;
+
+ new->offset = offset + sizeof(brw_inst);
+ new->block_start = NULL;
+
+ exec_node_insert_after(&cur->link, &new->link);
}
if (cur->error)
ralloc_strcat(&cur->error, error);
else
- cur->error = ralloc_strdup(annotation->mem_ctx, error);
+ cur->error = ralloc_strdup(disasm, error);
return;
}
}
#ifndef _INTEL_ASM_ANNOTATION_H
#define _INTEL_ASM_ANNOTATION_H
+#include "brw_cfg.h"
+
#ifdef __cplusplus
extern "C" {
#endif
-struct backend_instruction;
-struct cfg_t;
+struct inst_group {
+ struct exec_node link;
-struct annotation {
int offset;
size_t error_length;
const char *annotation;
};
-struct annotation_info {
- void *mem_ctx;
- struct annotation *ann;
- int ann_count;
- int ann_size;
+struct disasm_info {
+ struct exec_list group_list;
+
+ const struct gen_device_info *devinfo;
+ const struct cfg_t *cfg;
/** Block index in the cfg. */
int cur_block;
+ bool use_tail;
};
void
-dump_assembly(void *assembly, int num_annotations, struct annotation *annotation,
- const struct gen_device_info *devinfo);
+dump_assembly(void *assembly, struct disasm_info *disasm);
+
+struct disasm_info *
+disasm_initialize(const struct gen_device_info *devinfo,
+ const struct cfg_t *cfg);
+
+struct inst_group *
+disasm_new_inst_group(struct disasm_info *disasm, unsigned offset);
void
-annotate(const struct gen_device_info *devinfo,
- struct annotation_info *annotation, const struct cfg_t *cfg,
- struct backend_instruction *inst, unsigned offset);
-void
-annotation_finalize(struct annotation_info *annotation, unsigned offset);
+disasm_annotate(struct disasm_info *disasm,
+ struct backend_instruction *inst, unsigned offset);
void
-annotation_insert_error(struct annotation_info *annotation, unsigned offset,
- const char *error);
+disasm_insert_error(struct disasm_info *disasm, unsigned offset,
+ const char *error);
#ifdef __cplusplus
} /* extern "C" */
validate(struct brw_codegen *p)
{
const bool print = getenv("TEST_DEBUG");
- struct annotation_info annotation;
- memset(&annotation, 0, sizeof(annotation));
+ struct disasm_info disasm = disasm_initialize(p->devinfo, NULL);
if (print) {
- annotation.mem_ctx = ralloc_context(NULL);
- annotation.ann_count = 1;
- annotation.ann_size = 2;
- annotation.ann = rzalloc_array(annotation.mem_ctx, struct annotation,
- annotation.ann_size);
- annotation.ann[annotation.ann_count].offset = p->next_insn_offset;
+ disasm_new_inst_group(&disasm, 0);
+ disasm_new_inst_group(&disasm, p->next_insn_offset);
}
bool ret = brw_validate_instructions(p->devinfo, p->store, 0,
- p->next_insn_offset, &annotation);
+ p->next_insn_offset, &disasm);
if (print) {
- dump_assembly(p->store, annotation.ann_count, annotation.ann, p->devinfo);
- ralloc_free(annotation.mem_ctx);
+ dump_assembly(p->store, &disasm);
}
+ ralloc_free(disasm.mem_ctx);
return ret;
}
struct gen_device_info *devinfo = &disasm->devinfo;
int end = gen_disasm_find_end(disasm, assembly, start);
- /* Make a dummy annotation structure that brw_validate_instructions
+ /* Make a dummy disasm structure that brw_validate_instructions
* can work from.
*/
- struct annotation_info annotation_info = {
- .ann_count = 1,
- .ann_size = 2,
- };
- annotation_info.mem_ctx = ralloc_context(NULL);
- annotation_info.ann = rzalloc_array(annotation_info.mem_ctx,
- struct annotation,
- annotation_info.ann_size);
- annotation_info.ann[0].offset = start;
- annotation_info.ann[1].offset = end;
- brw_validate_instructions(devinfo, assembly, start, end, &annotation_info);
- struct annotation *annotation = annotation_info.ann;
-
- for (int i = 0; i < annotation_info.ann_count; i++) {
- int start_offset = annotation[i].offset;
- int end_offset = annotation[i + 1].offset;
+ struct disasm_info *disasm_info = disasm_initialize(devinfo, NULL);
+ disasm_new_inst_group(disasm_info, start);
+ disasm_new_inst_group(disasm_info, end);
+
+ brw_validate_instructions(devinfo, assembly, start, end, disasm_info);
+
+ foreach_list_typed(struct inst_group, group, link,
+ &disasm_info->group_list) {
+ struct exec_node *next_node = exec_node_get_next(&group->link);
+ if (exec_node_is_tail_sentinel(next_node))
+ break;
+
+ struct inst_group *next =
+ exec_node_data(struct inst_group, next_node, link);
+
+ int start_offset = group->offset;
+ int end_offset = next->offset;
brw_disassemble(devinfo, assembly, start_offset, end_offset, out);
- if (annotation[i].error) {
- fputs(annotation[i].error, out);
+ if (group->error) {
+ fputs(group->error, out);
}
}
- ralloc_free(annotation_info.mem_ctx);
+ ralloc_free(disasm_info);
}
struct gen_disasm *
}
}
- brw_compact_instructions(&c.func, 0, 0, NULL);
+ brw_compact_instructions(&c.func, 0, NULL);
/* get the program
*/