diff --git a/src/freedreno/ir3/ir3.c b/src/freedreno/ir3/ir3.c index bc493a9dc76..7dc042c9a55 100644 --- a/src/freedreno/ir3/ir3.c +++ b/src/freedreno/ir3/ir3.c @@ -1837,6 +1837,12 @@ ir3_valid_flags(struct ir3_instruction *instr, unsigned n, unsigned flags) else if (n == 1) valid_flags |= IR3_REG_SHARED; } + if (compiler->gen >= 7 && + (instr->opc == OPC_LDG_A || instr->opc == OPC_STG_A || + instr->opc == OPC_RAY_INTERSECTION) && + n == 0) { + valid_flags |= IR3_REG_CONST; + } if (flags & ~valid_flags) return false; @@ -1964,6 +1970,25 @@ ir3_valid_immediate(struct ir3_instruction *instr, int32_t immed) return !(immed & ~0x1ff) || !(-(uint32_t)immed & ~0x1ff); } +/* Some instructions (e.g., cat6) don't support the full range of const + * registers as src. + */ +bool +ir3_valid_const(struct ir3_instruction *instr, unsigned src_n, unsigned num) +{ + assert(ir3_valid_flags(instr, src_n, IR3_REG_CONST)); + + switch (instr->opc) { + case OPC_LDG_A: + case OPC_STG_A: + case OPC_RAY_INTERSECTION: + assert(src_n == 0); + return num < (1 << 8); + default: + return true; + } +} + struct ir3_instruction * ir3_get_cond_for_nonzero_compare(struct ir3_instruction *instr) { diff --git a/src/freedreno/ir3/ir3.h b/src/freedreno/ir3/ir3.h index 9d5351e6386..83517828918 100644 --- a/src/freedreno/ir3/ir3.h +++ b/src/freedreno/ir3/ir3.h @@ -998,6 +998,8 @@ int ir3_flut(struct ir3_register *src_reg); bool ir3_valid_flags(struct ir3_instruction *instr, unsigned n, unsigned flags); bool ir3_valid_immediate(struct ir3_instruction *instr, int32_t immed); +bool ir3_valid_const(struct ir3_instruction *instr, unsigned src_n, + unsigned num); /** * Given an instruction whose result we want to test for nonzero, return a diff --git a/src/freedreno/ir3/ir3_cp.c b/src/freedreno/ir3/ir3_cp.c index 7647265828d..6fd9955fe1d 100644 --- a/src/freedreno/ir3/ir3_cp.c +++ b/src/freedreno/ir3/ir3_cp.c @@ -409,6 +409,11 @@ reg_cp(struct ir3_cp_ctx *ctx, struct ir3_instruction *instr, * dependency. */ if (src_reg->flags & IR3_REG_CONST) { + if (!(src_reg->flags & IR3_REG_RELATIV) && + !ir3_valid_const(instr, n, src_reg->num)) { + return false; + } + /* an instruction cannot reference two different * address registers: */