i965: Rewrite disassembly annotation code
The old code used an array to store each "instruction group" (the new, better name than the old overloaded "annotation"), and required a memmove() to shift elements over in the array when we needed to split a group so that we could add an error message. This was confusing and difficult to get right, not the least of which was because the array has a tail sentinel not included in .ann_count. Instead use a linked list, a data structure made for efficient insertion. Acked-by: Samuel Iglesias Gonsálvez <siglesias@igalia.com> Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
This commit is contained in:
parent
f80e97346b
commit
4f82b17287
|
@ -79,7 +79,7 @@ brw_compile_clip(const struct brw_compiler *compiler,
|
||||||
unreachable("not reached");
|
unreachable("not reached");
|
||||||
}
|
}
|
||||||
|
|
||||||
brw_compact_instructions(&c.func, 0, 0, NULL);
|
brw_compact_instructions(&c.func, 0, NULL);
|
||||||
|
|
||||||
*prog_data = c.prog_data;
|
*prog_data = c.prog_data;
|
||||||
|
|
||||||
|
|
|
@ -548,7 +548,7 @@ enum brw_conditional_mod brw_swap_cmod(uint32_t cmod);
|
||||||
/* brw_eu_compact.c */
|
/* brw_eu_compact.c */
|
||||||
void brw_init_compaction_tables(const struct gen_device_info *devinfo);
|
void brw_init_compaction_tables(const struct gen_device_info *devinfo);
|
||||||
void brw_compact_instructions(struct brw_codegen *p, int start_offset,
|
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,
|
void brw_uncompact_instruction(const struct gen_device_info *devinfo,
|
||||||
brw_inst *dst, brw_compact_inst *src);
|
brw_inst *dst, brw_compact_inst *src);
|
||||||
bool brw_try_compact_instruction(const struct gen_device_info *devinfo,
|
bool brw_try_compact_instruction(const struct gen_device_info *devinfo,
|
||||||
|
@ -560,7 +560,7 @@ void brw_debug_compact_uncompact(const struct gen_device_info *devinfo,
|
||||||
/* brw_eu_validate.c */
|
/* brw_eu_validate.c */
|
||||||
bool brw_validate_instructions(const struct gen_device_info *devinfo,
|
bool brw_validate_instructions(const struct gen_device_info *devinfo,
|
||||||
const void *assembly, int start_offset, int end_offset,
|
const void *assembly, int start_offset, int end_offset,
|
||||||
struct annotation_info *annotation);
|
struct disasm_info *disasm);
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
next_offset(const struct gen_device_info *devinfo, void *store, int offset)
|
next_offset(const struct gen_device_info *devinfo, void *store, int offset)
|
||||||
|
|
|
@ -1486,7 +1486,7 @@ brw_init_compaction_tables(const struct gen_device_info *devinfo)
|
||||||
|
|
||||||
void
|
void
|
||||||
brw_compact_instructions(struct brw_codegen *p, int start_offset,
|
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))
|
if (unlikely(INTEL_DEBUG & DEBUG_NO_COMPACTION))
|
||||||
return;
|
return;
|
||||||
|
@ -1501,7 +1501,7 @@ brw_compact_instructions(struct brw_codegen *p, int start_offset,
|
||||||
/* For an instruction at byte offset 8*i after compaction, this was its IP
|
/* For an instruction at byte offset 8*i after compaction, this was its IP
|
||||||
* (in 16-byte units) before compaction.
|
* (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)
|
if (devinfo->gen == 4 && !devinfo->is_g4x)
|
||||||
return;
|
return;
|
||||||
|
@ -1556,6 +1556,12 @@ brw_compact_instructions(struct brw_codegen *p, int start_offset,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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. */
|
/* Fix up control flow offsets. */
|
||||||
p->next_insn_offset = start_offset + offset;
|
p->next_insn_offset = start_offset + offset;
|
||||||
for (offset = 0; offset < p->next_insn_offset - start_offset;
|
for (offset = 0; offset < p->next_insn_offset - start_offset;
|
||||||
|
@ -1651,21 +1657,21 @@ brw_compact_instructions(struct brw_codegen *p, int start_offset,
|
||||||
}
|
}
|
||||||
p->nr_insn = p->next_insn_offset / sizeof(brw_inst);
|
p->nr_insn = p->next_insn_offset / sizeof(brw_inst);
|
||||||
|
|
||||||
/* Update the instruction offsets for each annotation. */
|
/* Update the instruction offsets for each group. */
|
||||||
if (annotation) {
|
if (disasm) {
|
||||||
for (int offset = 0, i = 0; i < num_annotations; i++) {
|
int offset = 0;
|
||||||
|
|
||||||
|
foreach_list_typed(struct inst_group, group, link, &disasm->group_list) {
|
||||||
while (start_offset + old_ip[offset / sizeof(brw_compact_inst)] *
|
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)] *
|
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);
|
offset = next_offset(devinfo, store, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
annotation[i].offset = start_offset + offset;
|
group->offset = start_offset + offset;
|
||||||
|
|
||||||
offset = next_offset(devinfo, store, offset);
|
offset = next_offset(devinfo, store, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
annotation[num_annotations].offset = p->next_insn_offset;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1258,7 +1258,7 @@ special_requirements_for_handling_double_precision_data_types(
|
||||||
bool
|
bool
|
||||||
brw_validate_instructions(const struct gen_device_info *devinfo,
|
brw_validate_instructions(const struct gen_device_info *devinfo,
|
||||||
const void *assembly, int start_offset, int end_offset,
|
const void *assembly, int start_offset, int end_offset,
|
||||||
struct annotation_info *annotation)
|
struct disasm_info *disasm)
|
||||||
{
|
{
|
||||||
bool valid = true;
|
bool valid = true;
|
||||||
|
|
||||||
|
@ -1286,8 +1286,8 @@ brw_validate_instructions(const struct gen_device_info *devinfo,
|
||||||
CHECK(special_requirements_for_handling_double_precision_data_types);
|
CHECK(special_requirements_for_handling_double_precision_data_types);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error_msg.str && annotation) {
|
if (error_msg.str && disasm) {
|
||||||
annotation_insert_error(annotation, src_offset, error_msg.str);
|
disasm_insert_error(disasm, src_offset, error_msg.str);
|
||||||
}
|
}
|
||||||
valid = valid && error_msg.len == 0;
|
valid = valid && error_msg.len == 0;
|
||||||
free(error_msg.str);
|
free(error_msg.str);
|
||||||
|
|
|
@ -1638,8 +1638,7 @@ fs_generator::generate_code(const cfg_t *cfg, int dispatch_width)
|
||||||
int spill_count = 0, fill_count = 0;
|
int spill_count = 0, fill_count = 0;
|
||||||
int loop_count = 0;
|
int loop_count = 0;
|
||||||
|
|
||||||
struct annotation_info annotation;
|
struct disasm_info *disasm_info = disasm_initialize(devinfo, cfg);
|
||||||
memset(&annotation, 0, sizeof(annotation));
|
|
||||||
|
|
||||||
foreach_block_and_inst (block, fs_inst, inst, cfg) {
|
foreach_block_and_inst (block, fs_inst, inst, cfg) {
|
||||||
struct brw_reg src[3], dst;
|
struct brw_reg src[3], dst;
|
||||||
|
@ -1666,7 +1665,7 @@ fs_generator::generate_code(const cfg_t *cfg, int dispatch_width)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unlikely(debug_flag))
|
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
|
/* If the instruction writes to more than one register, it needs to be
|
||||||
* explicitly marked as compressed on Gen <= 5. On Gen >= 6 the
|
* explicitly marked as compressed on Gen <= 5. On Gen >= 6 the
|
||||||
|
@ -2129,7 +2128,7 @@ fs_generator::generate_code(const cfg_t *cfg, int dispatch_width)
|
||||||
*/
|
*/
|
||||||
if (!patch_discard_jumps_to_fb_writes()) {
|
if (!patch_discard_jumps_to_fb_writes()) {
|
||||||
if (unlikely(debug_flag)) {
|
if (unlikely(debug_flag)) {
|
||||||
annotation.ann_count--;
|
disasm_info->use_tail = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -2189,7 +2188,9 @@ fs_generator::generate_code(const cfg_t *cfg, int dispatch_width)
|
||||||
}
|
}
|
||||||
|
|
||||||
brw_set_uip_jip(p, start_offset);
|
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
|
#ifndef NDEBUG
|
||||||
bool validated =
|
bool validated =
|
||||||
|
@ -2199,11 +2200,10 @@ fs_generator::generate_code(const cfg_t *cfg, int dispatch_width)
|
||||||
brw_validate_instructions(devinfo, p->store,
|
brw_validate_instructions(devinfo, p->store,
|
||||||
start_offset,
|
start_offset,
|
||||||
p->next_insn_offset,
|
p->next_insn_offset,
|
||||||
&annotation);
|
disasm_info);
|
||||||
|
|
||||||
int before_size = p->next_insn_offset - start_offset;
|
int before_size = p->next_insn_offset - start_offset;
|
||||||
brw_compact_instructions(p, start_offset, annotation.ann_count,
|
brw_compact_instructions(p, start_offset, disasm_info);
|
||||||
annotation.ann);
|
|
||||||
int after_size = p->next_insn_offset - start_offset;
|
int after_size = p->next_insn_offset - start_offset;
|
||||||
|
|
||||||
if (unlikely(debug_flag)) {
|
if (unlikely(debug_flag)) {
|
||||||
|
@ -2214,9 +2214,8 @@ fs_generator::generate_code(const cfg_t *cfg, int dispatch_width)
|
||||||
spill_count, fill_count, promoted_constants, before_size, after_size,
|
spill_count, fill_count, promoted_constants, before_size, after_size,
|
||||||
100.0f * (before_size - after_size) / before_size);
|
100.0f * (before_size - after_size) / before_size);
|
||||||
|
|
||||||
dump_assembly(p->store, annotation.ann_count, annotation.ann,
|
dump_assembly(p->store, disasm_info);
|
||||||
p->devinfo);
|
ralloc_free(disasm_info);
|
||||||
ralloc_free(annotation.mem_ctx);
|
|
||||||
}
|
}
|
||||||
assert(validated);
|
assert(validated);
|
||||||
|
|
||||||
|
|
|
@ -1500,8 +1500,7 @@ generate_code(struct brw_codegen *p,
|
||||||
const char *stage_abbrev = _mesa_shader_stage_to_abbrev(nir->info.stage);
|
const char *stage_abbrev = _mesa_shader_stage_to_abbrev(nir->info.stage);
|
||||||
bool debug_flag = INTEL_DEBUG &
|
bool debug_flag = INTEL_DEBUG &
|
||||||
intel_debug_flag_for_shader_stage(nir->info.stage);
|
intel_debug_flag_for_shader_stage(nir->info.stage);
|
||||||
struct annotation_info annotation;
|
struct disasm_info *disasm_info = disasm_initialize(devinfo, cfg);
|
||||||
memset(&annotation, 0, sizeof(annotation));
|
|
||||||
int spill_count = 0, fill_count = 0;
|
int spill_count = 0, fill_count = 0;
|
||||||
int loop_count = 0;
|
int loop_count = 0;
|
||||||
|
|
||||||
|
@ -1509,7 +1508,7 @@ generate_code(struct brw_codegen *p,
|
||||||
struct brw_reg src[3], dst;
|
struct brw_reg src[3], dst;
|
||||||
|
|
||||||
if (unlikely(debug_flag))
|
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++) {
|
for (unsigned int i = 0; i < 3; i++) {
|
||||||
src[i] = inst->src[i].as_brw_reg();
|
src[i] = inst->src[i].as_brw_reg();
|
||||||
|
@ -2175,7 +2174,9 @@ generate_code(struct brw_codegen *p,
|
||||||
}
|
}
|
||||||
|
|
||||||
brw_set_uip_jip(p, 0);
|
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
|
#ifndef NDEBUG
|
||||||
bool validated =
|
bool validated =
|
||||||
|
@ -2184,10 +2185,10 @@ generate_code(struct brw_codegen *p,
|
||||||
#endif
|
#endif
|
||||||
brw_validate_instructions(devinfo, p->store,
|
brw_validate_instructions(devinfo, p->store,
|
||||||
0, p->next_insn_offset,
|
0, p->next_insn_offset,
|
||||||
&annotation);
|
disasm_info);
|
||||||
|
|
||||||
int before_size = p->next_insn_offset;
|
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;
|
int after_size = p->next_insn_offset;
|
||||||
|
|
||||||
if (unlikely(debug_flag)) {
|
if (unlikely(debug_flag)) {
|
||||||
|
@ -2201,9 +2202,8 @@ generate_code(struct brw_codegen *p,
|
||||||
spill_count, fill_count, before_size, after_size,
|
spill_count, fill_count, before_size, after_size,
|
||||||
100.0f * (before_size - after_size) / before_size);
|
100.0f * (before_size - after_size) / before_size);
|
||||||
|
|
||||||
dump_assembly(p->store, annotation.ann_count, annotation.ann,
|
dump_assembly(p->store, disasm_info);
|
||||||
p->devinfo);
|
ralloc_free(disasm_info);
|
||||||
ralloc_free(annotation.mem_ctx);
|
|
||||||
}
|
}
|
||||||
assert(validated);
|
assert(validated);
|
||||||
|
|
||||||
|
|
|
@ -30,51 +30,58 @@
|
||||||
__attribute__((weak)) void nir_print_instr(const nir_instr *instr, FILE *fp) {}
|
__attribute__((weak)) void nir_print_instr(const nir_instr *instr, FILE *fp) {}
|
||||||
|
|
||||||
void
|
void
|
||||||
dump_assembly(void *assembly, int num_annotations, struct annotation *annotation,
|
dump_assembly(void *assembly, struct disasm_info *disasm)
|
||||||
const struct gen_device_info *devinfo)
|
|
||||||
{
|
{
|
||||||
|
const struct gen_device_info *devinfo = disasm->devinfo;
|
||||||
const char *last_annotation_string = NULL;
|
const char *last_annotation_string = NULL;
|
||||||
const void *last_annotation_ir = NULL;
|
const void *last_annotation_ir = NULL;
|
||||||
|
|
||||||
for (int i = 0; i < num_annotations; i++) {
|
foreach_list_typed(struct inst_group, group, link, &disasm->group_list) {
|
||||||
int start_offset = annotation[i].offset;
|
struct exec_node *next_node = exec_node_get_next(&group->link);
|
||||||
int end_offset = annotation[i + 1].offset;
|
if (exec_node_is_tail_sentinel(next_node))
|
||||||
|
break;
|
||||||
|
|
||||||
if (annotation[i].block_start) {
|
struct inst_group *next =
|
||||||
fprintf(stderr, " START B%d", annotation[i].block_start->num);
|
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,
|
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;
|
struct bblock_t *predecessor_block = predecessor_link->block;
|
||||||
fprintf(stderr, " <-B%d", predecessor_block->num);
|
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) {
|
if (last_annotation_ir != group->ir) {
|
||||||
last_annotation_ir = annotation[i].ir;
|
last_annotation_ir = group->ir;
|
||||||
if (last_annotation_ir) {
|
if (last_annotation_ir) {
|
||||||
fprintf(stderr, " ");
|
fprintf(stderr, " ");
|
||||||
nir_print_instr(annotation[i].ir, stderr);
|
nir_print_instr(group->ir, stderr);
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (last_annotation_string != annotation[i].annotation) {
|
if (last_annotation_string != group->annotation) {
|
||||||
last_annotation_string = annotation[i].annotation;
|
last_annotation_string = group->annotation;
|
||||||
if (last_annotation_string)
|
if (last_annotation_string)
|
||||||
fprintf(stderr, " %s\n", last_annotation_string);
|
fprintf(stderr, " %s\n", last_annotation_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
brw_disassemble(devinfo, assembly, start_offset, end_offset, stderr);
|
brw_disassemble(devinfo, assembly, start_offset, end_offset, stderr);
|
||||||
|
|
||||||
if (annotation[i].error) {
|
if (group->error) {
|
||||||
fputs(annotation[i].error, stderr);
|
fputs(group->error, stderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (annotation[i].block_end) {
|
if (group->block_end) {
|
||||||
fprintf(stderr, " END B%d", annotation[i].block_end->num);
|
fprintf(stderr, " END B%d", group->block_end->num);
|
||||||
foreach_list_typed(struct bblock_link, successor_link, link,
|
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;
|
struct bblock_t *successor_block = successor_link->block;
|
||||||
fprintf(stderr, " ->B%d", successor_block->num);
|
fprintf(stderr, " ->B%d", successor_block->num);
|
||||||
}
|
}
|
||||||
|
@ -84,43 +91,51 @@ dump_assembly(void *assembly, int num_annotations, struct annotation *annotation
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
struct disasm_info *
|
||||||
annotation_array_ensure_space(struct annotation_info *annotation)
|
disasm_initialize(const struct gen_device_info *devinfo,
|
||||||
|
const struct cfg_t *cfg)
|
||||||
{
|
{
|
||||||
if (annotation->ann_size <= annotation->ann_count) {
|
struct disasm_info *disasm = ralloc(NULL, struct disasm_info);
|
||||||
int old_size = annotation->ann_size;
|
exec_list_make_empty(&disasm->group_list);
|
||||||
annotation->ann_size = MAX2(1024, annotation->ann_size * 2);
|
disasm->devinfo = devinfo;
|
||||||
annotation->ann = reralloc(annotation->mem_ctx, annotation->ann,
|
disasm->cfg = cfg;
|
||||||
struct annotation, annotation->ann_size);
|
disasm->cur_block = 0;
|
||||||
if (!annotation->ann)
|
disasm->use_tail = false;
|
||||||
return false;
|
return disasm;
|
||||||
|
|
||||||
memset(annotation->ann + old_size, 0,
|
|
||||||
(annotation->ann_size - old_size) * sizeof(struct annotation));
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void annotate(const struct gen_device_info *devinfo,
|
struct inst_group *
|
||||||
struct annotation_info *annotation, const struct cfg_t *cfg,
|
disasm_new_inst_group(struct disasm_info *disasm, unsigned next_inst_offset)
|
||||||
struct backend_instruction *inst, unsigned offset)
|
|
||||||
{
|
{
|
||||||
if (annotation->mem_ctx == NULL)
|
struct inst_group *tail = rzalloc(disasm, struct inst_group);
|
||||||
annotation->mem_ctx = ralloc_context(NULL);
|
tail->offset = next_inst_offset;
|
||||||
|
exec_list_push_tail(&disasm->group_list, &tail->link);
|
||||||
|
return tail;
|
||||||
|
}
|
||||||
|
|
||||||
if (!annotation_array_ensure_space(annotation))
|
void
|
||||||
return;
|
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 annotation *ann = &annotation->ann[annotation->ann_count++];
|
struct inst_group *group;
|
||||||
ann->offset = offset;
|
if (!disasm->use_tail) {
|
||||||
if ((INTEL_DEBUG & DEBUG_ANNOTATION) != 0) {
|
group = disasm_new_inst_group(disasm, offset);
|
||||||
ann->ir = inst->ir;
|
disasm->use_tail = false;
|
||||||
ann->annotation = inst->annotation;
|
} else {
|
||||||
|
group = exec_node_data(struct inst_group,
|
||||||
|
exec_list_get_tail_raw(&disasm->group_list), link);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bblock_start(cfg->blocks[annotation->cur_block]) == inst) {
|
if ((INTEL_DEBUG & DEBUG_ANNOTATION) != 0) {
|
||||||
ann->block_start = cfg->blocks[annotation->cur_block];
|
group->ir = inst->ir;
|
||||||
|
group->annotation = inst->annotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
/* There is no hardware DO instruction on Gen6+, so since DO always
|
||||||
|
@ -132,66 +147,48 @@ void annotate(const struct gen_device_info *devinfo,
|
||||||
* a corresponding hardware instruction to disassemble.
|
* a corresponding hardware instruction to disassemble.
|
||||||
*/
|
*/
|
||||||
if (devinfo->gen >= 6 && inst->opcode == BRW_OPCODE_DO) {
|
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) {
|
if (bblock_end(cfg->blocks[disasm->cur_block]) == inst) {
|
||||||
ann->block_end = cfg->blocks[annotation->cur_block];
|
group->block_end = cfg->blocks[disasm->cur_block];
|
||||||
annotation->cur_block++;
|
disasm->cur_block++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
annotation_finalize(struct annotation_info *annotation,
|
disasm_insert_error(struct disasm_info *disasm, unsigned offset,
|
||||||
unsigned next_inst_offset)
|
const char *error)
|
||||||
{
|
{
|
||||||
if (!annotation->ann_count)
|
foreach_list_typed(struct inst_group, cur, link, &disasm->group_list) {
|
||||||
return;
|
struct exec_node *next_node = exec_node_get_next(&cur->link);
|
||||||
|
if (exec_node_is_tail_sentinel(next_node))
|
||||||
|
break;
|
||||||
|
|
||||||
if (annotation->ann_count == annotation->ann_size) {
|
struct inst_group *next =
|
||||||
annotation->ann = reralloc(annotation->mem_ctx, annotation->ann,
|
exec_node_data(struct inst_group, next_node, link);
|
||||||
struct annotation, annotation->ann_size + 1);
|
|
||||||
}
|
|
||||||
annotation->ann[annotation->ann_count].offset = next_inst_offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
annotation_insert_error(struct annotation_info *annotation, 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);
|
|
||||||
|
|
||||||
for (int i = 0; i < annotation->ann_count; i++) {
|
|
||||||
struct annotation *cur = &annotation->ann[i];
|
|
||||||
struct annotation *next = &annotation->ann[i + 1];
|
|
||||||
|
|
||||||
if (next->offset <= offset)
|
if (next->offset <= offset)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (offset + sizeof(brw_inst) != next->offset) {
|
if (offset + sizeof(brw_inst) != next->offset) {
|
||||||
memmove(next, cur,
|
struct inst_group *new = ralloc(disasm, struct inst_group);
|
||||||
(annotation->ann_count - i + 2) * sizeof(struct annotation));
|
memcpy(new, cur, sizeof(struct inst_group));
|
||||||
|
|
||||||
cur->error = NULL;
|
cur->error = NULL;
|
||||||
cur->error_length = 0;
|
cur->error_length = 0;
|
||||||
cur->block_end = NULL;
|
cur->block_end = NULL;
|
||||||
next->offset = offset + sizeof(brw_inst);
|
|
||||||
next->block_start = NULL;
|
new->offset = offset + sizeof(brw_inst);
|
||||||
annotation->ann_count++;
|
new->block_start = NULL;
|
||||||
|
|
||||||
|
exec_node_insert_after(&cur->link, &new->link);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cur->error)
|
if (cur->error)
|
||||||
ralloc_strcat(&cur->error, error);
|
ralloc_strcat(&cur->error, error);
|
||||||
else
|
else
|
||||||
cur->error = ralloc_strdup(annotation->mem_ctx, error);
|
cur->error = ralloc_strdup(disasm, error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,14 +24,15 @@
|
||||||
#ifndef _INTEL_ASM_ANNOTATION_H
|
#ifndef _INTEL_ASM_ANNOTATION_H
|
||||||
#define _INTEL_ASM_ANNOTATION_H
|
#define _INTEL_ASM_ANNOTATION_H
|
||||||
|
|
||||||
|
#include "brw_cfg.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct backend_instruction;
|
struct inst_group {
|
||||||
struct cfg_t;
|
struct exec_node link;
|
||||||
|
|
||||||
struct annotation {
|
|
||||||
int offset;
|
int offset;
|
||||||
|
|
||||||
size_t error_length;
|
size_t error_length;
|
||||||
|
@ -48,30 +49,34 @@ struct annotation {
|
||||||
const char *annotation;
|
const char *annotation;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct annotation_info {
|
struct disasm_info {
|
||||||
void *mem_ctx;
|
struct exec_list group_list;
|
||||||
struct annotation *ann;
|
|
||||||
int ann_count;
|
const struct gen_device_info *devinfo;
|
||||||
int ann_size;
|
const struct cfg_t *cfg;
|
||||||
|
|
||||||
/** Block index in the cfg. */
|
/** Block index in the cfg. */
|
||||||
int cur_block;
|
int cur_block;
|
||||||
|
bool use_tail;
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
dump_assembly(void *assembly, int num_annotations, struct annotation *annotation,
|
dump_assembly(void *assembly, struct disasm_info *disasm);
|
||||||
const struct gen_device_info *devinfo);
|
|
||||||
|
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
|
void
|
||||||
annotate(const struct gen_device_info *devinfo,
|
disasm_annotate(struct disasm_info *disasm,
|
||||||
struct annotation_info *annotation, const struct cfg_t *cfg,
|
struct backend_instruction *inst, unsigned offset);
|
||||||
struct backend_instruction *inst, unsigned offset);
|
|
||||||
void
|
|
||||||
annotation_finalize(struct annotation_info *annotation, unsigned offset);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
annotation_insert_error(struct annotation_info *annotation, unsigned offset,
|
disasm_insert_error(struct disasm_info *disasm, unsigned offset,
|
||||||
const char *error);
|
const char *error);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} /* extern "C" */
|
} /* extern "C" */
|
||||||
|
|
|
@ -113,25 +113,20 @@ static bool
|
||||||
validate(struct brw_codegen *p)
|
validate(struct brw_codegen *p)
|
||||||
{
|
{
|
||||||
const bool print = getenv("TEST_DEBUG");
|
const bool print = getenv("TEST_DEBUG");
|
||||||
struct annotation_info annotation;
|
struct disasm_info disasm = disasm_initialize(p->devinfo, NULL);
|
||||||
memset(&annotation, 0, sizeof(annotation));
|
|
||||||
|
|
||||||
if (print) {
|
if (print) {
|
||||||
annotation.mem_ctx = ralloc_context(NULL);
|
disasm_new_inst_group(&disasm, 0);
|
||||||
annotation.ann_count = 1;
|
disasm_new_inst_group(&disasm, p->next_insn_offset);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ret = brw_validate_instructions(p->devinfo, p->store, 0,
|
bool ret = brw_validate_instructions(p->devinfo, p->store, 0,
|
||||||
p->next_insn_offset, &annotation);
|
p->next_insn_offset, &disasm);
|
||||||
|
|
||||||
if (print) {
|
if (print) {
|
||||||
dump_assembly(p->store, annotation.ann_count, annotation.ann, p->devinfo);
|
dump_assembly(p->store, &disasm);
|
||||||
ralloc_free(annotation.mem_ctx);
|
|
||||||
}
|
}
|
||||||
|
ralloc_free(disasm.mem_ctx);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,34 +76,35 @@ gen_disasm_disassemble(struct gen_disasm *disasm, void *assembly,
|
||||||
struct gen_device_info *devinfo = &disasm->devinfo;
|
struct gen_device_info *devinfo = &disasm->devinfo;
|
||||||
int end = gen_disasm_find_end(disasm, assembly, start);
|
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.
|
* can work from.
|
||||||
*/
|
*/
|
||||||
struct annotation_info annotation_info = {
|
struct disasm_info *disasm_info = disasm_initialize(devinfo, NULL);
|
||||||
.ann_count = 1,
|
disasm_new_inst_group(disasm_info, start);
|
||||||
.ann_size = 2,
|
disasm_new_inst_group(disasm_info, end);
|
||||||
};
|
|
||||||
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++) {
|
brw_validate_instructions(devinfo, assembly, start, end, disasm_info);
|
||||||
int start_offset = annotation[i].offset;
|
|
||||||
int end_offset = annotation[i + 1].offset;
|
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);
|
brw_disassemble(devinfo, assembly, start_offset, end_offset, out);
|
||||||
|
|
||||||
if (annotation[i].error) {
|
if (group->error) {
|
||||||
fputs(annotation[i].error, out);
|
fputs(group->error, out);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ralloc_free(annotation_info.mem_ctx);
|
ralloc_free(disasm_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct gen_disasm *
|
struct gen_disasm *
|
||||||
|
|
|
@ -127,7 +127,7 @@ brw_codegen_ff_gs_prog(struct brw_context *brw,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
brw_compact_instructions(&c.func, 0, 0, NULL);
|
brw_compact_instructions(&c.func, 0, NULL);
|
||||||
|
|
||||||
/* get the program
|
/* get the program
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue