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