diff options
author | Alyssa Rosenzweig <[email protected]> | 2020-03-21 21:19:43 -0400 |
---|---|---|
committer | Marge Bot <[email protected]> | 2020-03-22 03:32:35 +0000 |
commit | d9d549ff8837b488f76981f23fa56c42164ee683 (patch) | |
tree | 1ed24b478a148f3657cca4995616bcab320ee664 /src/panfrost/bifrost/bi_pack.c | |
parent | 5cdc31abd63302e3da82a1bfee625019e818fc3f (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/bifrost/bi_pack.c')
-rw-r--r-- | src/panfrost/bifrost/bi_pack.c | 78 |
1 files changed, 77 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: |