diff --git a/src/freedreno/.gitlab-ci/reference/prefetch-test.log b/src/freedreno/.gitlab-ci/reference/prefetch-test.log index 5b29f740d39..e3cd8ee0039 100644 --- a/src/freedreno/.gitlab-ci/reference/prefetch-test.log +++ b/src/freedreno/.gitlab-ci/reference/prefetch-test.log @@ -149159,8 +149159,13 @@ shader-blocks: :4:0049:0061[821c4006x_20905a42x] no match: 821c400620905a42 :5:0050:0062[b002819cx_d601061dx] (sy)isam.a (f16)(x)hr39.x, r3.z, s#0, t#107 ; WARNING: unexpected bits[47:47] in #instruction-cat5: 0000000000000001 vs 0000000000000000, WARNING: unexpected bits[0:7] in #cat5-src2: 0000000000000083 vs 0000000000000000 :0:0051:0063[19d70515x_81d857bex] no match: 19d7051581d857be - :3:0052:0064[7972f999x_e4df0ecbx] (sy)(ss)(jp)(rpt1)(ul)mad.s16 r38.y, (r)hc, (neg)hr57.y, (neg)(r) ; no match: FIELD: 'mad.s16.SRC3': 00000000000004df + :3:0052:0064[7972f999x_e4df0ecbx] (sy)(ss)(jp)(rpt1)(ul)mad.s16 r38.y, (r)hc, (neg)hr57.y, (neg)(r)(last)hr55.w :6:0053:0066[dda7eb4fx_f96f6ddfx] no match: dda7eb4ff96f6ddf + :5:0054:0067[a4e7fe75x_ab4ffb7fx] no match: a4e7fe75ab4ffb7f + :6:0055:0068[d1937f77x_effcfeefx] no match: d1937f77effcfeef + :0:0056:0069[1134c8d0x_34200204x] (sy)jump #874512900 ; dontcare bits in jump: 0034c8d000000000 + :5:0057:0070[ac44c0eax_60215b2ex] (jp)gather4g.s (s16)()hr58.z, hr37.w, s#1, t#48 ; WARNING: unexpected bits[47:47] in #instruction-cat5: 0000000000000001 vs 0000000000000000, WARNING: unexpected bits[0:7] in #cat5-src2: 00000000000000ad vs 0000000000000000 + :3:0058:0071[6808c080x_2078f048x] no match: 6808c0802078f048 ----------------------------------------------- 8192 (0x2000) bytes 000000: 0000001e 03820000 0000001d 02820000 |................| diff --git a/src/freedreno/ir3/ir3.h b/src/freedreno/ir3/ir3.h index 9c829b5611b..0f7096a5e18 100644 --- a/src/freedreno/ir3/ir3.h +++ b/src/freedreno/ir3/ir3.h @@ -160,6 +160,12 @@ typedef enum ir3_register_flags { * interferes with the sources of the instruction. */ IR3_REG_EARLY_CLOBBER = BIT(17), + + /* If this is the last usage of a specific value in the register, the + * register cannot be read without being written to first after this. + * Note: This effectively has the same semantics as IR3_REG_KILL. + */ + IR3_REG_LAST_USE = BIT(18), } ir3_register_flags; struct ir3_register { diff --git a/src/freedreno/ir3/ir3_lexer.l b/src/freedreno/ir3/ir3_lexer.l index 84eed7b6b54..ff8ee7b96f9 100644 --- a/src/freedreno/ir3/ir3_lexer.l +++ b/src/freedreno/ir3/ir3_lexer.l @@ -115,6 +115,7 @@ static int parse_reg(const char *str) "(neg)" return TOKEN(T_NEG); "(abs)" return TOKEN(T_ABS); "(r)" return TOKEN(T_R); +"(last)" return TOKEN(T_LAST); "(ul)" return TOKEN(T_UL); "(even)" return TOKEN(T_EVEN); "(pos_infinity)" return TOKEN(T_POS_INFINITY); diff --git a/src/freedreno/ir3/ir3_parser.y b/src/freedreno/ir3/ir3_parser.y index 56e5cadd5b1..82677125887 100644 --- a/src/freedreno/ir3/ir3_parser.y +++ b/src/freedreno/ir3/ir3_parser.y @@ -343,6 +343,7 @@ static void print_token(FILE *file, int type, YYSTYPE value) %token T_NEG %token T_ABS %token T_R +%token T_LAST %token T_HR %token T_HC @@ -1364,6 +1365,7 @@ src_reg_flag: T_ABSNEG { rflags.flags |= IR3_REG_ABS|IR3_REG_NEGATE; | T_NEG { rflags.flags |= IR3_REG_NEGATE; } | T_ABS { rflags.flags |= IR3_REG_ABS; } | T_R { rflags.flags |= IR3_REG_R; } +| T_LAST { rflags.flags |= IR3_REG_LAST_USE; } src_reg_flags: src_reg_flag | src_reg_flag src_reg_flags diff --git a/src/freedreno/ir3/tests/disasm.c b/src/freedreno/ir3/tests/disasm.c index c1b85ab621d..1de2f808cda 100644 --- a/src/freedreno/ir3/tests/disasm.c +++ b/src/freedreno/ir3/tests/disasm.c @@ -103,6 +103,8 @@ static const struct test { INSTR_6XX(20400006_00003800, "mov.f16f16 hr1.z, h(0.500000)"), INSTR_6XX(204880f5_00000000, "mova1 a1.x, 0"), + INSTR_7XX(2004c005_00000405, "cov.f32u32 r1.y, (last)r1.y"), + /* cat2 */ INSTR_6XX(40104002_0c210001, "add.f hr0.z, r0.y, c"), INSTR_6XX(40b80804_10408004, "(nop3) cmps.f.lt r1.x, (abs)r1.x, c16.x"), @@ -120,6 +122,9 @@ static const struct test { INSTR_6XX(46b00001_00001020, "clz.b r0.y, c8.x"), INSTR_6XX(46700009_00000009, "bfrev.b r2.y, r2.y"), + INSTR_7XX(42380800_04010400, "(nop3) add.s r0.x, (last)r0.x, (last)r0.y"), + INSTR_7XX(42930000_04000406, "cmps.u.ge r0.x, (last)r1.z, (last)r0.x"), + /* cat3 */ INSTR_6XX(66000000_10421041, "sel.f16 hr0.x, hc16.y, hr0.x, hc16.z"), INSTR_6XX(64848109_109a9099, "(rpt1)sel.b32 r2.y, c38.y, (r)r2.y, c38.z"), @@ -143,6 +148,9 @@ static const struct test { INSTR_6XX(66818c02_0002e003, "(sat)(nop3) dp2acc.mixed.low r0.z, r0.w, r0.w, r0.z"), /* (nop3) dp2acc (sat)r0.z, (signed)(low)(r)r0.w, (low)(r)r0.w, r0.z */ INSTR_6XX(6681c802_8002a003, "(nop3) dp4acc.unsigned.low r0.z, r0.w, r0.w, (neg)r0.z"), /* (nop3) dp4acc r0.z, (unsigned)(r)r0.w, (r)r0.w, (neg)r0.z */ + INSTR_7XX(61808000_04020400, "madsh.m16 r0.x, (last)r0.x, r0.y, (last)r0.z"), + INSTR_7XX(64838806_04088406, "(nop3) sel.b32 r1.z, (last)r1.z, r1.w, (last)r2.x"), + /* cat4 */ INSTR_6XX(8010000a_00000003, "rcp r2.z, r0.w"), diff --git a/src/freedreno/isa/ir3-cat1.xml b/src/freedreno/isa/ir3-cat1.xml index 34a893b1cf5..b5fee7f495d 100644 --- a/src/freedreno/isa/ir3-cat1.xml +++ b/src/freedreno/isa/ir3-cat1.xml @@ -223,7 +223,7 @@ SOFTWARE. - {SRC_R}{HALF}{SRC} + {LAST}{SRC_R}{HALF}{SRC} @@ -275,12 +275,18 @@ SOFTWARE. + - 000000000000000000000000 + 00 + + 000000000000000000000 00 + + !!(src->srcs[0]->flags & IR3_REG_LAST_USE) + diff --git a/src/freedreno/isa/ir3-cat3.xml b/src/freedreno/isa/ir3-cat3.xml index d3bb351ee3b..4e53472cea5 100644 --- a/src/freedreno/isa/ir3-cat3.xml +++ b/src/freedreno/isa/ir3-cat3.xml @@ -40,12 +40,15 @@ SOFTWARE. - {HALF}{SRC} + {LAST}{HALF}{SRC} - 00000 + 00 + + 00 src + !!(src->flags & IR3_REG_LAST_USE) diff --git a/src/freedreno/isa/ir3-common.xml b/src/freedreno/isa/ir3-common.xml index b6717b557e3..09afc2648cc 100644 --- a/src/freedreno/isa/ir3-common.xml +++ b/src/freedreno/isa/ir3-common.xml @@ -199,12 +199,17 @@ SOFTWARE. - {ABSNEG}{SRC_R}{HALF}{SRC} + {LAST}{ABSNEG}{SRC_R}{HALF}{SRC} - 000000 + 00 + + 000 + + !!(src->flags & IR3_REG_LAST_USE) +