Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/panfrost/midgard/midgard_nir_algebraic.py
4564 views
1
#
2
# Copyright (C) 2018 Alyssa Rosenzweig
3
# Copyright (C) 2019-2020 Collabora, Ltd.
4
#
5
# Copyright (C) 2016 Intel Corporation
6
#
7
# Permission is hereby granted, free of charge, to any person obtaining a
8
# copy of this software and associated documentation files (the "Software"),
9
# to deal in the Software without restriction, including without limitation
10
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
11
# and/or sell copies of the Software, and to permit persons to whom the
12
# Software is furnished to do so, subject to the following conditions:
13
#
14
# The above copyright notice and this permission notice (including the next
15
# paragraph) shall be included in all copies or substantial portions of the
16
# Software.
17
#
18
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24
# IN THE SOFTWARE.
25
26
import argparse
27
import sys
28
import math
29
30
a = 'a'
31
b = 'b'
32
c = 'c'
33
34
algebraic = [
35
# Allows us to schedule as a multiply by 2
36
(('~fadd', ('fadd', a, b), a), ('fadd', ('fadd', a, a), b)),
37
]
38
39
algebraic_late = [
40
# ineg must be lowered late, but only for integers; floats will try to
41
# have modifiers attached... hence why this has to be here rather than
42
# a more standard lower_negate approach
43
44
(('ineg', a), ('isub', 0, a)),
45
46
# Likewise we want fsub lowered but not isub
47
(('fsub', a, b), ('fadd', a, ('fneg', b))),
48
49
# These two special-cases save space/an op than the actual csel op +
50
# scheduler flexibility
51
52
(('b32csel', a, 'b@32', 0), ('iand', a, b)),
53
(('b32csel', a, 0, 'b@32'), ('iand', ('inot', a), b)),
54
55
# Fuse sat_signed. This should probably be shared with Bifrost
56
(('~fmin', ('fmax', a, -1.0), 1.0), ('fsat_signed_mali', a)),
57
(('~fmax', ('fmin', a, 1.0), -1.0), ('fsat_signed_mali', a)),
58
59
# Fuse clamp_positive. This should probably be shared with Utgard/bifrost
60
(('fmax', a, 0.0), ('fclamp_pos_mali', a)),
61
62
(('ishl', 'a@16', b), ('u2u16', ('ishl', ('u2u32', a), b))),
63
(('ishr', 'a@16', b), ('i2i16', ('ishr', ('i2i32', a), b))),
64
(('ushr', 'a@16', b), ('u2u16', ('ushr', ('u2u32', a), b))),
65
66
(('ishl', 'a@8', b), ('u2u8', ('u2u16', ('ishl', ('u2u32', ('u2u16', a)), b)))),
67
(('ishr', 'a@8', b), ('i2i8', ('i2i16', ('ishr', ('i2i32', ('i2i16', a)), b)))),
68
(('ushr', 'a@8', b), ('u2u8', ('u2u16', ('ushr', ('u2u32', ('u2u16', a)), b)))),
69
70
# Canonical form. The scheduler will convert back if it makes sense.
71
(('fmul', a, 2.0), ('fadd', a, a))
72
]
73
74
# Size conversion is redundant to Midgard but needed for NIR, and writing this
75
# lowering in MIR would be painful without a competent builder, so eat the
76
# extra instruction
77
for sz in ('8', '16', '32'):
78
converted = ('u2u32', a) if sz != '32' else a
79
algebraic_late += [(('ufind_msb', 'a@' + sz), ('isub', 31, ('uclz', converted)))]
80
81
# Midgard is able to type convert down by only one "step" per instruction; if
82
# NIR wants more than one step, we need to break up into multiple instructions.
83
# Nevertheless, we can do both a size step and a floating/int step at once.
84
85
converts = []
86
87
for op in ('u2u', 'i2i', 'f2f', 'i2f', 'u2f', 'f2i', 'f2u'):
88
srcsz_max = 64
89
dstsz_max = 64
90
# 8 bit float doesn't exist
91
srcsz_min = 8 if op[0] != 'f' else 16
92
dstsz_min = 8 if op[2] != 'f' else 16
93
dstsz = dstsz_min
94
# Iterate over all possible destination and source sizes
95
while dstsz <= dstsz_max:
96
srcsz = srcsz_min
97
while srcsz <= srcsz_max:
98
# Size converter lowering is only needed if src and dst sizes are
99
# spaced by a factor > 2.
100
if srcsz != dstsz and (srcsz * 2 != dstsz and srcsz != dstsz * 2):
101
cursz = srcsz
102
rule = a
103
# When converting down we first do the type conversion followed
104
# by one or more size conversions. When converting up, we do
105
# the type conversion at the end. This way we don't have to
106
# deal with the fact that f2f8 doesn't exists.
107
sizeconvop = op[0] + '2' + op[0] if srcsz < dstsz else op[2] + '2' + op[2]
108
if srcsz > dstsz and op[0] != op[2]:
109
rule = (op + str(int(cursz)), rule)
110
while cursz != dstsz:
111
cursz = cursz / 2 if dstsz < srcsz else cursz * 2
112
rule = (sizeconvop + str(int(cursz)), rule)
113
if srcsz < dstsz and op[0] != op[2]:
114
rule = (op + str(int(cursz)), rule)
115
converts += [((op + str(int(dstsz)), 'a@' + str(int(srcsz))), rule)]
116
srcsz *= 2
117
dstsz *= 2
118
119
# Try to force constants to the right
120
constant_switch = [
121
# fge gets flipped to fle, so we invert to keep the order
122
(('fge', 'a', '#b'), (('inot', ('flt', a, b)))),
123
(('fge32', 'a', '#b'), (('inot', ('flt32', a, b)))),
124
(('ige32', 'a', '#b'), (('inot', ('ilt32', a, b)))),
125
(('uge32', 'a', '#b'), (('inot', ('ult32', a, b)))),
126
127
# fge gets mapped to fle with a flip
128
(('flt32', '#a', 'b'), ('inot', ('fge32', a, b))),
129
(('ilt32', '#a', 'b'), ('inot', ('ige32', a, b))),
130
(('ult32', '#a', 'b'), ('inot', ('uge32', a, b)))
131
]
132
133
# ..since the above switching happens after algebraic stuff is done
134
cancel_inot = [
135
(('inot', ('inot', a)), a)
136
]
137
138
# Midgard scales fsin/fcos arguments by pi.
139
# Pass must be run only once, after the main loop
140
141
scale_trig = [
142
(('fsin', a), ('fsin', ('fdiv', a, math.pi))),
143
(('fcos', a), ('fcos', ('fdiv', a, math.pi))),
144
]
145
146
def main():
147
parser = argparse.ArgumentParser()
148
parser.add_argument('-p', '--import-path', required=True)
149
args = parser.parse_args()
150
sys.path.insert(0, args.import_path)
151
run()
152
153
154
def run():
155
import nir_algebraic # pylint: disable=import-error
156
157
print('#include "midgard_nir.h"')
158
159
print(nir_algebraic.AlgebraicPass("midgard_nir_lower_algebraic_early",
160
algebraic).render())
161
162
print(nir_algebraic.AlgebraicPass("midgard_nir_lower_algebraic_late",
163
algebraic_late + converts + constant_switch).render())
164
165
print(nir_algebraic.AlgebraicPass("midgard_nir_scale_trig",
166
scale_trig).render())
167
168
print(nir_algebraic.AlgebraicPass("midgard_nir_cancel_inot",
169
cancel_inot).render())
170
171
172
if __name__ == '__main__':
173
main()
174
175