aco: use no contract/reassoc instead of exact
Some checks are pending
macOS-CI / macOS-CI (dri) (push) Waiting to run
macOS-CI / macOS-CI (xlib) (push) Waiting to run

Reviewed-by: Rhys Perry <pendingchaos02@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/40872>
This commit is contained in:
Georg Lehmann 2026-04-09 18:06:33 +02:00 committed by Marge Bot
parent b0194d0416
commit 51ba9b956a
6 changed files with 40 additions and 19 deletions

View file

@ -213,7 +213,8 @@ public:
std::vector<aco_ptr<Instruction>> *instructions;
std::vector<aco_ptr<Instruction>>::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);

View file

@ -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;

View file

@ -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())

View file

@ -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<Instruction>& 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 is_rcp>
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];

View file

@ -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())

View file

@ -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);