From d48d43039afbe08d7ca1eb9bc778499438c350ff Mon Sep 17 00:00:00 2001 From: Connor Abbott Date: Fri, 16 Apr 2021 14:07:44 +0200 Subject: [PATCH] ir3: Improve cat1 modifier disassembly Remove bit that shouldn't be part of (rptN), and rewrite the handling of (even) and (pos_infinity) to uncover a missing (neg_infinity) modifier. Part-of: --- src/freedreno/ir3/instr-a3xx.h | 7 +++++++ src/freedreno/ir3/ir3.h | 3 +-- src/freedreno/ir3/ir3_cf.c | 2 +- src/freedreno/ir3/ir3_compiler_nir.c | 2 +- src/freedreno/ir3/ir3_lexer.l | 1 + src/freedreno/ir3/ir3_parser.y | 6 ++++-- src/freedreno/ir3/ir3_postsched.c | 6 ++++-- src/freedreno/isa/ir3-cat1.xml | 24 +++++++++++++++--------- 8 files changed, 34 insertions(+), 17 deletions(-) diff --git a/src/freedreno/ir3/instr-a3xx.h b/src/freedreno/ir3/instr-a3xx.h index 4fc1d51..b56983a 100644 --- a/src/freedreno/ir3/instr-a3xx.h +++ b/src/freedreno/ir3/instr-a3xx.h @@ -355,6 +355,13 @@ static inline int type_sint(type_t type) return (type == TYPE_S32) || (type == TYPE_S16) || (type == TYPE_S8); } +typedef enum { + ROUND_ZERO = 0, + ROUND_EVEN = 1, + ROUND_POS_INF = 2, + ROUND_NEG_INF = 3, +} round_t; + typedef union PACKED { /* normal gpr or const src register: */ struct PACKED { diff --git a/src/freedreno/ir3/ir3.h b/src/freedreno/ir3/ir3.h index bc11f89..87c8144 100644 --- a/src/freedreno/ir3/ir3.h +++ b/src/freedreno/ir3/ir3.h @@ -108,8 +108,6 @@ struct ir3_register { IR3_REG_SNEG = 0x100, IR3_REG_SABS = 0x200, IR3_REG_BNOT = 0x400, - IR3_REG_EVEN = 0x800, - IR3_REG_POS_INF= 0x1000, /* (ei) flag, end-input? Set on last bary, presumably to signal * that the shader needs no more input: */ @@ -264,6 +262,7 @@ struct ir3_instruction { } cat0; struct { type_t src_type, dst_type; + round_t round; } cat1; struct { enum { diff --git a/src/freedreno/ir3/ir3_cf.c b/src/freedreno/ir3/ir3_cf.c index 62014f8..d479bc1 100644 --- a/src/freedreno/ir3/ir3_cf.c +++ b/src/freedreno/ir3/ir3_cf.c @@ -37,7 +37,7 @@ is_fp16_conv(struct ir3_instruction *instr) /* disallow conversions that cannot be folded into * alu instructions: */ - if (dst->flags & (IR3_REG_EVEN | IR3_REG_POS_INF)) + if (instr->cat1.round != ROUND_ZERO) return false; if (dst->flags & (IR3_REG_RELATIV | IR3_REG_ARRAY)) diff --git a/src/freedreno/ir3/ir3_compiler_nir.c b/src/freedreno/ir3/ir3_compiler_nir.c index b6a5e91..8065c30 100644 --- a/src/freedreno/ir3/ir3_compiler_nir.c +++ b/src/freedreno/ir3/ir3_compiler_nir.c @@ -260,7 +260,7 @@ create_cov(struct ir3_context *ctx, struct ir3_instruction *src, ir3_COV(ctx->block, src, src_type, dst_type); if (op == nir_op_f2f16 || op == nir_op_f2f16_rtne) - cov->regs[0]->flags |= IR3_REG_EVEN; + cov->cat1.round = ROUND_EVEN; return cov; } diff --git a/src/freedreno/ir3/ir3_lexer.l b/src/freedreno/ir3/ir3_lexer.l index 47edd07..568145a 100644 --- a/src/freedreno/ir3/ir3_lexer.l +++ b/src/freedreno/ir3/ir3_lexer.l @@ -125,6 +125,7 @@ static int parse_w(const char *str) "(ul)" return TOKEN(T_UL); "(even)" return TOKEN(T_EVEN); "(pos_infinity)" return TOKEN(T_POS_INFINITY); +"(neg_infinity)" return TOKEN(T_NEG_INFINITY); "(ei)" return TOKEN(T_EI); "(jp)" return TOKEN(T_JP); "(sat)" return TOKEN(T_SAT); diff --git a/src/freedreno/ir3/ir3_parser.y b/src/freedreno/ir3/ir3_parser.y index 6498aec..fc684a5 100644 --- a/src/freedreno/ir3/ir3_parser.y +++ b/src/freedreno/ir3/ir3_parser.y @@ -334,6 +334,7 @@ static void print_token(FILE *file, int type, YYSTYPE value) /* dst register flags */ %token T_EVEN %token T_POS_INFINITY +%token T_NEG_INFINITY %token T_EI %token T_WRMASK @@ -1113,8 +1114,9 @@ reg: T_REGISTER { $$ = new_reg($1, 0); } const: T_CONSTANT { $$ = new_reg($1, IR3_REG_CONST); } -dst_reg_flag: T_EVEN { rflags.flags |= IR3_REG_EVEN; } -| T_POS_INFINITY { rflags.flags |= IR3_REG_POS_INF; } +dst_reg_flag: T_EVEN { instr->cat1.round = ROUND_EVEN; } +| T_POS_INFINITY { instr->cat1.round = ROUND_POS_INF; } +| T_NEG_INFINITY { instr->cat1.round = ROUND_NEG_INF; } | T_EI { rflags.flags |= IR3_REG_EI; } | T_WRMASK { rflags.wrmask = $1; } diff --git a/src/freedreno/ir3/ir3_postsched.c b/src/freedreno/ir3/ir3_postsched.c index f2ff6a0..614f1bf 100644 --- a/src/freedreno/ir3/ir3_postsched.c +++ b/src/freedreno/ir3/ir3_postsched.c @@ -672,10 +672,12 @@ is_self_mov(struct ir3_instruction *instr) if (instr->regs[0]->flags & IR3_REG_RELATIV) return false; + if (instr->cat1.round != ROUND_ZERO) + return false; + if (instr->regs[1]->flags & (IR3_REG_CONST | IR3_REG_IMMED | IR3_REG_RELATIV | IR3_REG_FNEG | IR3_REG_FABS | - IR3_REG_SNEG | IR3_REG_SABS | IR3_REG_BNOT | - IR3_REG_EVEN | IR3_REG_POS_INF)) + IR3_REG_SNEG | IR3_REG_SABS | IR3_REG_BNOT)) return false; return true; diff --git a/src/freedreno/isa/ir3-cat1.xml b/src/freedreno/isa/ir3-cat1.xml index e55c735..671ccd4 100644 --- a/src/freedreno/isa/ir3-cat1.xml +++ b/src/freedreno/isa/ir3-cat1.xml @@ -60,16 +60,23 @@ SOFTWARE. + + + + + + + - + + 0 - - + 001 @@ -80,8 +87,7 @@ SOFTWARE. src->cat1.dst_type !!(src->regs[0]->flags & IR3_REG_RELATIV) src->cat1.src_type - !!(src->regs[0]->flags & IR3_REG_EVEN) - !!(src->regs[0]->flags & IR3_REG_POS_INF) + src->cat1.round @@ -91,7 +97,7 @@ SOFTWARE. ({DST} == 0xf4 /* a0.x */) && ({SRC_TYPE} == 4 /* s16 */) && ({DST_TYPE} == 4) - {SY}{SS}{JP}{REPEAT}{UL}mova {EVEN}{POS_INF}a0.x, {SRC} + {SY}{SS}{JP}{REPEAT}{UL}mova {ROUND}a0.x, {SRC} 11110100 100 @@ -102,7 +108,7 @@ SOFTWARE. ({DST} == 0xf5 /* a0.y */) && ({SRC_TYPE} == 2 /* u16 */) && ({DST_TYPE} == 2) - {SY}{SS}{JP}{REPEAT}{UL}mova1 {EVEN}{POS_INF}a1.x, {SRC} + {SY}{SS}{JP}{REPEAT}{UL}mova1 {ROUND}a1.x, {SRC} 11110101 010 @@ -113,11 +119,11 @@ SOFTWARE. {SRC_TYPE} != {DST_TYPE} - {SY}{SS}{JP}{REPEAT}{UL}cov.{SRC_TYPE}{DST_TYPE} {EVEN}{POS_INF}{DST_HALF}{DST}, {SRC} + {SY}{SS}{JP}{REPEAT}{UL}cov.{SRC_TYPE}{DST_TYPE} {ROUND}{DST_HALF}{DST}, {SRC} - {SY}{SS}{JP}{REPEAT}{UL}mov.{SRC_TYPE}{DST_TYPE} {EVEN}{POS_INF}{DST_HALF}{DST}, {SRC} + {SY}{SS}{JP}{REPEAT}{UL}mov.{SRC_TYPE}{DST_TYPE} {ROUND}{DST_HALF}{DST}, {SRC} 00 -- 2.7.4