diff --git a/src/amd/compiler/aco_assembler.cpp b/src/amd/compiler/aco_assembler.cpp index e302795869d..0a6feff5f4b 100644 --- a/src/amd/compiler/aco_assembler.cpp +++ b/src/amd/compiler/aco_assembler.cpp @@ -547,7 +547,11 @@ emit_instruction(asm_context& ctx, std::vector& out, Instruction* inst encoding |= instr->operands[1].physReg() << 16; } else if (instr->format != Format::FLAT || ctx.gfx_level >= GFX10) { /* SADDR is actually used with FLAT on GFX10 */ - if (ctx.gfx_level <= GFX9) + /* For GFX10.3 scratch, 0x7F disables both ADDR and SADDR, unlike sgpr_null, which only + * disables SADDR. + */ + if (ctx.gfx_level <= GFX9 || + (instr->format == Format::SCRATCH && instr->operands[0].isUndefined())) encoding |= 0x7F << 16; else encoding |= sgpr_null << 16; diff --git a/src/amd/compiler/aco_builder_h.py b/src/amd/compiler/aco_builder_h.py index 8177c36207c..e62ad43c0e6 100644 --- a/src/amd/compiler/aco_builder_h.py +++ b/src/amd/compiler/aco_builder_h.py @@ -541,7 +541,8 @@ formats = [("pseudo", [Format.PSEUDO], 'Pseudo_instruction', list(itertools.prod ("vop2_e64", [Format.VOP2, Format.VOP3], 'VOP3_instruction', itertools.product([1, 2], [2, 3])), ("vopc_e64", [Format.VOPC, Format.VOP3], 'VOP3_instruction', itertools.product([1, 2], [2])), ("flat", [Format.FLAT], 'FLAT_instruction', [(0, 3), (1, 2)]), - ("global", [Format.GLOBAL], 'FLAT_instruction', [(0, 3), (1, 2)])] + ("global", [Format.GLOBAL], 'FLAT_instruction', [(0, 3), (1, 2)]), + ("scratch", [Format.SCRATCH], 'FLAT_instruction', [(0, 3), (1, 2)])] formats = [(f if len(f) == 5 else f + ('',)) for f in formats] %>\\ % for name, formats, struct, shapes, extra_field_setup in formats: diff --git a/src/amd/compiler/aco_insert_waitcnt.cpp b/src/amd/compiler/aco_insert_waitcnt.cpp index ad41b5315d8..076f636f266 100644 --- a/src/amd/compiler/aco_insert_waitcnt.cpp +++ b/src/amd/compiler/aco_insert_waitcnt.cpp @@ -673,7 +673,8 @@ gen(Instruction* instr, wait_ctx& ctx) case Format::MUBUF: case Format::MTBUF: case Format::MIMG: - case Format::GLOBAL: { + case Format::GLOBAL: + case Format::SCRATCH: { wait_event ev = !instr->definitions.empty() || ctx.gfx_level < GFX10 ? event_vmem : event_vmem_store; update_counters(ctx, ev, get_sync_info(instr)); diff --git a/src/amd/compiler/aco_validate.cpp b/src/amd/compiler/aco_validate.cpp index 87b5beefbaf..db013e18353 100644 --- a/src/amd/compiler/aco_validate.cpp +++ b/src/amd/compiler/aco_validate.cpp @@ -262,7 +262,8 @@ validate_ir(Program* program) bool can_be_undef = is_phi(instr) || instr->isEXP() || instr->isReduction() || instr->opcode == aco_opcode::p_create_vector || (flat && i == 1) || (instr->isMIMG() && (i == 1 || i == 2)) || - ((instr->isMUBUF() || instr->isMTBUF()) && i == 1); + ((instr->isMUBUF() || instr->isMTBUF()) && i == 1) || + (instr->isScratch() && i == 0); check(can_be_undef, "Undefs can only be used in certain operands", instr.get()); } else { check(instr->operands[i].isFixed() || instr->operands[i].isTemp() || @@ -658,13 +659,20 @@ validate_ir(Program* program) instr.get()); FALLTHROUGH; case Format::GLOBAL: - case Format::SCRATCH: { check( instr->operands[0].isTemp() && instr->operands[0].regClass().type() == RegType::vgpr, - "FLAT/GLOBAL/SCRATCH address must be vgpr", instr.get()); + "FLAT/GLOBAL address must be vgpr", instr.get()); + FALLTHROUGH; + case Format::SCRATCH: { + check(instr->operands[0].hasRegClass() && + instr->operands[0].regClass().type() == RegType::vgpr, + "FLAT/GLOBAL/SCRATCH address must be undefined or vgpr", instr.get()); check(instr->operands[1].hasRegClass() && instr->operands[1].regClass().type() == RegType::sgpr, "FLAT/GLOBAL/SCRATCH sgpr address must be undefined or sgpr", instr.get()); + if (instr->format == Format::SCRATCH && program->gfx_level < GFX10_3) + check(instr->operands[0].isTemp() || instr->operands[1].isTemp(), + "SCRATCH must have either SADDR or ADDR operand", instr.get()); if (!instr->definitions.empty()) check(instr->definitions[0].getTemp().type() == RegType::vgpr, "FLAT/GLOBAL/SCRATCH result must be vgpr", instr.get());