/* * Copyright 2022 Google LLC * SPDX-License-Identifier: MIT */ #include "ir3.h" /* * Mark (ul) on the last user of a0 before a0 is loaded again. emit_block * makes sure a0 is loaded first if there is any user in the block. This * allows us to process each block independently. * * Note that this must be called before passes that break the assumption, such * as ir3_lower_subgroups. */ static bool is_reg_relative(const struct ir3_instruction *instr) { foreach_dst (reg, instr) { if (reg->flags & IR3_REG_RELATIV) return true; } foreach_src (reg, instr) { if (reg->flags & IR3_REG_RELATIV) return true; } return false; } static bool is_dst_a0(const struct ir3_instruction *instr) { foreach_dst (reg, instr) { if (reg->num == regid(REG_A0, 0)) return true; } return false; } bool ir3_legalize_relative(struct ir3 *ir) { foreach_block (block, &ir->block_list) { struct ir3_instruction *last_user = NULL; foreach_instr (instr, &block->instr_list) { if (is_reg_relative(instr)) last_user = instr; /* Is it valid to have address reg loaded from a relative src (ie. * mova a0, c)? This marks the load (ul), which may or may * not be valid. */ if (last_user && is_dst_a0(instr)) { last_user->flags |= IR3_INSTR_UL; last_user = NULL; } } if (last_user) last_user->flags |= IR3_INSTR_UL; } return true; }