• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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)18 is_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)34 is_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)45 ir3_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