diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/gallium/drivers/vc4/vc4_qpu.c | 48 |
1 files changed, 47 insertions, 1 deletions
diff --git a/src/gallium/drivers/vc4/vc4_qpu.c b/src/gallium/drivers/vc4/vc4_qpu.c index fc5d4b09dc2..0e388905228 100644 --- a/src/gallium/drivers/vc4/vc4_qpu.c +++ b/src/gallium/drivers/vc4/vc4_qpu.c @@ -259,6 +259,37 @@ qpu_num_sf_accesses(uint64_t inst) return accesses; } +static bool +qpu_waddr_ignores_pm(uint32_t waddr) +{ + switch(waddr) { + case QPU_W_ACC0: + case QPU_W_ACC1: + case QPU_W_ACC2: + case QPU_W_ACC3: + case QPU_W_TLB_Z: + case QPU_W_TLB_COLOR_MS: + case QPU_W_TLB_COLOR_ALL: + case QPU_W_TLB_ALPHA_MASK: + case QPU_W_VPM: + case QPU_W_SFU_RECIP: + case QPU_W_SFU_RECIPSQRT: + case QPU_W_SFU_EXP: + case QPU_W_SFU_LOG: + case QPU_W_TMU0_S: + case QPU_W_TMU0_T: + case QPU_W_TMU0_R: + case QPU_W_TMU0_B: + case QPU_W_TMU1_S: + case QPU_W_TMU1_T: + case QPU_W_TMU1_R: + case QPU_W_TMU1_B: + return true; + } + + return false; +} + uint64_t qpu_merge_inst(uint64_t a, uint64_t b) { @@ -280,7 +311,7 @@ qpu_merge_inst(uint64_t a, uint64_t b) QPU_SET_FIELD(QPU_SIG_NONE, QPU_SIG)); /* Misc fields that have to match exactly. */ - ok = ok && merge_fields(&merge, a, b, QPU_SF | QPU_WS | QPU_PM, + ok = ok && merge_fields(&merge, a, b, QPU_SF | QPU_PM, ~0); ok = ok && merge_fields(&merge, a, b, QPU_RADDR_A_MASK, @@ -293,6 +324,21 @@ qpu_merge_inst(uint64_t a, uint64_t b) ok = ok && merge_fields(&merge, a, b, QPU_WADDR_MUL_MASK, QPU_SET_FIELD(QPU_W_NOP, QPU_WADDR_MUL)); + /* Allow disagreement on WS (swapping A vs B physical reg file as the + * destination for ADD/MUL) if one of the original instructions + * ignores it (probably because it's just writing to accumulators). + */ + if (qpu_waddr_ignores_pm(QPU_GET_FIELD(a, QPU_WADDR_ADD)) && + qpu_waddr_ignores_pm(QPU_GET_FIELD(a, QPU_WADDR_MUL))) { + merge = (merge & ~QPU_WS) | (b & QPU_WS); + } else if (qpu_waddr_ignores_pm(QPU_GET_FIELD(b, QPU_WADDR_ADD)) && + qpu_waddr_ignores_pm(QPU_GET_FIELD(b, QPU_WADDR_MUL))) { + merge = (merge & ~QPU_WS) | (a & QPU_WS); + } else { + if ((a & QPU_WS) != (b & QPU_WS)) + return 0; + } + if (ok) return merge; else |