xref: /aosp_15_r20/external/mesa3d/src/imagination/rogue/passes/rogue_dce.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © 2022 Imagination Technologies Ltd.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to deal
6  * in the Software without restriction, including without limitation the rights
7  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  * copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21  * SOFTWARE.
22  */
23 
24 #include "rogue.h"
25 #include "util/macros.h"
26 
27 #include <stdbool.h>
28 
29 /**
30  * \file rogue_dce.c
31  *
32  * \brief Contains the rogue_dce pass.
33  */
34 
35 /* TODO:
36  * 0) Add bools/flags to registers in rogue_info that specifies whether they can
37  * be I/O registers (i.e. populated by driver/used by driver).
38  * 1) Loop through instructions and delete ones that have their destinations
39  * unused (with exception of pixel output, shared, etc.).
40  * 2) Loop through registers and delete ones that have no uses/writes.
41  */
42 
rogue_dce_alu_instr(rogue_alu_instr * alu)43 static bool rogue_dce_alu_instr(rogue_alu_instr *alu)
44 {
45    bool progress = false;
46 
47    switch (alu->op) {
48    case ROGUE_ALU_OP_MOV:
49    case ROGUE_ALU_OP_MBYP:
50       if (!alu->mod && rogue_instr_dst_src_equal(&alu->dst[0], &alu->src[0])) {
51          rogue_instr_delete(&alu->instr);
52          progress = true;
53       }
54       break;
55 
56    default:
57       break;
58    }
59 
60    return progress;
61 }
62 
rogue_dce_instrs(rogue_shader * shader)63 static bool rogue_dce_instrs(rogue_shader *shader)
64 {
65    bool progress = false;
66 
67    rogue_foreach_instr_in_shader_safe (instr, shader) {
68       switch (instr->type) {
69       case ROGUE_INSTR_TYPE_ALU:
70          progress |= rogue_dce_alu_instr(rogue_instr_as_alu(instr));
71          break;
72 
73       case ROGUE_INSTR_TYPE_BACKEND:
74          break;
75 
76       case ROGUE_INSTR_TYPE_CTRL:
77          break;
78 
79       case ROGUE_INSTR_TYPE_BITWISE:
80          break;
81 
82       default:
83          unreachable("Unsupported instruction type.");
84          return false;
85       }
86    }
87 
88    return progress;
89 }
90 
91 /* TODO: Do this in rogue_trim instead? */
rogue_try_release_reg(rogue_reg * reg)92 static bool rogue_try_release_reg(rogue_reg *reg)
93 {
94    /* Check if the register is used or written to. */
95    if (!rogue_reg_is_unused(reg))
96       return false;
97 
98    /* Check if the register is part of a regarray. */
99    if (reg->regarray)
100       return false;
101 
102    /* Register is unused, delete it. */
103    rogue_reg_delete(reg);
104 
105    return true;
106 }
107 
rogue_dce_regs(rogue_shader * shader)108 static bool rogue_dce_regs(rogue_shader *shader)
109 {
110    bool progress = false;
111 
112    /* Remove unused SSA/temp registers that aren't in any regarrays. */
113    rogue_foreach_reg_safe (reg, shader, ROGUE_REG_CLASS_SSA) {
114       progress |= rogue_try_release_reg(reg);
115    }
116 
117    rogue_foreach_reg_safe (reg, shader, ROGUE_REG_CLASS_TEMP) {
118       progress |= rogue_try_release_reg(reg);
119    }
120 
121    return progress;
122 }
123 
124 PUBLIC
rogue_dce(rogue_shader * shader)125 bool rogue_dce(rogue_shader *shader)
126 {
127    if (shader->is_grouped)
128       return false;
129 
130    bool progress = false;
131 
132    progress |= rogue_dce_instrs(shader);
133    progress |= rogue_dce_regs(shader);
134 
135    return progress;
136 }
137