1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright 2022 Google LLC 3bf215546Sopenharmony_ci * SPDX-License-Identifier: MIT 4bf215546Sopenharmony_ci */ 5bf215546Sopenharmony_ci 6bf215546Sopenharmony_ci#include "ir3.h" 7bf215546Sopenharmony_ci 8bf215546Sopenharmony_ci/* 9bf215546Sopenharmony_ci * Mark (ul) on the last user of a0 before a0 is loaded again. emit_block 10bf215546Sopenharmony_ci * makes sure a0 is loaded first if there is any user in the block. This 11bf215546Sopenharmony_ci * allows us to process each block independently. 12bf215546Sopenharmony_ci * 13bf215546Sopenharmony_ci * Note that this must be called before passes that break the assumption, such 14bf215546Sopenharmony_ci * as ir3_lower_subgroups. 15bf215546Sopenharmony_ci */ 16bf215546Sopenharmony_ci 17bf215546Sopenharmony_cistatic bool 18bf215546Sopenharmony_ciis_reg_relative(const struct ir3_instruction *instr) 19bf215546Sopenharmony_ci{ 20bf215546Sopenharmony_ci foreach_dst (reg, instr) { 21bf215546Sopenharmony_ci if (reg->flags & IR3_REG_RELATIV) 22bf215546Sopenharmony_ci return true; 23bf215546Sopenharmony_ci } 24bf215546Sopenharmony_ci 25bf215546Sopenharmony_ci foreach_src (reg, instr) { 26bf215546Sopenharmony_ci if (reg->flags & IR3_REG_RELATIV) 27bf215546Sopenharmony_ci return true; 28bf215546Sopenharmony_ci } 29bf215546Sopenharmony_ci 30bf215546Sopenharmony_ci return false; 31bf215546Sopenharmony_ci} 32bf215546Sopenharmony_ci 33bf215546Sopenharmony_cistatic bool 34bf215546Sopenharmony_ciis_dst_a0(const struct ir3_instruction *instr) 35bf215546Sopenharmony_ci{ 36bf215546Sopenharmony_ci foreach_dst (reg, instr) { 37bf215546Sopenharmony_ci if (reg->num == regid(REG_A0, 0)) 38bf215546Sopenharmony_ci return true; 39bf215546Sopenharmony_ci } 40bf215546Sopenharmony_ci 41bf215546Sopenharmony_ci return false; 42bf215546Sopenharmony_ci} 43bf215546Sopenharmony_ci 44bf215546Sopenharmony_cibool 45bf215546Sopenharmony_ciir3_legalize_relative(struct ir3 *ir) 46bf215546Sopenharmony_ci{ 47bf215546Sopenharmony_ci foreach_block (block, &ir->block_list) { 48bf215546Sopenharmony_ci struct ir3_instruction *last_user = NULL; 49bf215546Sopenharmony_ci 50bf215546Sopenharmony_ci foreach_instr (instr, &block->instr_list) { 51bf215546Sopenharmony_ci if (is_reg_relative(instr)) 52bf215546Sopenharmony_ci last_user = instr; 53bf215546Sopenharmony_ci 54bf215546Sopenharmony_ci /* Is it valid to have address reg loaded from a relative src (ie. 55bf215546Sopenharmony_ci * mova a0, c<a0.x+4>)? This marks the load (ul), which may or may 56bf215546Sopenharmony_ci * not be valid. 57bf215546Sopenharmony_ci */ 58bf215546Sopenharmony_ci if (last_user && is_dst_a0(instr)) { 59bf215546Sopenharmony_ci last_user->flags |= IR3_INSTR_UL; 60bf215546Sopenharmony_ci last_user = NULL; 61bf215546Sopenharmony_ci } 62bf215546Sopenharmony_ci } 63bf215546Sopenharmony_ci 64bf215546Sopenharmony_ci if (last_user) 65bf215546Sopenharmony_ci last_user->flags |= IR3_INSTR_UL; 66bf215546Sopenharmony_ci } 67bf215546Sopenharmony_ci 68bf215546Sopenharmony_ci return true; 69bf215546Sopenharmony_ci} 70