From a21cd8c5b623e9b8b199518331a148835844660f Mon Sep 17 00:00:00 2001 From: Lionel Landwerlin Date: Wed, 13 Nov 2024 11:08:26 +0200 Subject: [PATCH] brw: allocate physical register sizes for spilling All of the spilling code should work with physical register units because for example SEND messages will expect a physical register as destination. So always allocate a full physical register for the spilled/unspilled values and adjust the offsets of the registers to physical sizes too. Cc: mesa-stable Fixes: aa494cba ("brw: align spilling offsets to physical register sizes") Closes: mesa/mesa#11967 Signed-off-by: Lionel Landwerlin Found-by: Paulo Zanoni Reviewed-by: Ian Romanick Part-of: --- src/intel/compiler/brw_fs_reg_allocate.cpp | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/intel/compiler/brw_fs_reg_allocate.cpp b/src/intel/compiler/brw_fs_reg_allocate.cpp index ff41d112ed1..979367ade01 100644 --- a/src/intel/compiler/brw_fs_reg_allocate.cpp +++ b/src/intel/compiler/brw_fs_reg_allocate.cpp @@ -1078,13 +1078,19 @@ fs_reg_alloc::spill_reg(unsigned spill_reg) for (unsigned int i = 0; i < inst->sources; i++) { if (inst->src[i].file == VGRF && inst->src[i].nr == spill_reg) { - int count = regs_read(inst, i); + /* Count registers needed in units of physical registers */ + int count = align(regs_read(inst, i), reg_unit(devinfo)); + /* Align the spilling offset the physical register size */ int subset_spill_offset = spill_offset + ROUND_DOWN_TO(inst->src[i].offset, REG_SIZE * reg_unit(devinfo)); brw_reg unspill_dst = alloc_spill_reg(count, ip); inst->src[i].nr = unspill_dst.nr; - inst->src[i].offset %= REG_SIZE; + /* The unspilled register is aligned to physical register, so + * adjust the offset to the remaining within the physical register + * size. + */ + inst->src[i].offset %= REG_SIZE * reg_unit(devinfo); /* We read the largest power-of-two divisor of the register count * (because only POT scratch read blocks are allowed by the @@ -1108,12 +1114,18 @@ fs_reg_alloc::spill_reg(unsigned spill_reg) if (inst->dst.file == VGRF && inst->dst.nr == spill_reg && inst->opcode != SHADER_OPCODE_UNDEF) { + /* Count registers needed in units of physical registers */ + int count = align(regs_written(inst), reg_unit(devinfo)); + /* Align the spilling offset the physical register size */ int subset_spill_offset = spill_offset + ROUND_DOWN_TO(inst->dst.offset, reg_unit(devinfo) * REG_SIZE); - brw_reg spill_src = alloc_spill_reg(regs_written(inst), ip); + brw_reg spill_src = alloc_spill_reg(count, ip); inst->dst.nr = spill_src.nr; - inst->dst.offset %= REG_SIZE; + /* The spilled register is aligned to physical register, so adjust + * the offset to the remaining within the physical register size. + */ + inst->dst.offset %= REG_SIZE * reg_unit(devinfo); /* If we're immediately spilling the register, we should not use * destination dependency hints. Doing so will cause the GPU do