• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2024 Imagination Technologies Ltd.
3  *
4  * SPDX-License-Identifier: MIT
5  */
6 
7 /**
8  * \file pco_const_imms.c
9  *
10  * \brief PCO constant immediates lowering pass.
11  */
12 
13 #include "pco.h"
14 #include "pco_builder.h"
15 #include "pco_internal.h"
16 #include "util/macros.h"
17 
18 #include <stdbool.h>
19 #include <stdint.h>
20 #include <stdlib.h>
21 
22 /** Mapping of constant register values and their indices. */
23 struct const_reg_def {
24    uint32_t val;
25    uint8_t idx;
26    bool flr : 1;
27    bool neg : 1;
28 };
29 
30 /** Constant register values (sorted for bsearch). */
31 static const struct const_reg_def const_reg_defs[] = {
32    { 0x00000000, 0, false, false },   { 0x00000001, 1, false, false },
33    { 0x00000002, 2, false, false },   { 0x00000003, 3, false, false },
34    { 0x00000004, 4, false, false },   { 0x00000005, 5, false, false },
35    { 0x00000006, 6, false, false },   { 0x00000007, 7, false, false },
36    { 0x00000008, 8, false, false },   { 0x00000009, 9, false, false },
37    { 0x0000000a, 10, false, false },  { 0x0000000b, 11, false, false },
38    { 0x0000000c, 12, false, false },  { 0x0000000d, 13, false, false },
39    { 0x0000000e, 14, false, false },  { 0x0000000f, 15, false, false },
40    { 0x00000010, 16, false, false },  { 0x00000011, 17, false, false },
41    { 0x00000012, 18, false, false },  { 0x00000013, 19, false, false },
42    { 0x00000014, 20, false, false },  { 0x00000015, 21, false, false },
43    { 0x00000016, 22, false, false },  { 0x00000017, 23, false, false },
44    { 0x00000018, 24, false, false },  { 0x00000019, 25, false, false },
45    { 0x0000001a, 26, false, false },  { 0x0000001b, 27, false, false },
46    { 0x0000001c, 28, false, false },  { 0x0000001d, 29, false, false },
47    { 0x0000001e, 30, false, false },  { 0x0000001f, 31, false, false },
48    { 0x0000007f, 147, false, false }, { 0x37800000, 134, false, false },
49    { 0x38000000, 135, false, false }, { 0x38800000, 88, false, false },
50    { 0x39000000, 87, false, false },  { 0x39800000, 86, false, false },
51    { 0x3a000000, 85, false, false },  { 0x3a800000, 84, false, false },
52    { 0x3b000000, 83, false, false },  { 0x3b4d2e1c, 136, false, false },
53    { 0x3b800000, 82, false, false },  { 0x3c000000, 81, false, false },
54    { 0x3c800000, 80, false, false },  { 0x3d000000, 79, false, false },
55    { 0x3d25aee6, 156, false, false }, { 0x3d6147ae, 140, false, false },
56    { 0x3d800000, 78, false, false },  { 0x3d9e8391, 157, false, false },
57    { 0x3e000000, 77, false, false },  { 0x3e2aaaab, 153, false, false },
58    { 0x3e800000, 76, false, false },  { 0x3e9a209b, 145, false, false },
59    { 0x3ea2f983, 128, false, false }, { 0x3eaaaaab, 152, false, false },
60    { 0x3ebc5ab2, 90, false, false },  { 0x3ed55555, 138, false, false },
61    { 0x3f000000, 75, false, false },  { 0x3f22f983, 129, false, false },
62    { 0x3f317218, 146, false, false }, { 0x3f3504f3, 92, false, false },
63    { 0x3f490fdb, 93, false, false },  { 0x3f72a76f, 158, false, false },
64    { 0x3f800000, 64, false, false },  { 0x3f860a92, 151, false, false },
65    { 0x3f870a3d, 139, false, false }, { 0x3fa2f983, 130, false, false },
66    { 0x3fb504f3, 91, false, false },  { 0x3fb8aa3b, 155, false, false },
67    { 0x3fc90fdb, 94, false, false },  { 0x40000000, 65, false, false },
68    { 0x4019999a, 159, false, false }, { 0x402df854, 89, false, false },
69    { 0x40400000, 95, true, false },   { 0x40490fdb, 95, false, false },
70    { 0x40549a78, 154, false, false }, { 0x40800000, 66, false, false },
71    { 0x40c00000, 131, true, false },  { 0x40c90fdb, 131, false, false },
72    { 0x41000000, 67, false, false },  { 0x41400000, 132, true, false },
73    { 0x41490fdb, 132, false, false }, { 0x414eb852, 137, false, false },
74    { 0x41800000, 68, false, false },  { 0x41c80000, 133, true, false },
75    { 0x41c90fdb, 133, false, false }, { 0x42000000, 69, false, false },
76    { 0x42800000, 70, false, false },  { 0x43000000, 71, false, false },
77    { 0x43800000, 72, false, false },  { 0x44000000, 73, false, false },
78    { 0x44800000, 74, false, false },  { 0x4b000000, 149, false, false },
79    { 0x4b800000, 150, false, false }, { 0x7f7fffff, 148, false, false },
80    { 0x7f800000, 142, false, false }, { 0x7fff7fff, 144, false, false },
81    { 0x7fffffff, 143, false, true },  { 0x80000000, 141, false, false },
82    { 0x80000001, 1, false, true },    { 0x80000002, 2, false, true },
83    { 0x80000003, 3, false, true },    { 0x80000004, 4, false, true },
84    { 0x80000005, 5, false, true },    { 0x80000006, 6, false, true },
85    { 0x80000007, 7, false, true },    { 0x80000008, 8, false, true },
86    { 0x80000009, 9, false, true },    { 0x8000000a, 10, false, true },
87    { 0x8000000b, 11, false, true },   { 0x8000000c, 12, false, true },
88    { 0x8000000d, 13, false, true },   { 0x8000000e, 14, false, true },
89    { 0x8000000f, 15, false, true },   { 0x80000010, 16, false, true },
90    { 0x80000011, 17, false, true },   { 0x80000012, 18, false, true },
91    { 0x80000013, 19, false, true },   { 0x80000014, 20, false, true },
92    { 0x80000015, 21, false, true },   { 0x80000016, 22, false, true },
93    { 0x80000017, 23, false, true },   { 0x80000018, 24, false, true },
94    { 0x80000019, 25, false, true },   { 0x8000001a, 26, false, true },
95    { 0x8000001b, 27, false, true },   { 0x8000001c, 28, false, true },
96    { 0x8000001d, 29, false, true },   { 0x8000001e, 30, false, true },
97    { 0x8000001f, 31, false, true },   { 0x8000007f, 147, false, true },
98    { 0xb7800000, 134, false, true },  { 0xb8000000, 135, false, true },
99    { 0xb8800000, 88, false, true },   { 0xb9000000, 87, false, true },
100    { 0xb9800000, 86, false, true },   { 0xba000000, 85, false, true },
101    { 0xba800000, 84, false, true },   { 0xbb000000, 83, false, true },
102    { 0xbb4d2e1c, 136, false, true },  { 0xbb800000, 82, false, true },
103    { 0xbc000000, 81, false, true },   { 0xbc800000, 80, false, true },
104    { 0xbd000000, 79, false, true },   { 0xbd25aee6, 156, false, true },
105    { 0xbd6147ae, 140, false, true },  { 0xbd800000, 78, false, true },
106    { 0xbd9e8391, 157, false, true },  { 0xbe000000, 77, false, true },
107    { 0xbe2aaaab, 153, false, true },  { 0xbe800000, 76, false, true },
108    { 0xbe9a209b, 145, false, true },  { 0xbea2f983, 128, false, true },
109    { 0xbeaaaaab, 152, false, true },  { 0xbebc5ab2, 90, false, true },
110    { 0xbed55555, 138, false, true },  { 0xbf000000, 75, false, true },
111    { 0xbf22f983, 129, false, true },  { 0xbf317218, 146, false, true },
112    { 0xbf3504f3, 92, false, true },   { 0xbf490fdb, 93, false, true },
113    { 0xbf72a76f, 158, false, true },  { 0xbf800000, 64, false, true },
114    { 0xbf860a92, 151, false, true },  { 0xbf870a3d, 139, false, true },
115    { 0xbfa2f983, 130, false, true },  { 0xbfb504f3, 91, false, true },
116    { 0xbfb8aa3b, 155, false, true },  { 0xbfc90fdb, 94, false, true },
117    { 0xc0000000, 65, false, true },   { 0xc019999a, 159, false, true },
118    { 0xc02df854, 89, false, true },   { 0xc0400000, 95, true, true },
119    { 0xc0490fdb, 95, false, true },   { 0xc0549a78, 154, false, true },
120    { 0xc0800000, 66, false, true },   { 0xc0c00000, 131, true, true },
121    { 0xc0c90fdb, 131, false, true },  { 0xc1000000, 67, false, true },
122    { 0xc1400000, 132, true, true },   { 0xc1490fdb, 132, false, true },
123    { 0xc14eb852, 137, false, true },  { 0xc1800000, 68, false, true },
124    { 0xc1c80000, 133, true, true },   { 0xc1c90fdb, 133, false, true },
125    { 0xc2000000, 69, false, true },   { 0xc2800000, 70, false, true },
126    { 0xc3000000, 71, false, true },   { 0xc3800000, 72, false, true },
127    { 0xc4000000, 73, false, true },   { 0xc4800000, 74, false, true },
128    { 0xcb000000, 149, false, true },  { 0xcb800000, 150, false, true },
129    { 0xff7fffff, 148, false, true },  { 0xff800000, 142, false, true },
130    { 0xffff7fff, 144, false, true },  { 0xffffffff, 143, false, false },
131 };
132 
133 /**
134  * \brief Comparison function for bsearch() to support rogue_const_reg_def.
135  *
136  * \param[in] lhs The left hand side of the comparison.
137  * \param[in] rhs The right hand side of the comparison.
138  * \return 0 if (lhs == rhs), -1 if (lhs < rhs), 1 if (lhs > rhs).
139  */
constreg_cmp(const void * lhs,const void * rhs)140 static int constreg_cmp(const void *lhs, const void *rhs)
141 {
142    const struct const_reg_def *l = lhs;
143    const struct const_reg_def *r = rhs;
144 
145    if (l->val < r->val)
146       return -1;
147    else if (l->val > r->val)
148       return 1;
149 
150    return 0;
151 }
152 
153 /**
154  * \brief Looks up an immediate in constant registers.
155  *
156  * \param[in] imm The immediate to lookup.
157  * \return A pointer to the constant register definition,
158  *         or NULL if no constant register was found.
159  */
constreg_lookup(uint32_t imm)160 inline static const struct const_reg_def *constreg_lookup(uint32_t imm)
161 {
162    return bsearch(&(struct const_reg_def){ .val = imm },
163                   const_reg_defs,
164                   ARRAY_SIZE(const_reg_defs),
165                   sizeof(*const_reg_defs),
166                   constreg_cmp);
167 }
168 
169 /**
170  * \brief Converts immediates into constant register lookups where possible.
171  *
172  * \param[in,out] shader PCO shader.
173  * \return True if the pass made progress.
174  */
pco_const_imms(pco_shader * shader)175 bool pco_const_imms(pco_shader *shader)
176 {
177    bool progress = false;
178 
179    pco_foreach_func_in_shader (func, shader) {
180       pco_foreach_instr_in_func_safe (instr, func) {
181          if (instr->op != PCO_OP_MOVI32)
182             continue;
183 
184          const struct const_reg_def *const_reg_def =
185             constreg_lookup(pco_ref_get_imm(instr->src[0]));
186 
187          if (!const_reg_def)
188             continue;
189 
190          pco_builder b =
191             pco_builder_create(func, pco_cursor_before_instr(instr));
192 
193          pco_ref dest = instr->dest[0];
194          pco_ref const_reg =
195             pco_ref_hwreg(const_reg_def->idx, PCO_REG_CLASS_CONST);
196 
197          if (!const_reg_def->flr && !const_reg_def->neg) {
198             pco_mov(&b, dest, const_reg);
199          } else if (!const_reg_def->flr && const_reg_def->neg) {
200             pco_neg(&b, dest, const_reg);
201          } else if (const_reg_def->flr && !const_reg_def->neg) {
202             pco_flr(&b, dest, const_reg);
203          } else {
204             /* TODO: use floor and neg mods when support for > 1 is added. */
205             const_reg = pco_ref_flr(const_reg);
206             const_reg = pco_ref_neg(const_reg);
207 
208             pco_fadd(&b, dest, const_reg, pco_zero);
209          }
210 
211          pco_instr_delete(instr);
212          progress = true;
213       }
214    }
215 
216    return progress;
217 }
218