ir3/cp: support propagating const vecs

Some instructions (e.g., cat6) support using a const vec (i.e., multiple
consecutive const registers) as src. Add support for cp'ing collects of
consecutive const registers.

Signed-off-by: Job Noorman <jnoorman@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/41365>
This commit is contained in:
Job Noorman 2026-05-05 16:14:14 +02:00 committed by Marge Bot
parent c67118a6eb
commit 8bd0212874

View file

@ -287,6 +287,34 @@ try_swap_cat3_two_srcs(struct ir3_instruction *instr, unsigned n,
return is_sad(instr->opc) && try_swap_two_srcs(instr, n, new_flags, 1); return is_sad(instr->opc) && try_swap_two_srcs(instr, n, new_flags, 1);
} }
/* Is this a collect of only consecutive const srcs? Some instructions (e.g.,
* cat6) can directly use consecutive const registers as a src so the collect
* can be cp'ed like a mov.
*/
static bool
is_const_vec(struct ir3_instruction *collect)
{
if (collect->opc != OPC_META_COLLECT) {
return false;
}
unsigned first_num;
foreach_src_n (src, src_n, collect) {
if (!(src->flags & IR3_REG_CONST)) {
return false;
}
if (src_n == 0) {
first_num = src->num;
} else if (src->num != first_num + src_n) {
return false;
}
}
return true;
}
/** /**
* Handle cp for a given src register. This additionally handles * Handle cp for a given src register. This additionally handles
* the cases of collapsing immedate/const (which replace the src * the cases of collapsing immedate/const (which replace the src
@ -341,7 +369,7 @@ reg_cp(struct ir3_cp_ctx *ctx, struct ir3_instruction *instr,
} else if (try_swap_cat3_two_srcs(instr, n, new_flags)) { } else if (try_swap_cat3_two_srcs(instr, n, new_flags)) {
return true; return true;
} }
} else if ((is_same_type_mov(src) || is_const_mov(src)) && } else if ((is_same_type_mov(src) || is_const_mov(src) || is_const_vec(src)) &&
/* cannot collapse const/immed/etc into control flow: */ /* cannot collapse const/immed/etc into control flow: */
opc_cat(instr->opc) != 0) { opc_cat(instr->opc) != 0) {
/* immed/const/etc cases, which require some special handling: */ /* immed/const/etc cases, which require some special handling: */
@ -406,25 +434,28 @@ reg_cp(struct ir3_cp_ctx *ctx, struct ir3_instruction *instr,
* to work only for float. So we should do this only with * to work only for float. So we should do this only with
* float opcodes. * float opcodes.
*/ */
if (src->cat1.dst_type == TYPE_F16) { if (src->opc == OPC_MOV) {
/* TODO: should we have a way to tell phi/collect to use a if (src->cat1.dst_type == TYPE_F16) {
* float move so that this is legal? /* TODO: should we have a way to tell phi/collect to use a
*/ * float move so that this is legal?
if (is_meta(instr)) */
return false; if (is_meta(instr))
if (instr->opc == OPC_MOV && !type_float(instr->cat1.src_type)) return false;
return false; if (instr->opc == OPC_MOV && !type_float(instr->cat1.src_type))
if (!is_cat2_float(instr->opc) && !is_cat3_float(instr->opc)) return false;
return false; if (!is_cat2_float(instr->opc) && !is_cat3_float(instr->opc))
} else if (src->cat1.dst_type == TYPE_U16 || src->cat1.dst_type == TYPE_S16) { return false;
/* Since we set CONSTANT_DEMOTION_ENABLE, a float reference of } else if (src->cat1.dst_type == TYPE_U16 ||
* what was a U16 value read from the constbuf would incorrectly src->cat1.dst_type == TYPE_S16) {
* do 32f->16f conversion, when we want to read a 16f value. /* Since we set CONSTANT_DEMOTION_ENABLE, a float reference of
*/ * what was a U16 value read from the constbuf would incorrectly
if (is_cat2_float(instr->opc) || is_cat3_float(instr->opc)) * do 32f->16f conversion, when we want to read a 16f value.
return false; */
if (instr->opc == OPC_MOV && type_float(instr->cat1.src_type)) if (is_cat2_float(instr->opc) || is_cat3_float(instr->opc))
return false; return false;
if (instr->opc == OPC_MOV && type_float(instr->cat1.src_type))
return false;
}
} }
src_reg = ir3_reg_clone(instr->block->shader, src_reg); src_reg = ir3_reg_clone(instr->block->shader, src_reg);