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