From c2b1978aa47c5b8876a589aa035a670d55e87c2e Mon Sep 17 00:00:00 2001 From: Samuel Pitoiset Date: Fri, 14 Aug 2020 10:42:27 +0200 Subject: [PATCH] aco: rework the way various compilation/validation errors are reported The upcoming change will allow to report all ACO errors (or warnings) directly to the app via VK_EXT_debug_report. This is similar to what we already do for reporting various SPIRV->NIR errors. Signed-off-by: Samuel Pitoiset Reviewed-by: Rhys Perry Part-of: --- src/amd/compiler/aco_assembler.cpp | 15 +- .../compiler/aco_instruction_selection.cpp | 369 +++++------------- src/amd/compiler/aco_interface.cpp | 4 +- src/amd/compiler/aco_ir.h | 14 +- src/amd/compiler/aco_live_var_analysis.cpp | 2 +- src/amd/compiler/aco_optimizer.cpp | 25 +- src/amd/compiler/aco_register_allocation.cpp | 2 +- src/amd/compiler/aco_validate.cpp | 124 ++++-- src/amd/compiler/tests/helpers.cpp | 6 +- 9 files changed, 239 insertions(+), 322 deletions(-) diff --git a/src/amd/compiler/aco_assembler.cpp b/src/amd/compiler/aco_assembler.cpp index 5e199d48e0a..b056cd507b6 100644 --- a/src/amd/compiler/aco_assembler.cpp +++ b/src/amd/compiler/aco_assembler.cpp @@ -80,8 +80,17 @@ void emit_instruction(asm_context& ctx, std::vector& out, Instruction* uint32_t opcode = ctx.opcode[(int)instr->opcode]; if (opcode == (uint32_t)-1) { - fprintf(stderr, "Unsupported opcode: "); - aco_print_instr(instr, stderr); + char *out; + size_t outsize; + FILE *memf = open_memstream(&out, &outsize); + + fprintf(memf, "Unsupported opcode: "); + aco_print_instr(instr, memf); + fclose(memf); + + aco_err(ctx.program, out); + free(out); + abort(); } @@ -737,7 +746,7 @@ void fix_exports(asm_context& ctx, std::vector& out, Program* program) if (!exported) { /* Abort in order to avoid a GPU hang. */ - fprintf(stderr, "Missing export in %s shader:\n", (program->stage & hw_vs) ? "vertex" : "fragment"); + aco_err(program, "Missing export in %s shader:", (program->stage & hw_vs) ? "vertex" : "fragment"); aco_print_program(program, stderr); abort(); } diff --git a/src/amd/compiler/aco_instruction_selection.cpp b/src/amd/compiler/aco_instruction_selection.cpp index 4c9fe3fcd03..07c61a33d81 100644 --- a/src/amd/compiler/aco_instruction_selection.cpp +++ b/src/amd/compiler/aco_instruction_selection.cpp @@ -38,6 +38,23 @@ namespace aco { namespace { +#define isel_err(...) _isel_err(ctx, __FILE__, __LINE__, __VA_ARGS__) + +static void _isel_err(isel_context *ctx, const char *file, unsigned line, + const nir_instr *instr, const char *msg) +{ + char *out; + size_t outsize; + FILE *memf = open_memstream(&out, &outsize); + + fprintf(memf, "%s: ", msg); + nir_print_instr(instr, memf); + fclose(memf); + + _aco_err(ctx->program, file, line, out); + free(out); +} + class loop_info_RAII { isel_context* ctx; unsigned header_idx_old; @@ -951,9 +968,7 @@ void emit_bcsel(isel_context *ctx, nir_alu_instr *instr, Temp dst) bld.pseudo(aco_opcode::p_create_vector, Definition(dst), dst0, dst1); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } return; } @@ -971,9 +986,7 @@ void emit_bcsel(isel_context *ctx, nir_alu_instr *instr, Temp dst) aco_opcode op = dst.regClass() == s1 ? aco_opcode::s_cselect_b32 : aco_opcode::s_cselect_b64; bld.sop2(op, Definition(dst), then, els, bld.scc(bool_to_scalar_condition(ctx, cond))); } else { - fprintf(stderr, "Unimplemented uniform bcsel bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented uniform bcsel bit size"); } return; } @@ -1128,9 +1141,7 @@ Temp emit_floor_f64(isel_context *ctx, Builder& bld, Definition dst, Temp val) void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) { if (!instr->dest.dest.is_ssa) { - fprintf(stderr, "nir alu dst not in ssa: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "nir alu dst not in ssa"); abort(); } Builder bld(ctx->program, ctx->block); @@ -1224,9 +1235,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) aco_opcode opcode = dst.size() == 1 ? aco_opcode::s_not_b32 : aco_opcode::s_not_b64; bld.sop1(opcode, Definition(dst), bld.def(s1, scc), src); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -1253,9 +1262,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) bld.pseudo(aco_opcode::p_create_vector, Definition(dst), lower, upper); } } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -1266,9 +1273,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) Temp src = get_alu_src(ctx, instr->src[0]); bld.vop2(aco_opcode::v_max_i32, Definition(dst), src, bld.vsub32(bld.def(v1), Operand(0u), src)); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -1296,9 +1301,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) upper = bld.vop2(aco_opcode::v_cndmask_b32, bld.def(v1), Operand(0u), neg, gtz); bld.pseudo(aco_opcode::p_create_vector, Definition(dst), lower, upper); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -1308,9 +1311,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) } else if (dst.regClass() == s1) { emit_sop2_instruction(ctx, instr, aco_opcode::s_max_i32, dst, true); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -1320,9 +1321,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) } else if (dst.regClass() == s1) { emit_sop2_instruction(ctx, instr, aco_opcode::s_max_u32, dst, true); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -1332,9 +1331,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) } else if (dst.regClass() == s1) { emit_sop2_instruction(ctx, instr, aco_opcode::s_min_i32, dst, true); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -1344,9 +1341,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) } else if (dst.regClass() == s1) { emit_sop2_instruction(ctx, instr, aco_opcode::s_min_u32, dst, true); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -1362,9 +1357,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) } else if (dst.regClass() == s2) { emit_sop2_instruction(ctx, instr, aco_opcode::s_or_b64, dst, true); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -1380,9 +1373,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) } else if (dst.regClass() == s2) { emit_sop2_instruction(ctx, instr, aco_opcode::s_and_b64, dst, true); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -1398,9 +1389,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) } else if (dst.regClass() == s2) { emit_sop2_instruction(ctx, instr, aco_opcode::s_xor_b64, dst, true); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -1418,9 +1407,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) } else if (dst.regClass() == s1) { emit_sop2_instruction(ctx, instr, aco_opcode::s_lshr_b32, dst, true); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -1438,9 +1425,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) } else if (dst.regClass() == s2) { emit_sop2_instruction(ctx, instr, aco_opcode::s_lshl_b64, dst, true); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -1458,9 +1443,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) } else if (dst.regClass() == s2) { emit_sop2_instruction(ctx, instr, aco_opcode::s_ashr_i64, dst, true); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -1473,9 +1456,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) } else if (src.regClass() == s2) { bld.sop1(aco_opcode::s_ff1_i32_b64, Definition(dst), src); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -1502,9 +1483,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) Temp carry = bld.vsub32(Definition(msb), Operand(31u), Operand(msb_rev), true).def(1).getTemp(); bld.vop2_e64(aco_opcode::v_cndmask_b32, Definition(dst), msb, Operand((uint32_t)-1), carry); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -1514,9 +1493,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) } else if (dst.regClass() == v1) { bld.vop1(aco_opcode::v_bfrev_b32, Definition(dst), get_alu_src(ctx, instr->src[0])); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -1552,9 +1529,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) Temp dst1 = bld.vadd32(bld.def(v1), src01, src11, false, carry); bld.pseudo(aco_opcode::p_create_vector, Definition(dst), dst0, dst1); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -1583,9 +1558,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) bld.vop2_e64(aco_opcode::v_cndmask_b32, Definition(dst), tmp, Operand((uint32_t) -1), carry); } } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -1619,9 +1592,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) carry = bld.vop2_e64(aco_opcode::v_cndmask_b32, bld.def(v1), Operand(0u), Operand(1u), carry); bld.pseudo(aco_opcode::p_create_vector, Definition(dst), carry, Operand(0u)); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -1655,9 +1626,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) Temp upper = bld.vsub32(bld.def(v1), src01, src11, false, borrow); bld.pseudo(aco_opcode::p_create_vector, Definition(dst), lower, upper); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -1690,9 +1659,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) borrow = bld.vop2_e64(aco_opcode::v_cndmask_b32, bld.def(v1), Operand(0u), Operand(1u), borrow); bld.pseudo(aco_opcode::p_create_vector, Definition(dst), borrow, Operand(0u)); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -1703,9 +1670,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) } else if (dst.regClass() == s1) { emit_sop2_instruction(ctx, instr, aco_opcode::s_mul_i32, dst, false); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -1719,9 +1684,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) as_vgpr(ctx, get_alu_src(ctx, instr->src[1]))); bld.pseudo(aco_opcode::p_as_uniform, Definition(dst), tmp); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -1735,9 +1698,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) as_vgpr(ctx, get_alu_src(ctx, instr->src[1]))); bld.pseudo(aco_opcode::p_as_uniform, Definition(dst), tmp); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -1751,9 +1712,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) } else if (dst.regClass() == v2) { bld.vop3(aco_opcode::v_mul_f64, Definition(dst), src0, src1); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -1767,9 +1726,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) } else if (dst.regClass() == v2) { bld.vop3(aco_opcode::v_add_f64, Definition(dst), src0, src1); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -1792,9 +1749,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) VOP3A_instruction* sub = static_cast(add); sub->neg[1] = true; } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -1814,9 +1769,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) bld.vop3(aco_opcode::v_max_f64, Definition(dst), src0, src1); } } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -1836,9 +1789,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) bld.vop3(aco_opcode::v_min_f64, Definition(dst), src0, src1); } } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -1848,9 +1799,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) } else if (dst.regClass() == v1) { emit_vop3a_instruction(ctx, instr, aco_opcode::v_max3_f32, dst, ctx->block->fp_mode.must_flush_denorms32); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -1860,9 +1809,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) } else if (dst.regClass() == v1) { emit_vop3a_instruction(ctx, instr, aco_opcode::v_min3_f32, dst, ctx->block->fp_mode.must_flush_denorms32); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -1872,9 +1819,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) } else if (dst.regClass() == v1) { emit_vop3a_instruction(ctx, instr, aco_opcode::v_med3_f32, dst, ctx->block->fp_mode.must_flush_denorms32); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -1882,9 +1827,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) if (dst.size() == 1) { emit_vop3a_instruction(ctx, instr, aco_opcode::v_max3_u32, dst); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -1892,9 +1835,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) if (dst.size() == 1) { emit_vop3a_instruction(ctx, instr, aco_opcode::v_min3_u32, dst); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -1902,9 +1843,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) if (dst.size() == 1) { emit_vop3a_instruction(ctx, instr, aco_opcode::v_med3_u32, dst); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -1912,9 +1851,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) if (dst.size() == 1) { emit_vop3a_instruction(ctx, instr, aco_opcode::v_max3_i32, dst); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -1922,9 +1859,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) if (dst.size() == 1) { emit_vop3a_instruction(ctx, instr, aco_opcode::v_min3_i32, dst); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -1932,9 +1867,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) if (dst.size() == 1) { emit_vop3a_instruction(ctx, instr, aco_opcode::v_med3_i32, dst); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -1976,9 +1909,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) /* Lowered at NIR level for precision reasons. */ emit_vop1_instruction(ctx, instr, aco_opcode::v_rsq_f64, dst); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -2000,9 +1931,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) upper = bld.vop2(aco_opcode::v_xor_b32, bld.def(v1), Operand(0x80000000u), upper); bld.pseudo(aco_opcode::p_create_vector, Definition(dst), lower, upper); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -2024,9 +1953,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) upper = bld.vop2(aco_opcode::v_and_b32, bld.def(v1), Operand(0x7FFFFFFFu), upper); bld.pseudo(aco_opcode::p_create_vector, Definition(dst), lower, upper); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -2043,9 +1970,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) VOP3A_instruction* vop3 = static_cast(add); vop3->clamp = true; } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -2056,9 +1981,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) } else if (dst.regClass() == v1) { emit_log2(ctx, bld, Definition(dst), src); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -2072,9 +1995,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) /* Lowered at NIR level for precision reasons. */ emit_vop1_instruction(ctx, instr, aco_opcode::v_rcp_f64, dst); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -2084,9 +2005,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) } else if (dst.regClass() == v1) { emit_vop1_instruction(ctx, instr, aco_opcode::v_exp_f32, dst); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -2100,9 +2019,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) /* Lowered at NIR level for precision reasons. */ emit_vop1_instruction(ctx, instr, aco_opcode::v_sqrt_f64, dst); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -2114,9 +2031,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) } else if (dst.regClass() == v2) { emit_vop1_instruction(ctx, instr, aco_opcode::v_fract_f64, dst); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -2129,9 +2044,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) } else if (dst.regClass() == v2) { emit_floor_f64(ctx, bld, Definition(dst), src); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -2159,9 +2072,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) bld.vop3(aco_opcode::v_add_f64, Definition(dst), trunc, add); } } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -2174,9 +2085,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) } else if (dst.regClass() == v2) { emit_trunc_f64(ctx, bld, Definition(dst), src); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -2214,9 +2123,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) bld.pseudo(aco_opcode::p_create_vector, Definition(dst), dst0, dst1); } } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -2240,9 +2147,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) aco_opcode opcode = instr->op == nir_op_fsin ? aco_opcode::v_sin_f32 : aco_opcode::v_cos_f32; bld.vop1(opcode, Definition(dst), tmp); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -2256,9 +2161,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) } else if (dst.regClass() == v2) { bld.vop3(aco_opcode::v_ldexp_f64, Definition(dst), as_vgpr(ctx, src0), src1); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -2271,9 +2174,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) } else if (dst.regClass() == v2) { bld.vop1(aco_opcode::v_frexp_mant_f64, Definition(dst), src); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -2288,9 +2189,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) } else if (instr->src[0].src.ssa->bit_size == 64) { bld.vop1(aco_opcode::v_frexp_exp_i32_f64, Definition(dst), src); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -2319,9 +2218,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) bld.pseudo(aco_opcode::p_create_vector, Definition(dst), Operand(0u), upper); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -2352,9 +2249,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) } else if (instr->src[0].src.ssa->bit_size == 64) { emit_vop1_instruction(ctx, instr, aco_opcode::v_cvt_f32_f64, dst); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -2400,9 +2295,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) bld.vop3(aco_opcode::v_add_f64, Definition(dst), lower, upper); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -2444,9 +2337,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) upper = bld.vop3(aco_opcode::v_ldexp_f64, bld.def(v2), upper, Operand(32u)); bld.vop3(aco_opcode::v_add_f64, Definition(dst), lower, upper); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -2485,9 +2376,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) } else if (instr->src[0].src.ssa->bit_size == 64) { emit_vop1_instruction(ctx, instr, aco_opcode::v_cvt_i32_f64, dst); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -2506,9 +2395,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) } else if (instr->src[0].src.ssa->bit_size == 64) { emit_vop1_instruction(ctx, instr, aco_opcode::v_cvt_u32_f64, dst); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -2585,9 +2472,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) bld.pseudo(aco_opcode::p_create_vector, Definition(dst), lower, upper); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -2657,9 +2542,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) bld.pseudo(aco_opcode::p_create_vector, Definition(dst), lower, upper); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -2838,9 +2721,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) bld.vop1(aco_opcode::v_cvt_f32_f16, bld.def(v1), src0), bld.vop1(aco_opcode::v_cvt_f32_f16, bld.def(v1), src1)); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -2848,9 +2729,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) if (dst.regClass() == v1) { bld.vop1(aco_opcode::v_cvt_f32_f16, Definition(dst), get_alu_src(ctx, instr->src[0])); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -2860,9 +2739,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) bld.vop1(aco_opcode::v_cvt_f32_f16, Definition(dst), bld.vop2(aco_opcode::v_lshrrev_b32, bld.def(v1), Operand(16u), as_vgpr(ctx, get_alu_src(ctx, instr->src[0])))); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -2903,9 +2780,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) } else if (dst.regClass() == v1) { bld.vop3(aco_opcode::v_bfm_b32, Definition(dst), bits, offset); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -2948,9 +2823,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) bld.vop3(aco_opcode::v_bfi_b32, Definition(dst), bitmask, insert, base); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -3023,9 +2896,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) } else if (src.regClass() == s2) { bld.sop1(aco_opcode::s_bcnt1_i32_b64, Definition(dst), bld.def(s1, scc), src); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -3112,9 +2983,7 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) break; } default: - fprintf(stderr, "Unknown NIR ALU instr: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unknown NIR ALU instr"); } } @@ -4521,9 +4390,7 @@ void visit_store_output(isel_context *ctx, nir_intrinsic_instr *instr) ctx->shader->info.stage == MESA_SHADER_GEOMETRY) { bool stored_to_temps = store_output_to_temps(ctx, instr); if (!stored_to_temps) { - fprintf(stderr, "Unimplemented output offset instruction:\n"); - nir_print_instr(instr->src[1].ssa->parent_instr, stderr); - fprintf(stderr, "\n"); + isel_err(instr->src[1].ssa->parent_instr, "Unimplemented output offset instruction"); abort(); } } else if (ctx->stage == vertex_es || @@ -4740,9 +4607,7 @@ void visit_load_input(isel_context *ctx, nir_intrinsic_instr *instr) nir_instr *off_instr = instr->src[0].ssa->parent_instr; if (off_instr->type != nir_instr_type_load_const) { - fprintf(stderr, "Unimplemented nir_intrinsic_load_input offset\n"); - nir_print_instr(off_instr, stderr); - fprintf(stderr, "\n"); + isel_err(off_instr, "Unimplemented nir_intrinsic_load_input offset"); } uint32_t offset = nir_instr_as_load_const(off_instr)->value[0].u32; @@ -4954,9 +4819,7 @@ void visit_load_input(isel_context *ctx, nir_intrinsic_instr *instr) nir_instr *off_instr = instr->src[offset_idx].ssa->parent_instr; if (off_instr->type != nir_instr_type_load_const || nir_instr_as_load_const(off_instr)->value[0].u32 != 0) { - fprintf(stderr, "Unimplemented nir_intrinsic_load_input offset\n"); - nir_print_instr(off_instr, stderr); - fprintf(stderr, "\n"); + isel_err(off_instr, "Unimplemented nir_intrinsic_load_input offset"); } Temp prim_mask = get_arg(ctx, ctx->args->ac.prim_mask); @@ -7263,9 +7126,7 @@ void emit_uniform_subgroup(isel_context *ctx, nir_intrinsic_instr *instr, Temp s } else if (src.regClass() == s2) { bld.sop1(aco_opcode::s_mov_b64, dst, src); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } } @@ -7696,9 +7557,7 @@ void visit_intrinsic(isel_context *ctx, nir_intrinsic_instr *instr) } else if (instr->src[0].ssa->bit_size == 64 && src.regClass() == v2) { bld.vopc(aco_opcode::v_cmp_lg_u64, lanemask_tmp, Operand(0u), src); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } if (dst.size() != bld.lm.size()) { /* Wave32 with ballot size set to 64 */ @@ -7750,9 +7609,7 @@ void visit_intrinsic(isel_context *ctx, nir_intrinsic_instr *instr) tmp = bld.vop2(aco_opcode::v_and_b32, bld.def(v1), Operand(1u), tmp); emit_wqm(ctx, bld.vopc(aco_opcode::v_cmp_lg_u32, bld.def(bld.lm), Operand(0u), tmp), dst); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } } break; @@ -7790,9 +7647,7 @@ void visit_intrinsic(isel_context *ctx, nir_intrinsic_instr *instr) } else if (src.regClass() == s2) { bld.pseudo(aco_opcode::p_create_vector, Definition(dst), src); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -7963,9 +7818,7 @@ void visit_intrinsic(isel_context *ctx, nir_intrinsic_instr *instr) bld.pseudo(aco_opcode::p_create_vector, Definition(dst), lo, hi); emit_split_vector(ctx, dst, 2); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } } break; @@ -8043,9 +7896,7 @@ void visit_intrinsic(isel_context *ctx, nir_intrinsic_instr *instr) bld.pseudo(aco_opcode::p_create_vector, Definition(dst), lo, hi); emit_split_vector(ctx, dst, 2); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -8079,9 +7930,7 @@ void visit_intrinsic(isel_context *ctx, nir_intrinsic_instr *instr) bld.pseudo(aco_opcode::p_create_vector, Definition(dst), lo, hi); emit_split_vector(ctx, dst, 2); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -8103,9 +7952,7 @@ void visit_intrinsic(isel_context *ctx, nir_intrinsic_instr *instr) bld.pseudo(aco_opcode::p_create_vector, Definition(dst), lo, hi); emit_split_vector(ctx, dst, 2); } else { - fprintf(stderr, "Unimplemented NIR instr bit size: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented NIR instr bit size"); } break; } @@ -8256,9 +8103,7 @@ void visit_intrinsic(isel_context *ctx, nir_intrinsic_instr *instr) break; } default: - fprintf(stderr, "Unimplemented intrinsic instr: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unimplemented intrinsic instr"); abort(); break; @@ -9325,9 +9170,7 @@ void visit_jump(isel_context *ctx, nir_jump_instr *instr) } break; default: - fprintf(stderr, "Unknown NIR jump instr: "); - nir_print_instr(&instr->instr, stderr); - fprintf(stderr, "\n"); + isel_err(&instr->instr, "Unknown NIR jump instr"); abort(); } @@ -9385,9 +9228,7 @@ void visit_block(isel_context *ctx, nir_block *block) visit_jump(ctx, nir_instr_as_jump(instr)); break; default: - fprintf(stderr, "Unknown NIR instr type: "); - nir_print_instr(instr, stderr); - fprintf(stderr, "\n"); + isel_err(instr, "Unknown NIR instr type"); //abort(); } } diff --git a/src/amd/compiler/aco_interface.cpp b/src/amd/compiler/aco_interface.cpp index 95c2ac1be08..4dfba2618cc 100644 --- a/src/amd/compiler/aco_interface.cpp +++ b/src/amd/compiler/aco_interface.cpp @@ -48,7 +48,7 @@ static void validate(aco::Program *program) if (!(aco::debug_flags & aco::DEBUG_VALIDATE_IR)) return; - bool is_valid = aco::validate_ir(program, stderr); + bool is_valid = aco::validate_ir(program); assert(is_valid); } @@ -121,7 +121,7 @@ void aco_compile_shader(unsigned shader_count, aco_print_program(program.get(), stderr); } - if (aco::validate_ra(program.get(), args->options, stderr)) { + if (aco::validate_ra(program.get(), args->options)) { std::cerr << "Program after RA validation failure:\n"; aco_print_program(program.get(), stderr); abort(); diff --git a/src/amd/compiler/aco_ir.h b/src/amd/compiler/aco_ir.h index 62f9303e793..5fb4a095db9 100644 --- a/src/amd/compiler/aco_ir.h +++ b/src/amd/compiler/aco_ir.h @@ -1665,10 +1665,10 @@ void insert_NOPs(Program* program); unsigned emit_program(Program* program, std::vector& code); void print_asm(Program *program, std::vector& binary, unsigned exec_size, std::ostream& out); -bool validate_ir(Program* program, FILE *output); -bool validate_ra(Program* program, const struct radv_nir_compiler_options *options, FILE *output); +bool validate_ir(Program* program); +bool validate_ra(Program* program, const struct radv_nir_compiler_options *options); #ifndef NDEBUG -void perfwarn(bool cond, const char *msg, Instruction *instr=NULL); +void perfwarn(Program *program, bool cond, const char *msg, Instruction *instr=NULL); #else #define perfwarn(program, cond, msg, ...) do {} while(0) #endif @@ -1680,6 +1680,14 @@ void collect_postasm_stats(Program *program, const std::vector& code); void aco_print_instr(const Instruction *instr, FILE *output); void aco_print_program(const Program *program, FILE *output); +void _aco_perfwarn(Program *program, const char *file, unsigned line, + const char *fmt, ...); +void _aco_err(Program *program, const char *file, unsigned line, + const char *fmt, ...); + +#define aco_perfwarn(program, ...) _aco_perfwarn(program, __FILE__, __LINE__, __VA_ARGS__) +#define aco_err(program, ...) _aco_err(program, __FILE__, __LINE__, __VA_ARGS__) + /* utilities for dealing with register demand */ RegisterDemand get_live_changes(aco_ptr& instr); RegisterDemand get_temp_registers(aco_ptr& instr); diff --git a/src/amd/compiler/aco_live_var_analysis.cpp b/src/amd/compiler/aco_live_var_analysis.cpp index 08f2d68c80a..1c47eb3d6a4 100644 --- a/src/amd/compiler/aco_live_var_analysis.cpp +++ b/src/amd/compiler/aco_live_var_analysis.cpp @@ -214,7 +214,7 @@ void process_live_temps_per_block(Program *program, live& lives, Block* block, #ifndef NDEBUG if (preds.empty()) - fprintf(stderr, "Temporary never defined or are defined after use: %%%d in BB%d\n", t.id(), block->index); + aco_err(program, "Temporary never defined or are defined after use: %%%d in BB%d", t.id(), block->index); #endif for (unsigned pred_idx : preds) { diff --git a/src/amd/compiler/aco_optimizer.cpp b/src/amd/compiler/aco_optimizer.cpp index d060f378fe2..0a43964457a 100644 --- a/src/amd/compiler/aco_optimizer.cpp +++ b/src/amd/compiler/aco_optimizer.cpp @@ -34,6 +34,27 @@ namespace aco { +#ifndef NDEBUG +void perfwarn(Program *program, bool cond, const char *msg, Instruction *instr) +{ + if (cond) { + char *out; + size_t outsize; + FILE *memf = open_memstream(&out, &outsize); + + fprintf(memf, "%s: ", msg); + aco_print_instr(instr, memf); + fclose(memf); + + aco_perfwarn(program, out); + free(out); + + if (debug_flags & DEBUG_PERFWARN) + exit(1); + } +} +#endif + /** * The optimizer works in 4 phases: * (1) The first pass collects information for each ssa-def, @@ -803,7 +824,7 @@ void label_instruction(opt_ctx &ctx, Block& block, aco_ptr& instr) ASSERTED bool all_const = false; for (Operand& op : instr->operands) all_const = all_const && (!op.isTemp() || ctx.info[op.tempId()].is_constant_or_literal(32)); - perfwarn(all_const, "All instruction operands are constant", instr.get()); + perfwarn(ctx.program, all_const, "All instruction operands are constant", instr.get()); } for (unsigned i = 0; i < instr->operands.size(); i++) @@ -905,7 +926,7 @@ void label_instruction(opt_ctx &ctx, Block& block, aco_ptr& instr) unsigned bits = get_operand_size(instr, i); if (info.is_constant(bits) && alu_can_accept_constant(instr->opcode, i)) { Operand op = get_constant_op(ctx, info, bits); - perfwarn(instr->opcode == aco_opcode::v_cndmask_b32 && i == 2, "v_cndmask_b32 with a constant selector", instr.get()); + perfwarn(ctx.program, instr->opcode == aco_opcode::v_cndmask_b32 && i == 2, "v_cndmask_b32 with a constant selector", instr.get()); if (i == 0 || instr->opcode == aco_opcode::v_readlane_b32 || instr->opcode == aco_opcode::v_writelane_b32) { instr->operands[i] = op; continue; diff --git a/src/amd/compiler/aco_register_allocation.cpp b/src/amd/compiler/aco_register_allocation.cpp index 862b00d859b..ca7a0fa4815 100644 --- a/src/amd/compiler/aco_register_allocation.cpp +++ b/src/amd/compiler/aco_register_allocation.cpp @@ -1259,7 +1259,7 @@ PhysReg get_reg(ra_ctx& ctx, //FIXME: if nothing helps, shift-rotate the registers to make space - fprintf(stderr, "ACO: failed to allocate registers during shader compilation\n"); + aco_err(ctx.program, "Failed to allocate registers during shader compilation."); abort(); } diff --git a/src/amd/compiler/aco_validate.cpp b/src/amd/compiler/aco_validate.cpp index e9cfe0b4355..b09cf2bb86b 100644 --- a/src/amd/compiler/aco_validate.cpp +++ b/src/amd/compiler/aco_validate.cpp @@ -29,37 +29,68 @@ namespace aco { -#ifndef NDEBUG -void perfwarn(bool cond, const char *msg, Instruction *instr) +static void aco_log(Program *program, const char *prefix, + const char *file, unsigned line, + const char *fmt, va_list args) { - if (cond) { - fprintf(stderr, "ACO performance warning: %s\n", msg); - if (instr) { - fprintf(stderr, "instruction: "); - aco_print_instr(instr, stderr); - fprintf(stderr, "\n"); - } + char *msg; - if (debug_flags & DEBUG_PERFWARN) - exit(1); - } + msg = ralloc_strdup(NULL, prefix); + + ralloc_asprintf_append(&msg, " In file %s:%u\n", file, line); + ralloc_asprintf_append(&msg, " "); + ralloc_vasprintf_append(&msg, fmt, args); + + /* TODO: log messages via callback if available too. */ + + fprintf(stderr, "%s\n", msg); + + ralloc_free(msg); +} + +void _aco_perfwarn(Program *program, const char *file, unsigned line, + const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + aco_log(program, "ACO PERFWARN:\n", file, line, fmt, args); + va_end(args); } -#endif -bool validate_ir(Program* program, FILE *output) +void _aco_err(Program *program, const char *file, unsigned line, + const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + aco_log(program, "ACO ERROR:\n", file, line, fmt, args); + va_end(args); +} + +bool validate_ir(Program* program) { bool is_valid = true; - auto check = [&output, &is_valid](bool check, const char * msg, aco::Instruction * instr) -> void { + auto check = [&program, &is_valid](bool check, const char * msg, aco::Instruction * instr) -> void { if (!check) { - fprintf(output, "%s: ", msg); - aco_print_instr(instr, output); - fprintf(output, "\n"); + char *out; + size_t outsize; + FILE *memf = open_memstream(&out, &outsize); + + fprintf(memf, "%s: ", msg); + aco_print_instr(instr, memf); + fclose(memf); + + aco_err(program, out); + free(out); + is_valid = false; } }; - auto check_block = [&output, &is_valid](bool check, const char * msg, aco::Block * block) -> void { + + auto check_block = [&program, &is_valid](bool check, const char * msg, aco::Block * block) -> void { if (!check) { - fprintf(output, "%s: BB%u\n", msg, block->index); + aco_err(program, "%s: BB%u", msg, block->index); is_valid = false; } }; @@ -455,25 +486,32 @@ struct Assignment { PhysReg reg; }; -bool ra_fail(FILE *output, Location loc, Location loc2, const char *fmt, ...) { +bool ra_fail(Program *program, Location loc, Location loc2, const char *fmt, ...) { va_list args; va_start(args, fmt); char msg[1024]; vsprintf(msg, fmt, args); va_end(args); - fprintf(stderr, "RA error found at instruction in BB%d:\n", loc.block->index); + char *out; + size_t outsize; + FILE *memf = open_memstream(&out, &outsize); + + fprintf(memf, "RA error found at instruction in BB%d:\n", loc.block->index); if (loc.instr) { - aco_print_instr(loc.instr, stderr); - fprintf(stderr, "\n%s", msg); + aco_print_instr(loc.instr, memf); + fprintf(memf, "\n%s", msg); } else { - fprintf(stderr, "%s", msg); + fprintf(memf, "%s", msg); } if (loc2.block) { - fprintf(stderr, " in BB%d:\n", loc2.block->index); - aco_print_instr(loc2.instr, stderr); + fprintf(memf, " in BB%d:\n", loc2.block->index); + aco_print_instr(loc2.instr, memf); } - fprintf(stderr, "\n\n"); + fprintf(memf, "\n\n"); + + aco_err(program, out); + free(out); return true; } @@ -610,7 +648,7 @@ unsigned get_subdword_bytes_written(Program *program, const aco_ptr } /* end namespace */ -bool validate_ra(Program *program, const struct radv_nir_compiler_options *options, FILE *output) { +bool validate_ra(Program *program, const struct radv_nir_compiler_options *options) { if (!(debug_flags & DEBUG_VALIDATE_RA)) return false; @@ -638,16 +676,16 @@ bool validate_ra(Program *program, const struct radv_nir_compiler_options *optio if (!op.isTemp()) continue; if (!op.isFixed()) - err |= ra_fail(output, loc, Location(), "Operand %d is not assigned a register", i); + err |= ra_fail(program, loc, Location(), "Operand %d is not assigned a register", i); if (assignments.count(op.tempId()) && assignments[op.tempId()].reg != op.physReg()) - err |= ra_fail(output, loc, assignments.at(op.tempId()).firstloc, "Operand %d has an inconsistent register assignment with instruction", i); + err |= ra_fail(program, loc, assignments.at(op.tempId()).firstloc, "Operand %d has an inconsistent register assignment with instruction", i); if ((op.getTemp().type() == RegType::vgpr && op.physReg().reg_b + op.bytes() > (256 + program->config->num_vgprs) * 4) || (op.getTemp().type() == RegType::sgpr && op.physReg() + op.size() > program->config->num_sgprs && op.physReg() < program->sgpr_limit)) - err |= ra_fail(output, loc, assignments.at(op.tempId()).firstloc, "Operand %d has an out-of-bounds register assignment", i); + err |= ra_fail(program, loc, assignments.at(op.tempId()).firstloc, "Operand %d has an out-of-bounds register assignment", i); if (op.physReg() == vcc && !program->needs_vcc) - err |= ra_fail(output, loc, Location(), "Operand %d fixed to vcc but needs_vcc=false", i); + err |= ra_fail(program, loc, Location(), "Operand %d fixed to vcc but needs_vcc=false", i); if (op.regClass().is_subdword() && !validate_subdword_operand(program->chip_class, instr, i)) - err |= ra_fail(output, loc, Location(), "Operand %d not aligned correctly", i); + err |= ra_fail(program, loc, Location(), "Operand %d not aligned correctly", i); if (!assignments[op.tempId()].firstloc.block) assignments[op.tempId()].firstloc = loc; if (!assignments[op.tempId()].defloc.block) @@ -659,16 +697,16 @@ bool validate_ra(Program *program, const struct radv_nir_compiler_options *optio if (!def.isTemp()) continue; if (!def.isFixed()) - err |= ra_fail(output, loc, Location(), "Definition %d is not assigned a register", i); + err |= ra_fail(program, loc, Location(), "Definition %d is not assigned a register", i); if (assignments[def.tempId()].defloc.block) - err |= ra_fail(output, loc, assignments.at(def.tempId()).defloc, "Temporary %%%d also defined by instruction", def.tempId()); + err |= ra_fail(program, loc, assignments.at(def.tempId()).defloc, "Temporary %%%d also defined by instruction", def.tempId()); if ((def.getTemp().type() == RegType::vgpr && def.physReg().reg_b + def.bytes() > (256 + program->config->num_vgprs) * 4) || (def.getTemp().type() == RegType::sgpr && def.physReg() + def.size() > program->config->num_sgprs && def.physReg() < program->sgpr_limit)) - err |= ra_fail(output, loc, assignments.at(def.tempId()).firstloc, "Definition %d has an out-of-bounds register assignment", i); + err |= ra_fail(program, loc, assignments.at(def.tempId()).firstloc, "Definition %d has an out-of-bounds register assignment", i); if (def.physReg() == vcc && !program->needs_vcc) - err |= ra_fail(output, loc, Location(), "Definition %d fixed to vcc but needs_vcc=false", i); + err |= ra_fail(program, loc, Location(), "Definition %d fixed to vcc but needs_vcc=false", i); if (def.regClass().is_subdword() && !validate_subdword_definition(program->chip_class, instr)) - err |= ra_fail(output, loc, Location(), "Definition %d not aligned correctly", i); + err |= ra_fail(program, loc, Location(), "Definition %d not aligned correctly", i); if (!assignments[def.tempId()].firstloc.block) assignments[def.tempId()].firstloc = loc; assignments[def.tempId()].defloc = loc; @@ -695,7 +733,7 @@ bool validate_ra(Program *program, const struct radv_nir_compiler_options *optio PhysReg reg = assignments.at(tmp.id()).reg; for (unsigned i = 0; i < tmp.bytes(); i++) { if (regs[reg.reg_b + i]) { - err |= ra_fail(output, loc, Location(), "Assignment of element %d of %%%d already taken by %%%d in live-out", i, tmp.id(), regs[reg.reg_b + i]); + err |= ra_fail(program, loc, Location(), "Assignment of element %d of %%%d already taken by %%%d in live-out", i, tmp.id(), regs[reg.reg_b + i]); } regs[reg.reg_b + i] = tmp.id(); } @@ -711,7 +749,7 @@ bool validate_ra(Program *program, const struct radv_nir_compiler_options *optio PhysReg reg = assignments.at(tmp.id()).reg; for (unsigned i = 0; i < tmp.bytes(); i++) { if (regs[reg.reg_b + i]) - err |= ra_fail(output, loc, Location(), "Assignment of element %d of %%%d already taken by %%%d in live-out", i, tmp.id(), regs[reg.reg_b + i]); + err |= ra_fail(program, loc, Location(), "Assignment of element %d of %%%d already taken by %%%d in live-out", i, tmp.id(), regs[reg.reg_b + i]); } live.emplace(tmp); } @@ -771,7 +809,7 @@ bool validate_ra(Program *program, const struct radv_nir_compiler_options *optio PhysReg reg = assignments.at(tmp.id()).reg; for (unsigned j = 0; j < tmp.bytes(); j++) { if (regs[reg.reg_b + j]) - err |= ra_fail(output, loc, assignments.at(regs[reg.reg_b + j]).defloc, "Assignment of element %d of %%%d already taken by %%%d from instruction", i, tmp.id(), regs[reg.reg_b + j]); + err |= ra_fail(program, loc, assignments.at(regs[reg.reg_b + j]).defloc, "Assignment of element %d of %%%d already taken by %%%d from instruction", i, tmp.id(), regs[reg.reg_b + j]); regs[reg.reg_b + j] = tmp.id(); } if (def.regClass().is_subdword() && def.bytes() < 4) { @@ -780,7 +818,7 @@ bool validate_ra(Program *program, const struct radv_nir_compiler_options *optio for (unsigned j = reg.byte() & ~(written - 1); j < written; j++) { unsigned written_reg = reg.reg() * 4u + j; if (regs[written_reg] && regs[written_reg] != def.tempId()) - err |= ra_fail(output, loc, assignments.at(regs[written_reg]).defloc, "Assignment of element %d of %%%d overwrites the full register taken by %%%d from instruction", i, tmp.id(), regs[written_reg]); + err |= ra_fail(program, loc, assignments.at(regs[written_reg]).defloc, "Assignment of element %d of %%%d overwrites the full register taken by %%%d from instruction", i, tmp.id(), regs[written_reg]); } } } diff --git a/src/amd/compiler/tests/helpers.cpp b/src/amd/compiler/tests/helpers.cpp index 3e2f697814e..295108e9879 100644 --- a/src/amd/compiler/tests/helpers.cpp +++ b/src/amd/compiler/tests/helpers.cpp @@ -146,7 +146,7 @@ void finish_validator_test() finish_program(program.get()); aco_print_program(program.get(), output); fprintf(output, "Validation results:\n"); - if (aco::validate_ir(program.get(), output)) + if (aco::validate_ir(program.get())) fprintf(output, "Validation passed\n"); else fprintf(output, "Validation failed\n"); @@ -155,12 +155,12 @@ void finish_validator_test() void finish_opt_test() { finish_program(program.get()); - if (!aco::validate_ir(program.get(), output)) { + if (!aco::validate_ir(program.get())) { fail_test("Validation before optimization failed"); return; } aco::optimize(program.get()); - if (!aco::validate_ir(program.get(), output)) { + if (!aco::validate_ir(program.get())) { fail_test("Validation after optimization failed"); return; } -- 2.30.2