diff --git a/src/amd/compiler/aco_optimizer.cpp b/src/amd/compiler/aco_optimizer.cpp index b4baa807304..ba398dc35c9 100644 --- a/src/amd/compiler/aco_optimizer.cpp +++ b/src/amd/compiler/aco_optimizer.cpp @@ -2130,163 +2130,6 @@ follow_operand(opt_ctx& ctx, Operand op, bool ignore_uses = false) return instr; } -/* s_or_b64(neq(a, a), neq(b, b)) -> v_cmp_u_f32(a, b) - * s_and_b64(eq(a, a), eq(b, b)) -> v_cmp_o_f32(a, b) */ -bool -combine_ordering_test(opt_ctx& ctx, aco_ptr& instr) -{ - if (instr->definitions[0].regClass() != ctx.program->lane_mask) - return false; - if (instr->definitions[1].isTemp() && ctx.uses[instr->definitions[1].tempId()]) - return false; - - bool is_or = instr->opcode == aco_opcode::s_or_b64 || instr->opcode == aco_opcode::s_or_b32; - - bitarray8 opsel = 0; - Instruction* op_instr[2]; - Temp op[2]; - - unsigned bitsize = 0; - for (unsigned i = 0; i < 2; i++) { - op_instr[i] = follow_operand(ctx, instr->operands[i], true); - if (!op_instr[i]) - return false; - - aco_opcode expected_cmp = is_or ? aco_opcode::v_cmp_neq_f32 : aco_opcode::v_cmp_eq_f32; - unsigned op_bitsize = get_cmp_bitsize(op_instr[i]->opcode); - - if (get_f32_cmp(op_instr[i]->opcode) != expected_cmp) - return false; - if (bitsize && op_bitsize != bitsize) - return false; - if (!op_instr[i]->operands[0].isTemp() || !op_instr[i]->operands[1].isTemp()) - return false; - - if (op_instr[i]->isSDWA() || op_instr[i]->isDPP()) - return false; - - VALU_instruction& valu = op_instr[i]->valu(); - if (valu.neg[0] != valu.neg[1] || valu.abs[0] != valu.abs[1] || - valu.opsel[0] != valu.opsel[1]) - return false; - opsel[i] = valu.opsel[0]; - - Temp op0 = op_instr[i]->operands[0].getTemp(); - Temp op1 = op_instr[i]->operands[1].getTemp(); - if (original_temp_id(ctx, op0) != original_temp_id(ctx, op1)) - return false; - - op[i] = op1; - bitsize = op_bitsize; - } - - if (op[1].type() == RegType::sgpr) { - std::swap(op[0], op[1]); - opsel[0].swap(opsel[1]); - } - unsigned num_sgprs = (op[0].type() == RegType::sgpr) + (op[1].type() == RegType::sgpr); - if (num_sgprs > (ctx.program->gfx_level >= GFX10 ? 2 : 1)) - return false; - - aco_opcode new_op = aco_opcode::num_opcodes; - switch (bitsize) { - case 16: new_op = is_or ? aco_opcode::v_cmp_u_f16 : aco_opcode::v_cmp_o_f16; break; - case 32: new_op = is_or ? aco_opcode::v_cmp_u_f32 : aco_opcode::v_cmp_o_f32; break; - case 64: new_op = is_or ? aco_opcode::v_cmp_u_f64 : aco_opcode::v_cmp_o_f64; break; - } - bool needs_vop3 = num_sgprs > 1 || (opsel[0] && op[0].type() != RegType::vgpr); - Instruction* new_instr = - create_instruction(new_op, needs_vop3 ? asVOP3(Format::VOPC) : Format::VOPC, 2, 1); - - new_instr->valu().opsel = opsel; - new_instr->operands[0] = copy_operand(ctx, Operand(op[0])); - new_instr->operands[1] = copy_operand(ctx, Operand(op[1])); - new_instr->definitions[0] = instr->definitions[0]; - new_instr->pass_flags = instr->pass_flags; - - decrease_uses(ctx, op_instr[0]); - decrease_uses(ctx, op_instr[1]); - - ctx.info[instr->definitions[0].tempId()].label = 0; - ctx.info[instr->definitions[0].tempId()].set_vopc(new_instr); - - instr.reset(new_instr); - - return true; -} - -/* s_or_b64(v_cmp_u_f32(a, b), cmp(a, b)) -> get_unordered(cmp)(a, b) - * s_and_b64(v_cmp_o_f32(a, b), cmp(a, b)) -> get_ordered(cmp)(a, b) */ -bool -combine_comparison_ordering(opt_ctx& ctx, aco_ptr& instr) -{ - if (instr->definitions[0].regClass() != ctx.program->lane_mask) - return false; - if (instr->definitions[1].isTemp() && ctx.uses[instr->definitions[1].tempId()]) - return false; - - bool is_or = instr->opcode == aco_opcode::s_or_b64 || instr->opcode == aco_opcode::s_or_b32; - aco_opcode expected_nan_test = is_or ? aco_opcode::v_cmp_u_f32 : aco_opcode::v_cmp_o_f32; - - Instruction* nan_test = follow_operand(ctx, instr->operands[0], true); - Instruction* cmp = follow_operand(ctx, instr->operands[1], true); - if (!nan_test || !cmp) - return false; - if (nan_test->isSDWA() || cmp->isSDWA()) - return false; - - if (get_f32_cmp(cmp->opcode) == expected_nan_test) - std::swap(nan_test, cmp); - else if (get_f32_cmp(nan_test->opcode) != expected_nan_test) - return false; - - if (!is_fp_cmp(cmp->opcode) || get_cmp_bitsize(cmp->opcode) != get_cmp_bitsize(nan_test->opcode)) - return false; - - if (!nan_test->operands[0].isTemp() || !nan_test->operands[1].isTemp()) - return false; - if (!cmp->operands[0].isTemp() || !cmp->operands[1].isTemp()) - return false; - - unsigned prop_cmp0 = original_temp_id(ctx, cmp->operands[0].getTemp()); - unsigned prop_cmp1 = original_temp_id(ctx, cmp->operands[1].getTemp()); - unsigned prop_nan0 = original_temp_id(ctx, nan_test->operands[0].getTemp()); - unsigned prop_nan1 = original_temp_id(ctx, nan_test->operands[1].getTemp()); - VALU_instruction& cmp_valu = cmp->valu(); - VALU_instruction& nan_valu = nan_test->valu(); - if ((prop_cmp0 != prop_nan0 || cmp_valu.opsel[0] != nan_valu.opsel[0]) && - (prop_cmp0 != prop_nan1 || cmp_valu.opsel[0] != nan_valu.opsel[1])) - return false; - if ((prop_cmp1 != prop_nan0 || cmp_valu.opsel[1] != nan_valu.opsel[0]) && - (prop_cmp1 != prop_nan1 || cmp_valu.opsel[1] != nan_valu.opsel[1])) - return false; - if (prop_cmp0 == prop_cmp1 && cmp_valu.opsel[0] == cmp_valu.opsel[1]) - return false; - - aco_opcode new_op = is_or ? get_unordered(cmp->opcode) : get_ordered(cmp->opcode); - Instruction* new_instr = - create_instruction(new_op, cmp->isVOP3() ? asVOP3(Format::VOPC) : Format::VOPC, 2, 1); - new_instr->valu().neg = cmp_valu.neg; - new_instr->valu().abs = cmp_valu.abs; - new_instr->valu().clamp = cmp_valu.clamp; - new_instr->valu().omod = cmp_valu.omod; - new_instr->valu().opsel = cmp_valu.opsel; - new_instr->operands[0] = copy_operand(ctx, cmp->operands[0]); - new_instr->operands[1] = copy_operand(ctx, cmp->operands[1]); - new_instr->definitions[0] = instr->definitions[0]; - new_instr->pass_flags = instr->pass_flags; - - decrease_uses(ctx, nan_test); - decrease_uses(ctx, cmp); - - ctx.info[instr->definitions[0].tempId()].label = 0; - ctx.info[instr->definitions[0].tempId()].set_vopc(new_instr); - - instr.reset(new_instr); - - return true; -} - /* Optimize v_cmp of constant with subgroup invocation to a constant mask. * Ideally, we can trade v_cmp for a constant (or literal). * In a less ideal case, we trade v_cmp for a SALU instruction, which is still a win. @@ -2384,101 +2227,6 @@ is_operand_constant(opt_ctx& ctx, Operand op, unsigned bit_size, uint64_t* value return false; } -bool -is_constant_nan(uint64_t value, unsigned bit_size) -{ - if (bit_size == 16) - return ((value >> 10) & 0x1f) == 0x1f && (value & 0x3ff); - else if (bit_size == 32) - return ((value >> 23) & 0xff) == 0xff && (value & 0x7fffff); - else - return ((value >> 52) & 0x7ff) == 0x7ff && (value & 0xfffffffffffff); -} - -/* s_or_b64(v_cmp_neq_f32(a, a), cmp(a, #b)) and b is not NaN -> get_unordered(cmp)(a, b) - * s_and_b64(v_cmp_eq_f32(a, a), cmp(a, #b)) and b is not NaN -> get_ordered(cmp)(a, b) */ -bool -combine_constant_comparison_ordering(opt_ctx& ctx, aco_ptr& instr) -{ - if (instr->definitions[0].regClass() != ctx.program->lane_mask) - return false; - if (instr->definitions[1].isTemp() && ctx.uses[instr->definitions[1].tempId()]) - return false; - - bool is_or = instr->opcode == aco_opcode::s_or_b64 || instr->opcode == aco_opcode::s_or_b32; - - Instruction* nan_test = follow_operand(ctx, instr->operands[0], true); - Instruction* cmp = follow_operand(ctx, instr->operands[1], true); - - if (!nan_test || !cmp || nan_test->isSDWA() || cmp->isSDWA() || nan_test->isDPP() || - cmp->isDPP()) - return false; - - aco_opcode expected_nan_test = is_or ? aco_opcode::v_cmp_neq_f32 : aco_opcode::v_cmp_eq_f32; - if (get_f32_cmp(cmp->opcode) == expected_nan_test) - std::swap(nan_test, cmp); - else if (get_f32_cmp(nan_test->opcode) != expected_nan_test) - return false; - - unsigned bit_size = get_cmp_bitsize(cmp->opcode); - if (!is_fp_cmp(cmp->opcode) || get_cmp_bitsize(nan_test->opcode) != bit_size) - return false; - - if (!nan_test->operands[0].isTemp() || !nan_test->operands[1].isTemp()) - return false; - if (!cmp->operands[0].isTemp() && !cmp->operands[1].isTemp()) - return false; - - unsigned prop_nan0 = original_temp_id(ctx, nan_test->operands[0].getTemp()); - unsigned prop_nan1 = original_temp_id(ctx, nan_test->operands[1].getTemp()); - if (prop_nan0 != prop_nan1) - return false; - - VALU_instruction& vop3 = nan_test->valu(); - if (vop3.neg[0] != vop3.neg[1] || vop3.abs[0] != vop3.abs[1] || vop3.opsel[0] != vop3.opsel[1]) - return false; - - int constant_operand = -1; - for (unsigned i = 0; i < 2; i++) { - if (cmp->operands[i].isTemp() && - original_temp_id(ctx, cmp->operands[i].getTemp()) == prop_nan0 && - cmp->valu().opsel[i] == nan_test->valu().opsel[0]) { - constant_operand = !i; - break; - } - } - if (constant_operand == -1) - return false; - - uint64_t constant_value; - if (!is_operand_constant(ctx, cmp->operands[constant_operand], bit_size, &constant_value)) - return false; - if (is_constant_nan(constant_value >> (cmp->valu().opsel[constant_operand] * 16), bit_size)) - return false; - - aco_opcode new_op = is_or ? get_unordered(cmp->opcode) : get_ordered(cmp->opcode); - Instruction* new_instr = create_instruction(new_op, cmp->format, 2, 1); - new_instr->valu().neg = cmp->valu().neg; - new_instr->valu().abs = cmp->valu().abs; - new_instr->valu().clamp = cmp->valu().clamp; - new_instr->valu().omod = cmp->valu().omod; - new_instr->valu().opsel = cmp->valu().opsel; - new_instr->operands[0] = copy_operand(ctx, cmp->operands[0]); - new_instr->operands[1] = copy_operand(ctx, cmp->operands[1]); - new_instr->definitions[0] = instr->definitions[0]; - new_instr->pass_flags = instr->pass_flags; - - decrease_uses(ctx, nan_test); - decrease_uses(ctx, cmp); - - ctx.info[instr->definitions[0].tempId()].label = 0; - ctx.info[instr->definitions[0].tempId()].set_vopc(new_instr); - - instr.reset(new_instr); - - return true; -} - /* s_not(cmp(a, b)) -> get_inverse(cmp)(a, b) */ bool combine_inverse_comparison(opt_ctx& ctx, aco_ptr& instr) @@ -4455,11 +4203,7 @@ combine_instruction(opt_ctx& ctx, aco_ptr& instr) combine_inverse_comparison(ctx, instr); } else if (instr->opcode == aco_opcode::s_and_b32 || instr->opcode == aco_opcode::s_or_b32 || instr->opcode == aco_opcode::s_and_b64 || instr->opcode == aco_opcode::s_or_b64) { - if (combine_ordering_test(ctx, instr)) { - } else if (combine_comparison_ordering(ctx, instr)) { - } else if (combine_constant_comparison_ordering(ctx, instr)) { - } else if (combine_salu_n2(ctx, instr)) { - } + combine_salu_n2(ctx, instr); } else if (instr->opcode == aco_opcode::s_abs_i32) { combine_sabsdiff(ctx, instr); } else if (instr->opcode == aco_opcode::v_and_b32) { diff --git a/src/amd/compiler/tests/test_optimizer.cpp b/src/amd/compiler/tests/test_optimizer.cpp index 3cc7f67fa15..c5230075829 100644 --- a/src/amd/compiler/tests/test_optimizer.cpp +++ b/src/amd/compiler/tests/test_optimizer.cpp @@ -540,139 +540,6 @@ BEGIN_TEST(optimize.clamp) } END_TEST -BEGIN_TEST(optimize.const_comparison_ordering) - //>> v1: %a, v1: %b, v2: %c, v1: %d = p_startpgm - if (!setup_cs("v1 v1 v2 v1", GFX9)) - return; - - /* optimize to unordered comparison */ - //! s2: %res0 = v_cmp_nge_f32 4.0, %a - //! p_unit_test 0, %res0 - writeout(0, bld.sop2(aco_opcode::s_or_b64, bld.def(bld.lm), bld.def(s1, scc), - bld.vopc(aco_opcode::v_cmp_neq_f32, bld.def(bld.lm), inputs[0], inputs[0]), - bld.vopc(aco_opcode::v_cmp_lt_f32, bld.def(bld.lm), - Operand::c32(0x40800000u), inputs[0]))); - - //! s2: %res1 = v_cmp_nge_f32 4.0, %a - //! p_unit_test 1, %res1 - writeout(1, bld.sop2(aco_opcode::s_or_b64, bld.def(bld.lm), bld.def(s1, scc), - bld.vopc(aco_opcode::v_cmp_neq_f32, bld.def(bld.lm), inputs[0], inputs[0]), - bld.vopc(aco_opcode::v_cmp_nge_f32, bld.def(bld.lm), - Operand::c32(0x40800000u), inputs[0]))); - - //! s2: %res2 = v_cmp_nge_f32 0x40a00000, %a - //! p_unit_test 2, %res2 - writeout(2, bld.sop2(aco_opcode::s_or_b64, bld.def(bld.lm), bld.def(s1, scc), - bld.vopc(aco_opcode::v_cmp_neq_f32, bld.def(bld.lm), inputs[0], inputs[0]), - bld.vopc(aco_opcode::v_cmp_lt_f32, bld.def(bld.lm), - bld.copy(bld.def(v1), Operand::c32(0x40a00000u)), inputs[0]))); - - /* optimize to ordered comparison */ - //! s2: %res3 = v_cmp_lt_f32 4.0, %a - //! p_unit_test 3, %res3 - writeout(3, bld.sop2(aco_opcode::s_and_b64, bld.def(bld.lm), bld.def(s1, scc), - bld.vopc(aco_opcode::v_cmp_eq_f32, bld.def(bld.lm), inputs[0], inputs[0]), - bld.vopc(aco_opcode::v_cmp_nge_f32, bld.def(bld.lm), - Operand::c32(0x40800000u), inputs[0]))); - - //! s2: %res4 = v_cmp_lt_f32 4.0, %a - //! p_unit_test 4, %res4 - writeout(4, bld.sop2(aco_opcode::s_and_b64, bld.def(bld.lm), bld.def(s1, scc), - bld.vopc(aco_opcode::v_cmp_eq_f32, bld.def(bld.lm), inputs[0], inputs[0]), - bld.vopc(aco_opcode::v_cmp_lt_f32, bld.def(bld.lm), - Operand::c32(0x40800000u), inputs[0]))); - - //! s2: %res5 = v_cmp_lt_f32 0x40a00000, %a - //! p_unit_test 5, %res5 - writeout(5, bld.sop2(aco_opcode::s_and_b64, bld.def(bld.lm), bld.def(s1, scc), - bld.vopc(aco_opcode::v_cmp_eq_f32, bld.def(bld.lm), inputs[0], inputs[0]), - bld.vopc(aco_opcode::v_cmp_nge_f32, bld.def(bld.lm), - bld.copy(bld.def(v1), Operand::c32(0x40a00000u)), inputs[0]))); - - /* similar but unoptimizable expressions */ - //! s2: %tmp6_0 = v_cmp_lt_f32 4.0, %a - //! s2: %tmp6_1 = v_cmp_neq_f32 %a, %a - //! s2: %res6, s1: %_:scc = s_and_b64 %tmp6_1, %tmp6_0 - //! p_unit_test 6, %res6 - Temp src1 = - bld.vopc(aco_opcode::v_cmp_lt_f32, bld.def(bld.lm), Operand::c32(0x40800000u), inputs[0]); - Temp src0 = bld.vopc(aco_opcode::v_cmp_neq_f32, bld.def(bld.lm), inputs[0], inputs[0]); - writeout(6, bld.sop2(aco_opcode::s_and_b64, bld.def(bld.lm), bld.def(s1, scc), src0, src1)); - - //! s2: %tmp7_0 = v_cmp_nge_f32 4.0, %a - //! s2: %tmp7_1 = v_cmp_eq_f32 %a, %a - //! s2: %res7, s1: %_:scc = s_or_b64 %tmp7_1, %tmp7_0 - //! p_unit_test 7, %res7 - src1 = - bld.vopc(aco_opcode::v_cmp_nge_f32, bld.def(bld.lm), Operand::c32(0x40800000u), inputs[0]); - src0 = bld.vopc(aco_opcode::v_cmp_eq_f32, bld.def(bld.lm), inputs[0], inputs[0]); - writeout(7, bld.sop2(aco_opcode::s_or_b64, bld.def(bld.lm), bld.def(s1, scc), src0, src1)); - - //! s2: %tmp8_0 = v_cmp_lt_f32 4.0, %d - //! s2: %tmp8_1 = v_cmp_neq_f32 %a, %a - //! s2: %res8, s1: %_:scc = s_or_b64 %tmp8_1, %tmp8_0 - //! p_unit_test 8, %res8 - src1 = bld.vopc(aco_opcode::v_cmp_lt_f32, bld.def(bld.lm), Operand::c32(0x40800000u), inputs[3]); - src0 = bld.vopc(aco_opcode::v_cmp_neq_f32, bld.def(bld.lm), inputs[0], inputs[0]); - writeout(8, bld.sop2(aco_opcode::s_or_b64, bld.def(bld.lm), bld.def(s1, scc), src0, src1)); - - //! s2: %tmp9_0 = v_cmp_lt_f32 4.0, %a - //! s2: %tmp9_1 = v_cmp_neq_f32 %a, %d - //! s2: %res9, s1: %_:scc = s_or_b64 %tmp9_1, %tmp9_0 - //! p_unit_test 9, %res9 - src1 = bld.vopc(aco_opcode::v_cmp_lt_f32, bld.def(bld.lm), Operand::c32(0x40800000u), inputs[0]); - src0 = bld.vopc(aco_opcode::v_cmp_neq_f32, bld.def(bld.lm), inputs[0], inputs[3]); - writeout(9, bld.sop2(aco_opcode::s_or_b64, bld.def(bld.lm), bld.def(s1, scc), src0, src1)); - - /* bit sizes */ - //! s2: %res10 = v_cmp_nge_f16 4.0, %b - //! p_unit_test 10, %res10 - Temp input1_16 = - bld.pseudo(aco_opcode::p_extract_vector, bld.def(v2b), inputs[1], Operand::zero()); - writeout(10, bld.sop2(aco_opcode::s_or_b64, bld.def(bld.lm), bld.def(s1, scc), - bld.vopc(aco_opcode::v_cmp_neq_f16, bld.def(bld.lm), input1_16, input1_16), - bld.vopc(aco_opcode::v_cmp_lt_f16, bld.def(bld.lm), Operand::c16(0x4400u), - input1_16))); - - //! s2: %res11 = v_cmp_nge_f64 4.0, %c - //! p_unit_test 11, %res11 - writeout(11, bld.sop2(aco_opcode::s_or_b64, bld.def(bld.lm), bld.def(s1, scc), - bld.vopc(aco_opcode::v_cmp_neq_f64, bld.def(bld.lm), inputs[2], inputs[2]), - bld.vopc(aco_opcode::v_cmp_lt_f64, bld.def(bld.lm), - Operand::c64(0x4010000000000000u), inputs[2]))); - - /* NaN */ - uint16_t nan16 = 0x7e00; - uint32_t nan32 = 0x7fc00000; - uint64_t nan64 = 0xffffffffffffffffllu; - - //! s2: %tmp12_0 = v_cmp_lt_f16 0x7e00, %a - //! s2: %tmp12_1 = v_cmp_neq_f16 %a, %a - //! s2: %res12, s1: %_:scc = s_or_b64 %tmp12_1, %tmp12_0 - //! p_unit_test 12, %res12 - src1 = bld.vopc(aco_opcode::v_cmp_lt_f16, bld.def(bld.lm), Operand::c16(nan16), inputs[0]); - src0 = bld.vopc(aco_opcode::v_cmp_neq_f16, bld.def(bld.lm), inputs[0], inputs[0]); - writeout(12, bld.sop2(aco_opcode::s_or_b64, bld.def(bld.lm), bld.def(s1, scc), src0, src1)); - - //! s2: %tmp13_0 = v_cmp_lt_f32 0x7fc00000, %a - //! s2: %tmp13_1 = v_cmp_neq_f32 %a, %a - //! s2: %res13, s1: %_:scc = s_or_b64 %tmp13_1, %tmp13_0 - //! p_unit_test 13, %res13 - src1 = bld.vopc(aco_opcode::v_cmp_lt_f32, bld.def(bld.lm), Operand::c32(nan32), inputs[0]); - src0 = bld.vopc(aco_opcode::v_cmp_neq_f32, bld.def(bld.lm), inputs[0], inputs[0]); - writeout(13, bld.sop2(aco_opcode::s_or_b64, bld.def(bld.lm), bld.def(s1, scc), src0, src1)); - - //! s2: %tmp14_0 = v_cmp_lt_f64 -1, %c - //! s2: %tmp14_1 = v_cmp_neq_f64 %c, %c - //! s2: %res14, s1: %_:scc = s_or_b64 %tmp14_1, %tmp14_0 - //! p_unit_test 14, %res14 - src1 = bld.vopc(aco_opcode::v_cmp_lt_f64, bld.def(bld.lm), Operand::c64(nan64), inputs[2]); - src0 = bld.vopc(aco_opcode::v_cmp_neq_f64, bld.def(bld.lm), inputs[2], inputs[2]); - writeout(14, bld.sop2(aco_opcode::s_or_b64, bld.def(bld.lm), bld.def(s1, scc), src0, src1)); - - finish_opt_test(); -END_TEST - BEGIN_TEST(optimize.add3) //>> v1: %a, v1: %b, v1: %c = p_startpgm if (!setup_cs("v1 v1 v1", GFX9)) @@ -2026,115 +1893,6 @@ BEGIN_TEST(optimize.apply_sgpr_swap_opsel) finish_opt_test(); END_TEST -BEGIN_TEST(optimize.combine_comparison_ordering) - //>> v1: %a, v1: %b, v1: %c = p_startpgm - if (!setup_cs("v1 v1 v1", GFX11)) - return; - - Temp a = inputs[0]; - Temp b = inputs[1]; - Temp c = inputs[2]; - - Temp a_unordered = bld.vopc(aco_opcode::v_cmp_neq_f32, bld.def(bld.lm), a, a); - Temp b_unordered = bld.vopc(aco_opcode::v_cmp_neq_f32, bld.def(bld.lm), b, b); - Temp unordered = - bld.sop2(Builder::s_or, bld.def(bld.lm), bld.def(bld.lm, scc), a_unordered, b_unordered); - - Temp a_lt_a = bld.vopc(aco_opcode::v_cmp_lt_f32, bld.def(bld.lm), a, a); - Temp unordered_cmp = - bld.sop2(Builder::s_or, bld.def(bld.lm), bld.def(bld.lm, scc), unordered, a_lt_a); - - //! s2: %res0_unordered = v_cmp_u_f32 %a, %b - //! s2: %res0_cmp = v_cmp_lt_f32 %a, %a - //! s2: %res0, s2: %_:scc = s_or_b64 %res0_unordered, %res0_cmp - //! p_unit_test 0, %res0 - writeout(0, unordered_cmp); - - Temp c_hi = bld.pseudo(aco_opcode::p_extract_vector, bld.def(v2b), c, Operand::c32(1)); - - Temp c_unordered = bld.vopc(aco_opcode::v_cmp_neq_f16, bld.def(bld.lm), c, c); - Temp c_hi_unordered = bld.vopc(aco_opcode::v_cmp_neq_f16, bld.def(bld.lm), c_hi, c_hi); - unordered = - bld.sop2(Builder::s_or, bld.def(bld.lm), bld.def(bld.lm, scc), c_unordered, c_hi_unordered); - - Temp c_lt_c_hi = bld.vopc(aco_opcode::v_cmp_lt_f16, bld.def(bld.lm), c, c_hi); - unordered_cmp = - bld.sop2(Builder::s_or, bld.def(bld.lm), bld.def(bld.lm, scc), unordered, c_lt_c_hi); - - //! s2: %res1 = v_cmp_nge_f16 %c, hi(%c) - //! p_unit_test 1, %res1 - writeout(1, unordered_cmp); - - finish_opt_test(); -END_TEST - -BEGIN_TEST(optimize.combine_comparison_ordering_opsel) - //>> v1: %a, v2b: %b = p_startpgm - if (!setup_cs("v1 v2b", GFX11)) - return; - - Temp a = inputs[0]; - Temp b = inputs[1]; - - Temp a_hi = bld.pseudo(aco_opcode::p_extract_vector, bld.def(v2b), a, Operand::c32(1)); - - Temp ahi_unordered = bld.vopc(aco_opcode::v_cmp_neq_f16, bld.def(bld.lm), a_hi, a_hi); - Temp b_unordered = bld.vopc(aco_opcode::v_cmp_neq_f16, bld.def(bld.lm), b, b); - Temp unordered = - bld.sop2(Builder::s_or, bld.def(bld.lm), bld.def(bld.lm, scc), ahi_unordered, b_unordered); - - Temp ahi_lt_b = bld.vopc(aco_opcode::v_cmp_lt_f16, bld.def(bld.lm), a_hi, b); - Temp unordered_cmp = - bld.sop2(Builder::s_or, bld.def(bld.lm), bld.def(bld.lm, scc), unordered, ahi_lt_b); - - //! s2: %res0 = v_cmp_nge_f16 hi(%a), %b - //! p_unit_test 0, %res0 - writeout(0, unordered_cmp); - - Temp ahi_cmp_const = bld.vopc(aco_opcode::v_cmp_lt_f16, bld.def(bld.lm), a_hi, - bld.copy(bld.def(v2b), Operand::c16(0x4400))); - Temp ahi_ucmp_const = - bld.sop2(Builder::s_or, bld.def(bld.lm), bld.def(bld.lm, scc), ahi_unordered, ahi_cmp_const); - //! s2: %res1 = v_cmp_nle_f16 4.0, hi(%a) - //! p_unit_test 1, %res1 - writeout(1, ahi_ucmp_const); - - a_hi = bld.pseudo(aco_opcode::p_extract_vector, bld.def(v2b), a, Operand::c32(1)); - ahi_unordered = bld.vopc(aco_opcode::v_cmp_neq_f16, bld.def(bld.lm), a_hi, a_hi); - b_unordered = bld.vopc(aco_opcode::v_cmp_neq_f16, bld.def(bld.lm), b, b); - unordered = - bld.sop2(Builder::s_or, bld.def(bld.lm), bld.def(bld.lm, scc), ahi_unordered, b_unordered); - Temp alo_lt_b = bld.vopc(aco_opcode::v_cmp_lt_f16, bld.def(bld.lm), a, b); - Temp noopt = bld.sop2(Builder::s_or, bld.def(bld.lm), bld.def(bld.lm, scc), unordered, alo_lt_b); - //! s2: %u2 = v_cmp_u_f16 hi(%a), %b - //! s2: %cmp2 = v_cmp_lt_f16 %a, %b - //! s2: %res2, s2: %scc2:scc = s_or_b64 %u2, %cmp2 - //! p_unit_test 2, %res2 - writeout(2, noopt); - - Temp hi_neq_lo = bld.vopc(aco_opcode::v_cmp_neq_f16, bld.def(bld.lm), a, a_hi); - Temp a_unordered = bld.vopc(aco_opcode::v_cmp_neq_f16, bld.def(bld.lm), a, a); - noopt = bld.sop2(Builder::s_or, bld.def(bld.lm), bld.def(bld.lm, scc), hi_neq_lo, a_unordered); - //! s2: %nan31 = v_cmp_neq_f16 %a, hi(%a) - //! s2: %nan32 = v_cmp_neq_f16 %a, %a - //! s2: %res3, s2: %scc3:scc = s_or_b64 %nan31, %nan32 - //! p_unit_test 3, %res3 - writeout(3, noopt); - - ahi_cmp_const = bld.vopc(aco_opcode::v_cmp_lt_f16, bld.def(bld.lm), a_hi, - bld.copy(bld.def(v2b), Operand::c16(0x4400))); - a_unordered = bld.vopc(aco_opcode::v_cmp_neq_f16, bld.def(bld.lm), a, a); - noopt = - bld.sop2(Builder::s_or, bld.def(bld.lm), bld.def(bld.lm, scc), a_unordered, ahi_cmp_const); - //! s2: %cmp4 = v_cmp_gt_f16 4.0, hi(%a) - //! s2: %nan4 = v_cmp_neq_f16 %a, %a - //! s2: %res4, s2: %scc4:scc = s_or_b64 %nan4, %cmp4 - //! p_unit_test 4, %res4 - writeout(4, noopt); - - finish_opt_test(); -END_TEST - BEGIN_TEST(optimize.max3_opsel) /* TODO make these work before GFX11 using SDWA. */ for (unsigned i = GFX11; i <= GFX11; i++) {