diff --git a/src/amd/compiler/aco_builder_h.py b/src/amd/compiler/aco_builder_h.py index 7a270be1169..39a19b79216 100644 --- a/src/amd/compiler/aco_builder_h.py +++ b/src/amd/compiler/aco_builder_h.py @@ -213,7 +213,8 @@ public: std::vector> *instructions; std::vector>::iterator it; - bool is_precise = false; + bool is_no_contract = false; + bool is_no_reassoc = false; bool is_sz_preserve = false; bool is_inf_preserve = false; bool is_nan_preserve = false; @@ -225,7 +226,8 @@ public: Builder precise() const { Builder res = *this; - res.is_precise = true; + res.is_no_contract = true; + res.is_no_reassoc = true; return res; }; @@ -639,7 +641,8 @@ formats = [(f if len(f) == 5 else f + ('',)) for f in formats] Instruction* instr = create_instruction(opcode, (Format)(${'|'.join('(int)Format::%s' % f.name for f in formats)}), num_ops, ${num_definitions}); % for i in range(num_definitions): instr->definitions[${i}] = def${i}; - instr->definitions[${i}].setPrecise(is_precise); + instr->definitions[${i}].setNoContract(is_no_contract); + instr->definitions[${i}].setNoReassoc(is_no_reassoc); instr->definitions[${i}].setSZPreserve(is_sz_preserve); instr->definitions[${i}].setInfPreserve(is_inf_preserve); instr->definitions[${i}].setNaNPreserve(is_nan_preserve); diff --git a/src/amd/compiler/aco_ir.h b/src/amd/compiler/aco_ir.h index 2969bf852e7..05882b2c329 100644 --- a/src/amd/compiler/aco_ir.h +++ b/src/amd/compiler/aco_ir.h @@ -944,8 +944,9 @@ private: class Definition final { public: constexpr Definition() - : temp(Temp(0, s1)), reg_(0), isFixed_(0), isPrecolored_(0), isKill_(0), isPrecise_(0), - isInfPreserve_(0), isNaNPreserve_(0), isSZPreserve_(0), isNUW_(0), isNoCSE_(0) + : temp(Temp(0, s1)), reg_(0), isFixed_(0), isPrecolored_(0), isKill_(0), isNoContract_(0), + isNoReassoc_(0), isInfPreserve_(0), isNaNPreserve_(0), isSZPreserve_(0), isNUW_(0), + isNoCSE_(0) {} explicit Definition(Temp tmp) noexcept : temp(tmp) {} explicit Definition(PhysReg reg, RegClass type) noexcept : temp(Temp(0, type)) { setFixed(reg); } @@ -988,9 +989,13 @@ public: constexpr bool isKill() const noexcept { return isKill_; } - constexpr void setPrecise(bool precise) noexcept { isPrecise_ = precise; } + constexpr void setNoContract(bool no_contract) noexcept { isNoContract_ = no_contract; } - constexpr bool isPrecise() const noexcept { return isPrecise_; } + constexpr bool isNoContract() const noexcept { return isNoContract_; } + + constexpr void setNoReassoc(bool no_reassoc) noexcept { isNoReassoc_ = no_reassoc; } + + constexpr bool isNoReassoc() const noexcept { return isNoReassoc_; } constexpr void setInfPreserve(bool inf_preserve) noexcept { isInfPreserve_ = inf_preserve; } @@ -1021,7 +1026,8 @@ private: uint8_t isFixed_ : 1; uint8_t isPrecolored_ : 1; uint8_t isKill_ : 1; - uint8_t isPrecise_ : 1; + uint8_t isNoContract_ : 1; + uint8_t isNoReassoc_ : 1; uint8_t isInfPreserve_ : 1; uint8_t isNaNPreserve_ : 1; uint8_t isSZPreserve_ : 1; diff --git a/src/amd/compiler/aco_opt_value_numbering.cpp b/src/amd/compiler/aco_opt_value_numbering.cpp index 9cdb121aee5..414ded1c0d1 100644 --- a/src/amd/compiler/aco_opt_value_numbering.cpp +++ b/src/amd/compiler/aco_opt_value_numbering.cpp @@ -399,8 +399,10 @@ process_block(vn_ctx& ctx, Block& block) assert(instr->definitions[i].regClass() == orig_instr->definitions[i].regClass()); assert(instr->definitions[i].isTemp()); ctx.renames[instr->definitions[i].tempId()] = orig_instr->definitions[i].getTemp(); - if (instr->definitions[i].isPrecise()) - orig_instr->definitions[i].setPrecise(true); + if (instr->definitions[i].isNoContract()) + orig_instr->definitions[i].setNoContract(true); + if (instr->definitions[i].isNoReassoc()) + orig_instr->definitions[i].setNoReassoc(true); if (instr->definitions[i].isSZPreserve()) orig_instr->definitions[i].setSZPreserve(true); if (instr->definitions[i].isInfPreserve()) diff --git a/src/amd/compiler/aco_optimizer.cpp b/src/amd/compiler/aco_optimizer.cpp index 052f032549d..985a36f475a 100644 --- a/src/amd/compiler/aco_optimizer.cpp +++ b/src/amd/compiler/aco_optimizer.cpp @@ -869,7 +869,7 @@ alu_opt_info_is_valid(opt_ctx& ctx, alu_opt_info& info) return false; break; case aco_opcode::v_mad_f32: - if (ctx.program->dev.fused_mad_mix && info.defs[0].isPrecise()) + if (ctx.program->dev.fused_mad_mix && info.defs[0].isNoContract()) return false; break; default: return false; @@ -3464,8 +3464,10 @@ match_and_apply_patterns(opt_ctx& ctx, alu_opt_info& info, new_info.opcode = pattern.res_opcode; - if (op_instr.defs[0].isPrecise()) - new_info.defs[0].setPrecise(true); + if (op_instr.defs[0].isNoContract()) + new_info.defs[0].setNoContract(true); + if (op_instr.defs[0].isNoReassoc()) + new_info.defs[0].setNoReassoc(true); if (op_instr.defs[0].isNaNPreserve()) new_info.defs[0].setNaNPreserve(true); if (op_instr.defs[0].isInfPreserve()) @@ -3999,7 +4001,7 @@ apply_output(opt_ctx& ctx, aco_ptr& instr) bool create_fma_cb(opt_ctx& ctx, alu_opt_info& info) { - if (!info.defs[0].isPrecise()) + if (!info.defs[0].isNoContract()) return true; aco_type type = instr_info.alu_opcode_infos[(int)info.opcode].def_types[0]; @@ -4066,14 +4068,14 @@ can_reassoc_omod(opt_ctx& ctx, const alu_opt_info& info, unsigned bit_size) bool no_signed_zero = info.opcode == aco_opcode::v_mul_legacy_f32 || !info.defs[0].isSZPreserve(); - return no_signed_zero && !info.omod && !info.defs[0].isPrecise() && denorm == fp_denorm_flush; + return no_signed_zero && !info.omod && !info.defs[0].isNoReassoc() && denorm == fp_denorm_flush; } template bool reassoc_omod_cb(opt_ctx& ctx, alu_opt_info& info) { - if (info.defs[0].isPrecise()) + if (info.defs[0].isNoReassoc()) return false; aco_type type = instr_info.alu_opcode_infos[(int)info.opcode].def_types[0]; diff --git a/src/amd/compiler/aco_print_ir.cpp b/src/amd/compiler/aco_print_ir.cpp index a7afa2c24e1..76649085ee6 100644 --- a/src/amd/compiler/aco_print_ir.cpp +++ b/src/amd/compiler/aco_print_ir.cpp @@ -148,8 +148,15 @@ print_definition(const Definition* definition, FILE* output, unsigned flags) { if (!(flags & print_no_ssa)) print_reg_class(definition->regClass(), output); - if (definition->isPrecise()) - fprintf(output, "(precise)"); + + if (definition->isNoContract() || definition->isNoReassoc()) { + if (!definition->isNoContract()) + fprintf(output, "(no-reassoc)"); + else if (!definition->isNoReassoc()) + fprintf(output, "(no-contract)"); + else + fprintf(output, "(precise)"); + } if (definition->isInfPreserve() || definition->isNaNPreserve() || definition->isSZPreserve()) { fprintf(output, "("); if (definition->isSZPreserve()) diff --git a/src/amd/compiler/instruction_selection/aco_select_nir_alu.cpp b/src/amd/compiler/instruction_selection/aco_select_nir_alu.cpp index 96d342f1a2d..9aaa64a3f7f 100644 --- a/src/amd/compiler/instruction_selection/aco_select_nir_alu.cpp +++ b/src/amd/compiler/instruction_selection/aco_select_nir_alu.cpp @@ -18,7 +18,8 @@ static Builder create_alu_builder(isel_context* ctx, nir_alu_instr* instr) { Builder bld(ctx->program, ctx->block); - bld.is_precise = nir_alu_instr_is_exact(instr); + bld.is_no_contract = nir_alu_instr_no_contract(instr); + bld.is_no_reassoc = nir_alu_instr_no_reassoc(instr); bld.is_sz_preserve = nir_alu_instr_is_signed_zero_preserve(instr); bld.is_inf_preserve = nir_alu_instr_is_inf_preserve(instr); bld.is_nan_preserve = nir_alu_instr_is_nan_preserve(instr);