Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/panfrost/bifrost/bi_layout.c
4564 views
1
/*
2
* Copyright (C) 2020 Collabora, Ltd.
3
*
4
* Permission is hereby granted, free of charge, to any person obtaining a
5
* copy of this software and associated documentation files (the "Software"),
6
* to deal in the Software without restriction, including without limitation
7
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
8
* and/or sell copies of the Software, and to permit persons to whom the
9
* Software is 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
18
* THE 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 "compiler.h"
25
26
/* The scheduler packs multiple instructions into a clause (grouped as tuple),
27
* and the packing code takes in a clause and emits it to the wire. During
28
* scheduling, we need to lay out the instructions (tuples) and constants
29
* within the clause so constraints can be resolved during scheduling instead
30
* of failing packing. These routines will help building clauses from
31
* instructions so the scheduler can focus on the high-level algorithm, and
32
* manipulating clause layouts.
33
*/
34
35
/* Helper to see if a tuple can be inserted. We must satisfy the invariant:
36
*
37
* constant_count + tuple_count <= 13
38
*
39
* ...which is equivalent to the clause ending up with 8 or fewer quardwords.
40
* Inserting a tuple increases tuple_count by one, and if it reads a unique
41
* constant, it increases constant_count by one.
42
*/
43
44
bool
45
bi_can_insert_tuple(bi_clause *clause, bool constant)
46
{
47
unsigned constant_count = clause->constant_count + (constant ? 1 : 0);
48
unsigned tuple_count = clause->tuple_count + 1;
49
50
return (constant_count + tuple_count) <= 13;
51
}
52
53
/* Is embedded constant 0 packed for free in a clause with this many tuples? */
54
55
bool
56
bi_ec0_packed(unsigned tuple_count)
57
{
58
return (tuple_count == 3) ||
59
(tuple_count == 5) ||
60
(tuple_count == 6) ||
61
(tuple_count == 8);
62
}
63
64
/* Helper to calculate the number of quadwords in a clause. This is a function
65
* of the number of instructions and constants; it doesn't require actually
66
* packing, which is useful for branch offsets.
67
*
68
* Table of instruction count to instruction quadwords, per the packing
69
* algorithm, where * indicates a constant is packed for free:
70
*
71
* X | Y
72
* ---|---
73
* 1 | 1
74
* 2 | 2
75
* 3 | 3*
76
* 4 | 3
77
* 5 | 4*
78
* 6 | 5*
79
* 7 | 5
80
* 8 | 6*
81
*
82
* Y = { X if X <= 3
83
* { X - 1 if 4 <= X <= 6
84
* { X - 2 if 7 <= X <= 8
85
*
86
* and there is a constant for free if X is in {3, 5, 6, 8}. The remaining
87
* constants are packed two-by-two as constant quadwords.
88
*/
89
90
unsigned
91
bi_clause_quadwords(bi_clause *clause)
92
{
93
unsigned X = clause->tuple_count;
94
unsigned Y = X - ((X >= 7) ? 2 : (X >= 4) ? 1 : 0);
95
96
unsigned constants = clause->constant_count;
97
98
if ((X != 4) && (X != 7) && (X >= 3) && constants)
99
constants--;
100
101
return Y + DIV_ROUND_UP(constants, 2);
102
}
103
104
/* Measures the number of quadwords a branch jumps. Bifrost relative offsets
105
* are from the beginning of a clause so to jump forward we count the current
106
* clause length, but to jump backwards we do not. */
107
108
signed
109
bi_block_offset(bi_context *ctx, bi_clause *start, bi_block *target)
110
{
111
/* Signed since we might jump backwards */
112
signed ret = 0;
113
114
/* Determine if the block we're branching to is strictly greater in
115
* source order */
116
bool forwards = target->base.name > start->block->base.name;
117
118
if (forwards) {
119
/* We have to jump through this block from the start of this
120
* clause to the end */
121
bi_foreach_clause_in_block_from(start->block, clause, start) {
122
ret += bi_clause_quadwords(clause);
123
}
124
125
/* We then need to jump through every clause of every following
126
* block until the target */
127
bi_foreach_block_from(ctx, start->block, _blk) {
128
bi_block *blk = (bi_block *) _blk;
129
130
/* Don't double-count the first block */
131
if (blk == start->block)
132
continue;
133
134
/* End just before the target */
135
if (blk == target)
136
break;
137
138
/* Count every clause in the block */
139
bi_foreach_clause_in_block(blk, clause) {
140
ret += bi_clause_quadwords(clause);
141
}
142
}
143
} else {
144
/* We start at the beginning of the clause but have to jump
145
* through the clauses before us in the block */
146
bi_foreach_clause_in_block_from_rev(start->block, clause, start) {
147
if (clause == start)
148
continue;
149
150
ret -= bi_clause_quadwords(clause);
151
}
152
153
/* And jump back every clause of preceding blocks up through
154
* and including the target to get to the beginning of the
155
* target */
156
bi_foreach_block_from_rev(ctx, start->block, _blk) {
157
bi_block *blk = (bi_block *) _blk;
158
159
if (blk == start->block)
160
continue;
161
162
bi_foreach_clause_in_block(blk, clause) {
163
ret -= bi_clause_quadwords(clause);
164
}
165
166
/* End just after the target */
167
if (blk == target)
168
break;
169
}
170
}
171
172
return ret;
173
}
174
175