diff options
author | Connor Abbott <cwabbott0@gmail.com> | 2023-02-16 18:17:35 +0100 |
---|---|---|
committer | Marge Bot <emma+marge@anholt.net> | 2024-04-26 12:55:13 +0000 |
commit | 4ee0f6d1fbf62438c69b1fe17ecf029e888414a0 (patch) | |
tree | 5ea7aedf1d68b851d868556ae3ba75a51f5b4c92 | |
parent | b309418380e6ed25135f31437d30c76a4ddec432 (diff) |
ir3: Allow propagation of normal->shared copies
Copies from normal to shared registers are only allowed architecturally
if all of the active threads have the same value for the normal
register, which means that they can normally be propagated into e.g. ALU
instructions or other copies. However, there are a few instruction types
where this is not (currently) allowed, namely the scan macro where the
source is tied to a shared destination and the collect/split macros
where the lowering doesn't currently allow differently-typed sources and
destinations (although we may want to allow that in the future), so we
need to clean up ir3_valid_flags() to catch that.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/22075>
-rw-r--r-- | src/freedreno/ir3/ir3.c | 10 | ||||
-rw-r--r-- | src/freedreno/ir3/ir3.h | 10 | ||||
-rw-r--r-- | src/freedreno/ir3/ir3_cp.c | 2 |
3 files changed, 11 insertions, 11 deletions
diff --git a/src/freedreno/ir3/ir3.c b/src/freedreno/ir3/ir3.c index 66479bd68a2..381136ddc57 100644 --- a/src/freedreno/ir3/ir3.c +++ b/src/freedreno/ir3/ir3.c @@ -1078,7 +1078,10 @@ ir3_valid_flags(struct ir3_instruction *instr, unsigned n, unsigned flags) if (flags & ~(IR3_REG_IMMED | IR3_REG_CONST | IR3_REG_SHARED)) return false; - if ((flags & IR3_REG_SHARED) && !(instr->dsts[0]->flags & IR3_REG_SHARED)) + /* Except for immed/const sources, source and dest shared-ness must match. + */ + if (!(flags & (IR3_REG_IMMED | IR3_REG_CONST)) && + (flags & IR3_REG_SHARED) != (instr->dsts[0]->flags & IR3_REG_SHARED)) return false; return true; @@ -1096,7 +1099,10 @@ ir3_valid_flags(struct ir3_instruction *instr, unsigned n, unsigned flags) valid_flags = IR3_REG_SHARED; break; case OPC_SCAN_MACRO: - return flags == 0; + if (n == 0) + return flags == 0; + else + return flags == IR3_REG_SHARED; break; case OPC_SCAN_CLUSTERS_MACRO: if (n == 0) diff --git a/src/freedreno/ir3/ir3.h b/src/freedreno/ir3/ir3.h index 89fd12729a4..2caad8ea8e2 100644 --- a/src/freedreno/ir3/ir3.h +++ b/src/freedreno/ir3/ir3.h @@ -917,14 +917,8 @@ is_same_type_reg(struct ir3_register *dst, struct ir3_register *src) unsigned dst_type = (dst->flags & IR3_REG_HALF); unsigned src_type = (src->flags & IR3_REG_HALF); - /* Treat shared->normal copies as same-type, because they can generally be - * folded, but not normal->shared copies. - */ - if (dst_type != src_type || - ((dst->flags & IR3_REG_SHARED) && !(src->flags & IR3_REG_SHARED))) - return false; - else - return true; + /* Treat shared->normal copies and normal->shared copies as same-type. */ + return dst_type == src_type; } /* Is it a non-transformative (ie. not type changing) mov? This can diff --git a/src/freedreno/ir3/ir3_cp.c b/src/freedreno/ir3/ir3_cp.c index e2c569fbacc..8f3133e18e1 100644 --- a/src/freedreno/ir3/ir3_cp.c +++ b/src/freedreno/ir3/ir3_cp.c @@ -116,7 +116,7 @@ combine_flags(unsigned *dstflags, struct ir3_instruction *src) if (srcflags & IR3_REG_BNOT) *dstflags ^= IR3_REG_BNOT; - *dstflags &= ~IR3_REG_SSA; + *dstflags &= ~(IR3_REG_SSA | IR3_REG_SHARED); *dstflags |= srcflags & IR3_REG_SSA; *dstflags |= srcflags & IR3_REG_CONST; *dstflags |= srcflags & IR3_REG_IMMED; |