X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Famd%2Fcompiler%2Faco_print_asm.cpp;h=ce12aacf9e407cd2fb50d633e9756e463fdbeb5b;hb=38a83a30484c5d7dfcdce3c41d71373c09d42668;hp=743824888d6b9c4faa55f9ddd3903fbc1877e0f4;hpb=23319add93bb22744ba48e9026dcc40ecd30628c;p=mesa.git diff --git a/src/amd/compiler/aco_print_asm.cpp b/src/amd/compiler/aco_print_asm.cpp index 743824888d6..ce12aacf9e4 100644 --- a/src/amd/compiler/aco_print_asm.cpp +++ b/src/amd/compiler/aco_print_asm.cpp @@ -5,12 +5,97 @@ #include "ac_llvm_util.h" #include +#if LLVM_VERSION_MAJOR >= 11 +#include +#endif namespace aco { +/* LLVM disassembler only supports GFX8+, try to disassemble with CLRXdisasm + * for GFX6-GFX7 if found on the system, this is better than nothing. +*/ +void print_asm_gfx6_gfx7(Program *program, std::vector& binary, + std::ostream& out) +{ + char path[] = "/tmp/fileXXXXXX"; + char line[2048], command[128]; + const char *gpu_type; + FILE *p; + int fd; + + /* Dump the binary into a temporary file. */ + fd = mkstemp(path); + if (fd < 0) + return; + + for (uint32_t w : binary) + { + if (write(fd, &w, sizeof(w)) == -1) + goto fail; + } + + /* Determine the GPU type for CLRXdisasm. Use the family for GFX6 chips + * because it doesn't allow to use gfx600 directly. + */ + switch (program->chip_class) { + case GFX6: + switch (program->family) { + case CHIP_TAHITI: + gpu_type = "tahiti"; + break; + case CHIP_PITCAIRN: + gpu_type = "pitcairn"; + break; + case CHIP_VERDE: + gpu_type = "capeverde"; + break; + case CHIP_OLAND: + gpu_type = "oland"; + break; + case CHIP_HAINAN: + gpu_type = "hainan"; + break; + default: + unreachable("Invalid GFX6 family!"); + } + break; + case GFX7: + gpu_type = "gfx700"; + break; + default: + unreachable("Invalid chip class!"); + } + + sprintf(command, "clrxdisasm --gpuType=%s -r %s", gpu_type, path); + + p = popen(command, "r"); + if (p) { + if (!fgets(line, sizeof(line), p)) { + out << "clrxdisasm not found\n"; + pclose(p); + goto fail; + } + + do { + out << line; + } while (fgets(line, sizeof(line), p)); + + pclose(p); + } + +fail: + close(fd); + unlink(path); +} + void print_asm(Program *program, std::vector& binary, unsigned exec_size, std::ostream& out) { + if (program->chip_class <= GFX7) { + print_asm_gfx6_gfx7(program, binary, out); + return; + } + std::vector referenced_blocks(program->blocks.size()); referenced_blocks[0] = true; for (Block& block : program->blocks) { @@ -18,7 +103,11 @@ void print_asm(Program *program, std::vector& binary, referenced_blocks[succ] = true; } + #if LLVM_VERSION_MAJOR >= 11 + std::vector symbols; + #else std::vector> symbols; + #endif std::vector> block_names; block_names.reserve(program->blocks.size()); for (Block& block : program->blocks) { @@ -53,34 +142,56 @@ void print_asm(Program *program, std::vector& binary, /* mask out src2 on v_writelane_b32 */ if (((program->chip_class == GFX8 || program->chip_class == GFX9) && (binary[pos] & 0xffff8000) == 0xd28a0000) || - (program->chip_class == GFX10 && (binary[pos] & 0xffff8000) == 0xd7610000)) { + (program->chip_class >= GFX10 && (binary[pos] & 0xffff8000) == 0xd7610000)) { binary[pos+1] = binary[pos+1] & 0xF803FFFF; } + const int align_width = 60; + out << std::left << std::setw(align_width) << std::setfill(' '); + size_t l = LLVMDisasmInstruction(disasm, (uint8_t *) &binary[pos], (exec_size - pos) * sizeof(uint32_t), pos * 4, outline, sizeof(outline)); size_t new_pos; - const int align_width = 60; - if (!l && program->chip_class == GFX9 && ((binary[pos] & 0xffff8000) == 0xd1348000)) { /* not actually an invalid instruction */ - out << std::left << std::setw(align_width) << std::setfill(' ') << "\tv_add_u32_e64 + clamp"; + if (!l && + ((program->chip_class >= GFX9 && (binary[pos] & 0xffff8000) == 0xd1348000) || /* v_add_u32_e64 + clamp */ + (program->chip_class >= GFX10 && (binary[pos] & 0xffff8000) == 0xd7038000) || /* v_add_u16_e64 + clamp */ + (program->chip_class <= GFX9 && (binary[pos] & 0xffff8000) == 0xd1268000)) /* v_add_u16_e64 + clamp */) { + out << "\tinteger addition + clamp"; + bool has_literal = program->chip_class >= GFX10 && + (((binary[pos+1] & 0x1ff) == 0xff) || (((binary[pos+1] >> 9) & 0x1ff) == 0xff)); + new_pos = pos + 2 + has_literal; + } else if (program->chip_class >= GFX10 && l == 4 && ((binary[pos] & 0xfe0001ff) == 0x020000f9)) { + out << "\tv_cndmask_b32 + sdwa"; new_pos = pos + 2; } else if (!l) { - out << std::left << std::setw(align_width) << std::setfill(' ') << "(invalid instruction)"; + out << "(invalid instruction)"; new_pos = pos + 1; invalid = true; } else { - out << std::left << std::setw(align_width) << std::setfill(' ') << outline; + out << outline; assert(l % 4 == 0); new_pos = pos + l / 4; } + size_t size = new_pos - pos; out << std::right; out << " ;"; - for (; pos < new_pos; pos++) - out << " " << std::setfill('0') << std::setw(8) << std::hex << binary[pos]; + for (unsigned i = 0; i < size; i++) + out << " " << std::setfill('0') << std::setw(8) << std::hex << binary[pos + i]; out << std::endl; + + size_t original_pos = pos; + pos += size; + + unsigned repeat_count = 0; + while (pos + size <= exec_size && memcmp(&binary[pos], &binary[original_pos], size * 4) == 0) { + repeat_count++; + pos += size; + } + if (repeat_count) + out << std::left << std::setw(0) << std::dec << std::setfill(' ') << "\t(then repeated " << repeat_count << " times)" << std::endl; } out << std::setfill(' ') << std::setw(0) << std::dec; assert(next_block == program->blocks.size());