diff --git a/src/amd/compiler/aco_optimizer.cpp b/src/amd/compiler/aco_optimizer.cpp index 8d88007bba7..c7f5c64ef56 100644 --- a/src/amd/compiler/aco_optimizer.cpp +++ b/src/amd/compiler/aco_optimizer.cpp @@ -1882,6 +1882,7 @@ label_instruction(opt_ctx& ctx, aco_ptr& instr) /* TODO: try to move the negate/abs modifier to the consumer instead */ bool uses_mods = instr->usesModifiers(); bool fp16 = instr->opcode == aco_opcode::v_mul_f16; + unsigned denorm_mode = fp16 ? ctx.fp_mode.denorm16_64 : ctx.fp_mode.denorm32; for (unsigned i = 0; i < 2; i++) { if (instr->operands[!i].isConstant() && instr->operands[i].isTemp()) { @@ -1910,8 +1911,12 @@ label_instruction(opt_ctx& ctx, aco_ptr& instr) ctx.info[instr->definitions[0].tempId()].set_abs(other); else if (!abs && neg && other.type() == RegType::vgpr) ctx.info[instr->definitions[0].tempId()].set_neg(other); - else if (!abs && !neg) - ctx.info[instr->definitions[0].tempId()].set_fcanonicalize(other); + else if (!abs && !neg) { + if (denorm_mode == fp_denorm_keep || ctx.info[other.id()].is_canonicalized()) + ctx.info[instr->definitions[0].tempId()].set_temp(other); + else + ctx.info[instr->definitions[0].tempId()].set_fcanonicalize(other); + } } else if (uses_mods || (instr->definitions[0].isSZPreserve() && instr->opcode != aco_opcode::v_mul_legacy_f32)) { continue; /* omod uses a legacy multiplication. */ @@ -1920,7 +1925,7 @@ label_instruction(opt_ctx& ctx, aco_ptr& instr) !instr->definitions[0].isInfPreserve()) || instr->opcode == aco_opcode::v_mul_legacy_f32)) { /* 0.0 */ ctx.info[instr->definitions[0].tempId()].set_constant(ctx.program->gfx_level, 0u); - } else if ((fp16 ? ctx.fp_mode.denorm16_64 : ctx.fp_mode.denorm32) != fp_denorm_flush) { + } else if (denorm_mode != fp_denorm_flush) { /* omod has no effect if denormals are enabled. */ continue; } else if (instr->operands[!i].constantValue() ==