Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/drivers/r300/compiler/radeon_remove_constants.c
4574 views
1
/*
2
* Copyright (C) 2010 Marek Olšák <[email protected]>
3
*
4
* All Rights Reserved.
5
*
6
* Permission is hereby granted, free of charge, to any person obtaining
7
* a copy of this software and associated documentation files (the
8
* "Software"), to deal in the Software without restriction, including
9
* without limitation the rights to use, copy, modify, merge, publish,
10
* distribute, sublicense, and/or sell copies of the Software, and to
11
* permit persons to whom the Software is furnished to do so, subject to
12
* the following conditions:
13
*
14
* The above copyright notice and this permission notice (including the
15
* next paragraph) shall be included in all copies or substantial
16
* portions of the Software.
17
*
18
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21
* IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
22
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
*
26
*/
27
28
#include <stdlib.h>
29
#include "radeon_remove_constants.h"
30
#include "radeon_dataflow.h"
31
32
struct mark_used_data {
33
unsigned char * const_used;
34
unsigned * has_rel_addr;
35
};
36
37
static void remap_regs(void * userdata, struct rc_instruction * inst,
38
rc_register_file * pfile, unsigned int * pindex)
39
{
40
unsigned *inv_remap_table = userdata;
41
42
if (*pfile == RC_FILE_CONSTANT) {
43
*pindex = inv_remap_table[*pindex];
44
}
45
}
46
47
static void mark_used(void * userdata, struct rc_instruction * inst,
48
struct rc_src_register * src)
49
{
50
struct mark_used_data * d = userdata;
51
52
if (src->File == RC_FILE_CONSTANT) {
53
if (src->RelAddr) {
54
*d->has_rel_addr = 1;
55
} else {
56
d->const_used[src->Index] = 1;
57
}
58
}
59
}
60
61
void rc_remove_unused_constants(struct radeon_compiler *c, void *user)
62
{
63
unsigned **out_remap_table = (unsigned**)user;
64
unsigned char *const_used;
65
unsigned *remap_table;
66
unsigned *inv_remap_table;
67
unsigned has_rel_addr = 0;
68
unsigned is_identity = 1;
69
unsigned are_externals_remapped = 0;
70
struct rc_constant *constants = c->Program.Constants.Constants;
71
struct mark_used_data d;
72
unsigned new_count;
73
74
if (!c->Program.Constants.Count) {
75
*out_remap_table = NULL;
76
return;
77
}
78
79
const_used = malloc(c->Program.Constants.Count);
80
memset(const_used, 0, c->Program.Constants.Count);
81
82
d.const_used = const_used;
83
d.has_rel_addr = &has_rel_addr;
84
85
/* Pass 1: Mark used constants. */
86
for (struct rc_instruction *inst = c->Program.Instructions.Next;
87
inst != &c->Program.Instructions; inst = inst->Next) {
88
rc_for_all_reads_src(inst, mark_used, &d);
89
}
90
91
/* Pass 2: If there is relative addressing or dead constant elimination
92
* is disabled, mark all externals as used. */
93
if (has_rel_addr || !c->remove_unused_constants) {
94
for (unsigned i = 0; i < c->Program.Constants.Count; i++)
95
if (constants[i].Type == RC_CONSTANT_EXTERNAL)
96
const_used[i] = 1;
97
}
98
99
/* Pass 3: Make the remapping table and remap constants.
100
* This pass removes unused constants simply by overwriting them by other constants. */
101
remap_table = malloc(c->Program.Constants.Count * sizeof(unsigned));
102
inv_remap_table = malloc(c->Program.Constants.Count * sizeof(unsigned));
103
new_count = 0;
104
105
for (unsigned i = 0; i < c->Program.Constants.Count; i++) {
106
if (const_used[i]) {
107
remap_table[new_count] = i;
108
inv_remap_table[i] = new_count;
109
110
if (i != new_count) {
111
if (constants[i].Type == RC_CONSTANT_EXTERNAL)
112
are_externals_remapped = 1;
113
114
constants[new_count] = constants[i];
115
is_identity = 0;
116
}
117
new_count++;
118
}
119
}
120
121
/* is_identity ==> new_count == old_count
122
* !is_identity ==> new_count < old_count */
123
assert( is_identity || new_count < c->Program.Constants.Count);
124
assert(!((has_rel_addr || !c->remove_unused_constants) && are_externals_remapped));
125
126
/* Pass 4: Redirect reads of all constants to their new locations. */
127
if (!is_identity) {
128
for (struct rc_instruction *inst = c->Program.Instructions.Next;
129
inst != &c->Program.Instructions; inst = inst->Next) {
130
rc_remap_registers(inst, remap_regs, inv_remap_table);
131
}
132
}
133
134
/* Set the new constant count. Note that new_count may be less than
135
* Count even though the remapping function is identity. In that case,
136
* the constants have been removed at the end of the array. */
137
c->Program.Constants.Count = new_count;
138
139
if (are_externals_remapped) {
140
*out_remap_table = remap_table;
141
} else {
142
*out_remap_table = NULL;
143
free(remap_table);
144
}
145
146
free(const_used);
147
free(inv_remap_table);
148
149
if (c->Debug & RC_DBG_LOG)
150
rc_constants_print(&c->Program.Constants);
151
}
152
153