diff --git a/src/amd/compiler/aco_validate.cpp b/src/amd/compiler/aco_validate.cpp index 655fb0c3bce..8d69952c811 100644 --- a/src/amd/compiler/aco_validate.cpp +++ b/src/amd/compiler/aco_validate.cpp @@ -105,60 +105,71 @@ void validate(Program* program, FILE * output) } } - /* check num literals */ if (instr->isSALU() || instr->isVALU()) { - unsigned num_literals = 0; + /* check literals */ + Operand literal(s1); for (unsigned i = 0; i < instr->operands.size(); i++) { - if (instr->operands[i].isLiteral() && instr->isVOP3() && program->chip_class >= GFX10) { - num_literals++; - } else if (instr->operands[i].isLiteral()) { - check(instr->format == Format::SOP1 || - instr->format == Format::SOP2 || - instr->format == Format::SOPC || - instr->format == Format::VOP1 || - instr->format == Format::VOP2 || - instr->format == Format::VOPC, - "Literal applied on wrong instruction format", instr.get()); + Operand op = instr->operands[i]; + if (!op.isLiteral()) + continue; - num_literals++; - check(!instr->isVALU() || i == 0 || i == 2, "Wrong source position for Literal argument", instr.get()); - } + check(instr->format == Format::SOP1 || + instr->format == Format::SOP2 || + instr->format == Format::SOPC || + instr->format == Format::VOP1 || + instr->format == Format::VOP2 || + instr->format == Format::VOPC || + (instr->isVOP3() && program->chip_class >= GFX10), + "Literal applied on wrong instruction format", instr.get()); + + check(literal.isUndefined() || (literal.size() == op.size() && literal.constantValue() == op.constantValue()), "Only 1 Literal allowed", instr.get()); + literal = op; + check(!instr->isVALU() || instr->isVOP3() || i == 0 || i == 2, "Wrong source position for Literal argument", instr.get()); } - check(num_literals <= 1, "Only 1 Literal allowed", instr.get()); /* check num sgprs for VALU */ if (instr->isVALU()) { + bool is_shift64 = instr->opcode == aco_opcode::v_lshlrev_b64 || + instr->opcode == aco_opcode::v_lshrrev_b64 || + instr->opcode == aco_opcode::v_ashrrev_i64; + unsigned const_bus_limit = 1; + if (program->chip_class >= GFX10 && !is_shift64) + const_bus_limit = 2; + check(instr->definitions[0].getTemp().type() == RegType::vgpr || (int) instr->format & (int) Format::VOPC || instr->opcode == aco_opcode::v_readfirstlane_b32 || instr->opcode == aco_opcode::v_readlane_b32 || instr->opcode == aco_opcode::v_readlane_b32_e64, "Wrong Definition type for VALU instruction", instr.get()); - unsigned num_sgpr = 0; - unsigned sgpr_idx = instr->operands.size(); - for (unsigned i = 0; i < instr->operands.size(); i++) { + unsigned num_sgprs = 0; + unsigned sgpr[] = {0, 0}; + for (unsigned i = 0; i < instr->operands.size(); i++) + { + Operand op = instr->operands[i]; if (instr->opcode == aco_opcode::v_readfirstlane_b32 || instr->opcode == aco_opcode::v_readlane_b32 || instr->opcode == aco_opcode::v_readlane_b32_e64 || instr->opcode == aco_opcode::v_writelane_b32 || instr->opcode == aco_opcode::v_writelane_b32_e64) { - check(!instr->operands[i].isLiteral(), "No literal allowed on VALU instruction", instr.get()); - check(i == 1 || (instr->operands[i].isTemp() && instr->operands[i].regClass() == v1), "Wrong Operand type for VALU instruction", instr.get()); + check(!op.isLiteral(), "No literal allowed on VALU instruction", instr.get()); + check(i == 1 || (op.isTemp() && op.regClass() == v1), "Wrong Operand type for VALU instruction", instr.get()); continue; } - if (instr->operands[i].isTemp() && instr->operands[i].regClass().type() == RegType::sgpr) { - check(i != 1 || (int) instr->format & (int) Format::VOP3A, "Wrong source position for SGPR argument", instr.get()); + if (op.isTemp() && instr->operands[i].regClass().type() == RegType::sgpr) { + check(i != 1 || instr->isVOP3(), "Wrong source position for SGPR argument", instr.get()); - if (sgpr_idx == instr->operands.size() || instr->operands[sgpr_idx].tempId() != instr->operands[i].tempId()) - num_sgpr++; - sgpr_idx = i; + if (op.tempId() != sgpr[0] && op.tempId() != sgpr[1]) { + if (num_sgprs < 2) + sgpr[num_sgprs++] = op.tempId(); + } } - if (instr->operands[i].isConstant() && !instr->operands[i].isLiteral()) - check(i == 0 || (int) instr->format & (int) Format::VOP3A, "Wrong source position for constant argument", instr.get()); + if (op.isConstant() && !op.isLiteral()) + check(i == 0 || instr->isVOP3(), "Wrong source position for constant argument", instr.get()); } - check(num_sgpr + num_literals <= 1, "Only 1 Literal OR 1 SGPR allowed", instr.get()); + check(num_sgprs + (literal.isUndefined() ? 0 : 1) <= const_bus_limit, "Too many SGPRs/literals", instr.get()); } if (instr->format == Format::SOP1 || instr->format == Format::SOP2) {