From 7c1fe4bdbe78ec8ef2dc36c465544b40505fdc2b Mon Sep 17 00:00:00 2001 From: antonino Date: Tue, 20 Aug 2024 22:04:16 -0400 Subject: [PATCH] pan/cs: add helpers to generate csf loop MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support for loops where we continually check whether a condition is met. Also add a `cs_while` pseudo-instruction to more easily use that feature. Signed-off-by: Antonino Maniscalco Reviewed-by: Boris Brezillon Reviewed-by: Louis-Francis Ratté-Boulianne Reviewed-by: Mary Guillemard Part-of: --- src/panfrost/.clang-format | 1 + src/panfrost/lib/genxml/cs_builder.h | 100 +++++++++++++++++++++++++++ 2 files changed, 101 insertions(+) diff --git a/src/panfrost/.clang-format b/src/panfrost/.clang-format index d974a0547a6..c926aabb178 100644 --- a/src/panfrost/.clang-format +++ b/src/panfrost/.clang-format @@ -6,3 +6,4 @@ AlignConsecutiveBitFields: true ColumnLimit: 80 BreakStringLiterals: false SpaceBeforeParens: ControlStatementsExceptControlMacros +ForEachMacros: ['cs_while'] diff --git a/src/panfrost/lib/genxml/cs_builder.h b/src/panfrost/lib/genxml/cs_builder.h index 2d7011bf878..2b0d2887a2b 100644 --- a/src/panfrost/lib/genxml/cs_builder.h +++ b/src/panfrost/lib/genxml/cs_builder.h @@ -609,6 +609,106 @@ cs_set_label(struct cs_builder *b, struct cs_label *label) } } +struct cs_loop { + struct cs_label start, end; + struct cs_block block; + enum mali_cs_condition cond; + struct cs_index val; +}; + +static inline enum mali_cs_condition +cs_invert_cond(enum mali_cs_condition cond) +{ + switch (cond) { + case MALI_CS_CONDITION_LEQUAL: + return MALI_CS_CONDITION_GREATER; + case MALI_CS_CONDITION_EQUAL: + return MALI_CS_CONDITION_NEQUAL; + case MALI_CS_CONDITION_LESS: + return MALI_CS_CONDITION_GEQUAL; + case MALI_CS_CONDITION_GREATER: + return MALI_CS_CONDITION_LEQUAL; + case MALI_CS_CONDITION_NEQUAL: + return MALI_CS_CONDITION_EQUAL; + case MALI_CS_CONDITION_GEQUAL: + return MALI_CS_CONDITION_LESS; + case MALI_CS_CONDITION_ALWAYS: + unreachable("cannot invert ALWAYS"); + default: + unreachable("invalid cond"); + } +} + +static inline struct cs_loop * +cs_do_while_start(struct cs_builder *b, struct cs_loop *loop, + enum mali_cs_condition cond, struct cs_index val) +{ + cs_block_start(b, &loop->block); + cs_label_init(&loop->start); + cs_label_init(&loop->end); + cs_set_label(b, &loop->start); + loop->cond = cond; + loop->val = val; + return loop; +} + +static inline struct cs_loop * +cs_while_start(struct cs_builder *b, struct cs_loop *loop, + enum mali_cs_condition cond, struct cs_index val) +{ + cs_do_while_start(b, loop, cond, val); + + /* Do an initial check on the condition, and if it's false, jump to + * the end of the loop block. For 'while(true)' loops, skip the + * conditional branch. + */ + if (cond != MALI_CS_CONDITION_ALWAYS) + cs_branch_label(b, &loop->end, cs_invert_cond(cond), val); + + return loop; +} + +static inline void +cs_loop_continue(struct cs_builder *b, enum mali_cs_condition cond, + struct cs_index val) +{ + assert(b->blocks.cur); + + struct cs_loop *loop = container_of(b->blocks.cur, struct cs_loop, block); + + cs_branch_label(b, &loop->start, cond, val); +} + +static inline void +cs_loop_break(struct cs_builder *b, enum mali_cs_condition cond, + struct cs_index val) +{ + assert(b->blocks.cur); + + struct cs_loop *loop = container_of(b->blocks.cur, struct cs_loop, block); + + cs_branch_label(b, &loop->end, cond, val); +} + +static inline void +cs_while_end(struct cs_builder *b) +{ + assert(b->blocks.cur); + + struct cs_loop *loop = container_of(b->blocks.cur, struct cs_loop, block); + + cs_branch_label(b, &loop->start, loop->cond, loop->val); + cs_set_label(b, &loop->end); + cs_block_end(b); +} + +#define cs_while(__b, cond, val) \ + for (struct cs_loop __loop_storage, \ + *__loop = cs_while_start(__b, &__loop_storage, cond, val); \ + __loop != NULL; cs_while_end(__b), __loop = NULL) + +/* Pseudoinstructions follow */ + static inline void cs_move64_to(struct cs_builder *b, struct cs_index dest, uint64_t imm) {