aboutsummaryrefslogtreecommitdiffstats
path: root/src/freedreno
diff options
context:
space:
mode:
authorRob Clark <[email protected]>2020-05-16 14:24:45 -0700
committerMarge Bot <[email protected]>2020-05-19 16:06:17 +0000
commitf484d63617afe67f9eb8ba98f96e5c3617aa43c8 (patch)
tree3cdd9282822e04146b37cdb8e0202d3226bf9b1c /src/freedreno
parent3561d34fff44ae82283dc1d4352e87d47793c40e (diff)
freedreno/ir3: add helpers to deal with src/dst types
Add some helpers to properly maintain src/dst types, and in the cases where opcode depends on src or dst type, maintain that as well. Signed-off-by: Rob Clark <[email protected]> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5048>
Diffstat (limited to 'src/freedreno')
-rw-r--r--src/freedreno/ir3/ir3.c66
-rw-r--r--src/freedreno/ir3/ir3.h51
-rw-r--r--src/freedreno/ir3/ir3_cf.c7
-rw-r--r--src/freedreno/ir3/ir3_context.c6
4 files changed, 122 insertions, 8 deletions
diff --git a/src/freedreno/ir3/ir3.c b/src/freedreno/ir3/ir3.c
index d575ee3ae42..23f29664e82 100644
--- a/src/freedreno/ir3/ir3.c
+++ b/src/freedreno/ir3/ir3.c
@@ -1211,3 +1211,69 @@ ir3_find_ssa_uses(struct ir3 *ir, void *mem_ctx, bool falsedeps)
}
}
}
+
+/**
+ * Set the destination type of an instruction, for example if a
+ * conversion is folded in, handling the special cases where the
+ * instruction's dest type or opcode needs to be fixed up.
+ */
+void
+ir3_set_dst_type(struct ir3_instruction *instr, bool half)
+{
+ if (half) {
+ instr->regs[0]->flags |= IR3_REG_HALF;
+ } else {
+ instr->regs[0]->flags &= ~IR3_REG_HALF;
+ }
+
+ switch (opc_cat(instr->opc)) {
+ case 1: /* move instructions */
+ if (half) {
+ instr->cat1.dst_type = half_type(instr->cat1.dst_type);
+ } else {
+ instr->cat1.dst_type = full_type(instr->cat1.dst_type);
+ }
+ break;
+ case 4:
+ if (half) {
+ instr->opc = cat4_half_opc(instr->opc);
+ } else {
+ instr->opc = cat4_full_opc(instr->opc);
+ }
+ break;
+ case 5:
+ if (half) {
+ instr->cat5.type = half_type(instr->cat5.type);
+ } else {
+ instr->cat5.type = full_type(instr->cat5.type);
+ }
+ break;
+ }
+}
+
+/**
+ * One-time fixup for instruction src-types. Other than cov's that
+ * are folded, an instruction's src type does not change.
+ */
+void
+ir3_fixup_src_type(struct ir3_instruction *instr)
+{
+ bool half = !!(instr->regs[1]->flags & IR3_REG_HALF);
+
+ switch (opc_cat(instr->opc)) {
+ case 1: /* move instructions */
+ if (half) {
+ instr->cat1.src_type = half_type(instr->cat1.src_type);
+ } else {
+ instr->cat1.src_type = full_type(instr->cat1.src_type);
+ }
+ break;
+ case 3:
+ if (half) {
+ instr->opc = cat3_half_opc(instr->opc);
+ } else {
+ instr->opc = cat3_full_opc(instr->opc);
+ }
+ break;
+ }
+}
diff --git a/src/freedreno/ir3/ir3.h b/src/freedreno/ir3/ir3.h
index 2fb21b67d4d..d6ff469b26e 100644
--- a/src/freedreno/ir3/ir3.h
+++ b/src/freedreno/ir3/ir3.h
@@ -595,6 +595,9 @@ unsigned ir3_count_instructions_ra(struct ir3 *ir);
void ir3_find_ssa_uses(struct ir3 *ir, void *mem_ctx, bool falsedeps);
+void ir3_set_dst_type(struct ir3_instruction *instr, bool half);
+void ir3_fixup_src_type(struct ir3_instruction *instr);
+
#include "util/set.h"
#define foreach_ssa_use(__use, __instr) \
for (struct ir3_instruction *__use = (void *)~0; \
@@ -830,6 +833,54 @@ static inline bool is_bool(struct ir3_instruction *instr)
}
}
+static inline opc_t
+cat3_half_opc(opc_t opc)
+{
+ switch (opc) {
+ case OPC_MAD_F32: return OPC_MAD_F16;
+ case OPC_SEL_B32: return OPC_SEL_B16;
+ case OPC_SEL_S32: return OPC_SEL_S16;
+ case OPC_SEL_F32: return OPC_SEL_F16;
+ case OPC_SAD_S32: return OPC_SAD_S16;
+ default: return opc;
+ }
+}
+
+static inline opc_t
+cat3_full_opc(opc_t opc)
+{
+ switch (opc) {
+ case OPC_MAD_F16: return OPC_MAD_F32;
+ case OPC_SEL_B16: return OPC_SEL_B32;
+ case OPC_SEL_S16: return OPC_SEL_S32;
+ case OPC_SEL_F16: return OPC_SEL_F32;
+ case OPC_SAD_S16: return OPC_SAD_S32;
+ default: return opc;
+ }
+}
+
+static inline opc_t
+cat4_half_opc(opc_t opc)
+{
+ switch (opc) {
+ case OPC_RSQ: return OPC_HRSQ;
+ case OPC_LOG2: return OPC_HLOG2;
+ case OPC_EXP2: return OPC_HEXP2;
+ default: return opc;
+ }
+}
+
+static inline opc_t
+cat4_full_opc(opc_t opc)
+{
+ switch (opc) {
+ case OPC_HRSQ: return OPC_RSQ;
+ case OPC_HLOG2: return OPC_LOG2;
+ case OPC_HEXP2: return OPC_EXP2;
+ default: return opc;
+ }
+}
+
static inline bool is_meta(struct ir3_instruction *instr)
{
return (opc_cat(instr->opc) == -1);
diff --git a/src/freedreno/ir3/ir3_cf.c b/src/freedreno/ir3/ir3_cf.c
index c1dc5385d36..62014f8700a 100644
--- a/src/freedreno/ir3/ir3_cf.c
+++ b/src/freedreno/ir3/ir3_cf.c
@@ -148,12 +148,7 @@ try_conversion_folding(struct ir3_instruction *conv)
}
}
- if (is_half(conv)) {
- src->regs[0]->flags |= IR3_REG_HALF;
- } else {
- src->regs[0]->flags &= ~IR3_REG_HALF;
- }
-
+ ir3_set_dst_type(src, is_half(conv));
rewrite_src_uses(src);
return true;
diff --git a/src/freedreno/ir3/ir3_context.c b/src/freedreno/ir3/ir3_context.c
index 4fe3ae74e31..b9905625b70 100644
--- a/src/freedreno/ir3/ir3_context.c
+++ b/src/freedreno/ir3/ir3_context.c
@@ -256,9 +256,11 @@ ir3_put_dst(struct ir3_context *ctx, nir_dest *dst)
if (bit_size == 16) {
for (unsigned i = 0; i < ctx->last_dst_n; i++) {
struct ir3_instruction *dst = ctx->last_dst[i];
- dst->regs[0]->flags |= IR3_REG_HALF;
+ ir3_set_dst_type(dst, true);
+ ir3_fixup_src_type(dst);
if (dst->opc == OPC_META_SPLIT) {
- dst->regs[1]->instr->regs[0]->flags |= IR3_REG_HALF;
+ ir3_set_dst_type(ssa(dst->regs[1]), true);
+ ir3_fixup_src_type(ssa(dst->regs[1]));
dst->regs[1]->flags |= IR3_REG_HALF;
}
}