pan/bi: Rewrite conversion packing

To support roundmodes and other goodies.

Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4539>
This commit is contained in:
Alyssa Rosenzweig 2020-04-13 15:56:06 -04:00 committed by Marge Bot
parent 0b000c54c0
commit 8cfe660326
2 changed files with 89 additions and 63 deletions

View file

@ -749,49 +749,80 @@ bi_pack_fma_convert(bi_instruction *ins, struct bi_registers *regs)
nir_alu_type to_base = nir_alu_type_get_base_type(ins->dest_type);
unsigned to_size = nir_alu_type_get_type_size(ins->dest_type);
bool to_unsigned = to_base == nir_type_uint;
bool to_float = to_base == nir_type_float;
/* Sanity check */
assert((from_base != to_base) || (from_size != to_size));
assert((MAX2(from_size, to_size) / MIN2(from_size, to_size)) <= 2);
if (from_size == 16 && to_size == 16) {
/* f2i_i2f16 */
unreachable("i16 not yet implemented");
} else if (from_size == 32 && to_size == 32) {
unsigned op = 0;
/* f32 to f16 is special */
if (from_size == 32 && to_size == 16 && from_base == nir_type_float && to_base == from_base) {
/* TODO: second vectorized source? */
struct bifrost_fma_2src pack = {
.src0 = bi_get_src(ins, regs, 0, true),
.src1 = BIFROST_SRC_STAGE, /* 0 */
.op = BIFROST_FMA_FLOAT32_TO_16
};
if (from_base == nir_type_float) {
op = BIFROST_FMA_FLOAT32_TO_INT(to_unsigned);
} else {
op = BIFROST_FMA_INT_TO_FLOAT32(from_unsigned);
}
return bi_pack_fma_1src(ins, regs, op);
} else if (from_size == 16 && to_size == 32) {
bool from_y = ins->swizzle[0][0];
if (from_base == nir_type_float) {
return bi_pack_fma_1src(ins, regs,
BIFROST_FMA_FLOAT16_TO_32(from_y));
} else {
unreachable("i16 not yet implemented");
}
} else if (from_size == 32 && to_size == 16) {
if (from_base == nir_type_float) {
/* TODO: second vectorized source? */
struct bifrost_fma_2src pack = {
.src0 = bi_get_src(ins, regs, 0, true),
.src1 = BIFROST_SRC_STAGE, /* 0 */
.op = BIFROST_FMA_FLOAT32_TO_16
};
RETURN_PACKED(pack);
} else {
unreachable("i16 not yet implemented");
}
RETURN_PACKED(pack);
}
unreachable("Unknown convert");
/* Otherwise, figure out the mode */
unsigned op = 0;
if (from_size == 16 && to_size == 32) {
unsigned component = ins->swizzle[0][0];
assert(component <= 1);
if (from_base == nir_type_float)
op = BIFROST_CONVERT_5(component);
else
op = BIFROST_CONVERT_4(from_unsigned, component, to_float);
} else {
unsigned mode = 0;
unsigned swizzle = (from_size == 16) ? bi_swiz16(ins, 0) : 0;
bool is_unsigned = from_unsigned;
if (from_base == nir_type_float) {
assert(to_base != nir_type_float);
is_unsigned = to_unsigned;
if (from_size == 32 && to_size == 32)
mode = BIFROST_CONV_F32_TO_I32;
else if (from_size == 16 && to_size == 16)
mode = BIFROST_CONV_F16_TO_I16;
else
unreachable("Invalid float conversion");
} else {
assert(to_base == nir_type_float);
assert(from_size == to_size);
if (to_size == 32)
mode = BIFROST_CONV_I32_TO_F32;
else if (to_size == 16)
mode = BIFROST_CONV_I16_TO_F16;
else
unreachable("Invalid int conversion");
}
/* Fixup swizzle for 32-bit only modes */
if (mode == BIFROST_CONV_I32_TO_F32)
swizzle = 0b11;
else if (mode == BIFROST_CONV_F32_TO_I32)
swizzle = 0b10;
op = BIFROST_CONVERT(is_unsigned, ins->roundmode, swizzle, mode);
/* Unclear what the top bit is for... maybe 16-bit related */
bool mode2 = mode == BIFROST_CONV_F16_TO_I16;
bool mode6 = mode == BIFROST_CONV_I16_TO_F16;
if (!(mode2 || mode6))
op |= 0x100;
}
return bi_pack_fma_1src(ins, regs, BIFROST_FMA_CONVERT | op);
}
static unsigned

View file

@ -333,39 +333,34 @@ struct bifrost_shift_add {
unsigned op : 7;
} __attribute__((packed));
#define BIFROST_FMA_INT16_TO_32 (0xe0198 >> 3)
struct bifrost_fma_int16_to_32 {
unsigned src0 : 3;
unsigned is_unsigned : 1;
unsigned swizzle : 1;
unsigned to_float : 1;
unsigned op : 17;
} __attribute__((packed));
/* We could combine but it's easier to just use FMA_ONE_SRC */
#define BIFROST_FMA_FLOAT16_TO_32(y) (0xe01a2 | ((y) ? 1 : 0))
/* Two sources for vectorization */
#define BIFROST_FMA_FLOAT32_TO_16 (0xdd000 >> 3)
/* Again we could combine but easier to just ONE_SRC with an
* argumnt for unsignedness */
#define BIFROST_FMA_FLOAT32_TO_INT(u) (0xe0136 | ((u) ? 1 : 0))
#define BIFROST_FMA_INT_TO_FLOAT32(u) (0xe0178 | ((u) ? 1 : 0))
enum bifrost_convert_mode {
BIFROST_CONV_UNK0 = 0,
BIFROST_CONV_F32_TO_I32 = 1,
BIFROST_CONV_F16_TO_I16 = 2,
BIFROST_CONV_I32_TO_F32 = 3,
BIFROST_CONV_I16_TO_X32 = 4,
BIFROST_CONV_F16_TO_F32 = 5,
BIFROST_CONV_I16_TO_F16 = 6,
BIFROST_CONV_UNK7 = 7
};
/* Used for f2i16 and i2f16 */
#define BIFROST_FMA_F2I16 (0xe00)
/* i16 to x32 */
#define BIFROST_CONVERT_4(is_unsigned, component, to_float) \
((is_unsigned & 1) | ((component & 1) << 1) | ((to_float & 1) << 2) | \
((0x3) << 3) | ((4) << 5) | 0x100)
struct bifrost_fma_f2i_i2f16 {
unsigned src0 : 3;
unsigned is_unsigned : 1;
unsigned direction : 2; /* 00 for i2f, 11 for f2i */
unsigned swizzle : 2;
unsigned unk : 2; /* always 10 */
unsigned direction_2 : 1; /* 0 for f2i, 1 for i2f */
unsigned op : 12;
} __attribute__((packed));
/* f16 to f32 */
#define BIFROST_CONVERT_5(component) \
((component & 1) | ((1) << 1) | ((5) << 5) | 0x100)
/* Other conversions */
#define BIFROST_CONVERT(is_unsigned, roundmode, swizzle, mode) \
((is_unsigned & 1) | ((roundmode & 3) << 1) | ((swizzle & 3) << 3) | ((mode & 7) << 5))
#define BIFROST_FMA_CONVERT (0xe0000)
enum bifrost_ldst_type {
BIFROST_LDST_F16 = 0,