aboutsummaryrefslogtreecommitdiffstats
path: root/src/panfrost
diff options
context:
space:
mode:
authorAlyssa Rosenzweig <[email protected]>2020-03-21 21:19:43 -0400
committerMarge Bot <[email protected]>2020-03-22 03:32:35 +0000
commitd9d549ff8837b488f76981f23fa56c42164ee683 (patch)
tree1ed24b478a148f3657cca4995616bcab320ee664 /src/panfrost
parent5cdc31abd63302e3da82a1bfee625019e818fc3f (diff)
pan/bi: Pack csel4 opcodes
These are pretty straightforward but there's a lot of details to keep straight. In the IR, we keep a general logical comparator and types separately; in the hardware, the type gets fused with a (much more) limited number of comparators. So there's a fair bit of code here to account for these differences, fusing in the type information, and changing up argument order as necessary to make it actually correct. Anything to save a bit! Signed-off-by: Alyssa Rosenzweig <[email protected]> Tested-by: Marge Bot <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4276> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4276>
Diffstat (limited to 'src/panfrost')
-rw-r--r--src/panfrost/bifrost/bi_pack.c78
-rw-r--r--src/panfrost/bifrost/bifrost.h3
2 files changed, 80 insertions, 1 deletions
diff --git a/src/panfrost/bifrost/bi_pack.c b/src/panfrost/bifrost/bi_pack.c
index 1b216275ce1..aab59f724d0 100644
--- a/src/panfrost/bifrost/bi_pack.c
+++ b/src/panfrost/bifrost/bi_pack.c
@@ -475,6 +475,81 @@ bi_pack_fma_1src(bi_instruction *ins, struct bi_registers *regs, unsigned op)
RETURN_PACKED(pack);
}
+static enum bifrost_csel_cond
+bi_cond_to_csel(enum bi_cond cond, bool *flip, bool *invert, nir_alu_type T)
+{
+ nir_alu_type B = nir_alu_type_get_base_type(T);
+ unsigned idx = (B == nir_type_float) ? 0 :
+ ((B == nir_type_int) ? 1 : 2);
+
+ switch (cond){
+ case BI_COND_LT:
+ *flip = true;
+ case BI_COND_GT: {
+ const enum bifrost_csel_cond ops[] = {
+ BIFROST_FGT_F,
+ BIFROST_IGT_I,
+ BIFROST_UGT_I
+ };
+
+ return ops[idx];
+ }
+ case BI_COND_LE:
+ *flip = true;
+ case BI_COND_GE: {
+ const enum bifrost_csel_cond ops[] = {
+ BIFROST_FGE_F,
+ BIFROST_IGE_I,
+ BIFROST_UGE_I
+ };
+
+ return ops[idx];
+ }
+ case BI_COND_NE:
+ *invert = true;
+ case BI_COND_EQ: {
+ const enum bifrost_csel_cond ops[] = {
+ BIFROST_FEQ_F,
+ BIFROST_IEQ_F,
+ BIFROST_IEQ_F /* sign is irrelevant */
+ };
+
+ return ops[idx];
+ }
+ default:
+ unreachable("Invalid op for csel");
+ }
+}
+
+static unsigned
+bi_pack_fma_csel(bi_instruction *ins, struct bi_registers *regs)
+{
+ /* TODO: Use csel3 as well */
+ bool flip = false, invert = false;
+
+ enum bifrost_csel_cond cond =
+ bi_cond_to_csel(ins->csel_cond, &flip, &invert, ins->src_types[0]);
+
+ unsigned size = nir_alu_type_get_type_size(ins->dest_type);
+
+ unsigned cmp_0 = (flip ? 3 : 0);
+ unsigned cmp_1 = (flip ? 0 : 3);
+ unsigned res_0 = (invert ? 2 : 1);
+ unsigned res_1 = (invert ? 1 : 2);
+
+ struct bifrost_csel4 pack = {
+ .src0 = bi_get_src(ins, regs, cmp_0, true),
+ .src1 = bi_get_src(ins, regs, cmp_1, true),
+ .src2 = bi_get_src(ins, regs, res_0, true),
+ .src3 = bi_get_src(ins, regs, res_1, true),
+ .cond = cond,
+ .op = (size == 16) ? BIFROST_FMA_OP_CSEL4_V16 :
+ BIFROST_FMA_OP_CSEL4
+ };
+
+ RETURN_PACKED(pack);
+}
+
static unsigned
bi_pack_fma(bi_clause *clause, bi_bundle bundle, struct bi_registers *regs)
{
@@ -487,8 +562,9 @@ bi_pack_fma(bi_clause *clause, bi_bundle bundle, struct bi_registers *regs)
case BI_CMP:
case BI_BITWISE:
case BI_CONVERT:
- case BI_CSEL:
return BIFROST_FMA_NOP;
+ case BI_CSEL:
+ return bi_pack_fma_csel(bundle.fma, regs);
case BI_FMA:
return bi_pack_fma_fma(bundle.fma, regs);
case BI_FREXP:
diff --git a/src/panfrost/bifrost/bifrost.h b/src/panfrost/bifrost/bifrost.h
index 7b8854f56f3..a6508440cbb 100644
--- a/src/panfrost/bifrost/bifrost.h
+++ b/src/panfrost/bifrost/bifrost.h
@@ -230,6 +230,9 @@ enum bifrost_csel_cond {
BIFROST_UGE_I = 0x7
};
+#define BIFROST_FMA_OP_CSEL4 (0x5c)
+#define BIFROST_FMA_OP_CSEL4_V16 (0xdc)
+
struct bifrost_csel4 {
unsigned src0 : 3;
unsigned src1 : 3;