From fb5e5adfb35958eb1db3dedace36fb973b2dc4a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Sch=C3=BCrmann?= Date: Thu, 14 Nov 2024 13:02:19 +0100 Subject: [PATCH] aco/insert_NOPs: implement vector-based RegCounterMap as replacement for VGPRCounterMap Part-of: --- src/amd/compiler/aco_insert_NOPs.cpp | 83 ++++++++++++++++++++++++++-- 1 file changed, 77 insertions(+), 6 deletions(-) diff --git a/src/amd/compiler/aco_insert_NOPs.cpp b/src/amd/compiler/aco_insert_NOPs.cpp index ad7942501e1..07fcbf86f54 100644 --- a/src/amd/compiler/aco_insert_NOPs.cpp +++ b/src/amd/compiler/aco_insert_NOPs.cpp @@ -164,6 +164,73 @@ struct NOP_ctx_gfx10 { } }; +template struct RegCounterMap { + void inc() { base++; } + void set(PhysReg reg) { update(reg, 0); } + + uint8_t get(PhysReg reg) + { + if (present.test(reg.reg() & 0x7F)) { + for (entry& e : list) { + if (e.reg == reg.reg()) + return MIN2(base - e.val, Max); + } + } + return Max; + } + + void reset() + { + present.reset(); + list.clear(); + base = 0; + } + + void join_min(const RegCounterMap& other) + { + for (const entry& e : other.list) { + int idx = other.base - e.val; + if (idx >= Max) + continue; + + update(e.reg, idx); + } + } + + void update(uint16_t reg, int idx) + { + int16_t val = base - idx; + for (entry& e : list) { + if (e.reg == reg) { + e.val = MAX2(e.val, val); + return; + } + } + list.push_back(entry{reg, val}); + present.set(reg & 0x7F); + } + + bool operator==(const RegCounterMap& other) const + { + /* Two maps with different bases could also be equal, but for our use case, + * i.e. checking for changes at loop headers, this is sufficient since we + * always join the predecessors into an empty map with base=0. + */ + return base == other.base && list == other.list; + } + +private: + struct entry { + uint16_t reg; + int16_t val; + bool operator==(const entry& other) const { return reg == other.reg && val == other.val; } + }; + + std::bitset<128> present; + std::vector list; + int base = 0; +}; + template struct CounterMap { public: int base = 0; @@ -263,8 +330,8 @@ struct NOP_ctx_gfx11 { std::bitset<256> vgpr_used_by_ds; /* VALUTransUseHazard */ - VGPRCounterMap<15> valu_since_wr_by_trans; - VGPRCounterMap<2> trans_since_wr_by_trans; + RegCounterMap<6> valu_since_wr_by_trans; + RegCounterMap<2> trans_since_wr_by_trans; /* VALUMaskWriteHazard */ std::bitset<128> sgpr_read_by_valu_as_lanemask; @@ -1449,8 +1516,9 @@ handle_instruction_gfx11(State& state, NOP_ctx_gfx11& ctx, aco_ptr& if (op.physReg().reg() < 256) continue; for (unsigned i = 0; i < op.size(); i++) { - num_valu = std::min(num_valu, ctx.valu_since_wr_by_trans.get(op.physReg(), i)); - num_trans = std::min(num_trans, ctx.trans_since_wr_by_trans.get(op.physReg(), i)); + PhysReg reg = op.physReg().advance(i * 4); + num_valu = std::min(num_valu, ctx.valu_since_wr_by_trans.get(reg)); + num_trans = std::min(num_trans, ctx.trans_since_wr_by_trans.get(reg)); } } if (num_trans <= 1 && num_valu <= 5) { @@ -1500,8 +1568,11 @@ handle_instruction_gfx11(State& state, NOP_ctx_gfx11& ctx, aco_ptr& if (is_trans) { for (Definition& def : instr->definitions) { - ctx.valu_since_wr_by_trans.set(def.physReg(), def.bytes()); - ctx.trans_since_wr_by_trans.set(def.physReg(), def.bytes()); + for (unsigned i = 0; i < def.size(); i++) { + PhysReg reg = def.physReg().advance(i * 4); + ctx.valu_since_wr_by_trans.set(reg); + ctx.trans_since_wr_by_trans.set(reg); + } } }